Andrid 7.1 启动init.rc中自定义service

本文详细介绍了在RK3288平台搭载Android7.12系统下,解决新增自定义服务无法启动的问题过程。通过调整init.rc配置,修改SELinux策略,成功启动了自定义服务。关键步骤包括在Android.mk和infoservice.cpp中定义服务,在init.rc中添加服务,并通过SELinux策略调整确保服务正常运行。

平台:

RK3288 + Android7.12

问题:

无法启动init.rc中新增的服务.

步骤:

新增服务

|–system/extras/info-service/Android.mk

LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

LOCAL_CFLAGS := -std=c11 -Wall
#-Wmacro-redefined -Wunused-parameter -Wunused-variable
LOCAL_SRC_FILES:= infoservice.cpp
LOCAL_MODULE:= infoservice
LOCAL_SHARED_LIBRARIES := \
    libcutils \
    liblog \
	libc \
	libm
LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
LOCAL_MODULE_TAGS := debug

include $(BUILD_EXECUTABLE)

|–system/extras/info-service/infoservice.cpp

#define LOG_TAG "InfoService"
#include <errno.h>
#include <error.h>
#include <getopt.h>
#include <paths.h>
#include <pwd.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <utils/Log.h>

char configFile[] = "/data/system/device.cfg";
char profile[] = "/data/profile";

int main(int argc, char** argv) {
    ALOGI("start Info Service");
}

在init.rc中添服务
|–device/rockchip/rk3288/init.rk3288.rc

 on verity-logging
     exec u:r:slideshow:s0 -- /sbin/slideshow warning/verity_red_1 warning/verity_red_2
+
+service infoservice /system/xbin/infoservice
+    class core
+    user root
+    group root system
+    disabled
+    oneshot
尝试启动服务:

setprop ctl.start infoservice
服务无法启动!

查看LOG:
[   58.364922] init: ALog Starting 'infoservice'...
[   58.365266] init: Service infoservice does not have a SELinux domain defined.

SELinux无法找到自定义服务的域定义.

解决:

参考bootanimation的源码:

新增文件:

|–system/sepolicy/infoservice.te

type infoservice, domain;
type infoservice_exec, exec_type, file_type;

init_daemon_domain(infoservice)
修改文件如下:

|–system/sepolicy/file_contexts

 /system/bin/sh         --      u:object_r:shell_exec:s0
 /system/bin/run-as     --      u:object_r:runas_exec:s0
 /system/bin/bootanimation u:object_r:bootanim_exec:s0
+/system/xbin/infoservice u:object_r:infoservice_exec:s0
 /system/bin/bootstat           u:object_r:bootstat_exec:s0
 /system/bin/app_process32      u:object_r:zygote_exec:s0
 /system/bin/app_process64      u:object_r:zygote_exec:s0

|–system/sepolicy/property.te

 type vold_prop, property_type, core_property_type;
 type wifi_log_prop, property_type, log_property_type;
 type ctl_bootanim_prop, property_type;
+type ctl_infoservice_prop, property_type;
 type ctl_default_prop, property_type;
 type ctl_dumpstate_prop, property_type;
 type ctl_fuse_prop, property_type;

|–system/sepolicy/property_contexts

 # ctl properties
 ctl.bootanim            u:object_r:ctl_bootanim_prop:s0
+ctl.infoservice         u:object_r:ctl_infoservice_prop:s0
 ctl.dumpstate           u:object_r:ctl_dumpstate_prop:s0
 ctl.fuse_               u:object_r:ctl_fuse_prop:s0
 ctl.mdnsd               u:object_r:ctl_mdnsd_prop:s0

编译system/sepolicy, 打包烧录, 问题解决!

<think>我们正在分析Android 7.1系统中`mBar.interceptTouchEvent(event)`方法的作用及使用方法。根据用户提供的引用片段,我们可以从引用[2]和引用[3]中获取关键信息。 引用[2]展示了一个`onTouchEvent`方法的实现,其中调用了`mBar.interceptTouchEvent(event)`: ```java @Override public boolean onTouchEvent(MotionEvent event) { if(Settings.System.getInt(mContext.getContentResolver(), "systemui",0)!=0){ return false; } boolean barConsumedEvent = mBar.interceptTouchEvent(event); // ... 调试日志记录 return barConsumedEvent || super.onTouchEvent(event); } ``` 这段代码说明: - `mBar.interceptTouchEvent(event)`用于处理触摸事件,并返回一个布尔值表示事件是否被消费(即处理)。 - 如果事件被`mBar`消费(`barConsumedEvent`为`true`),则直接返回`true`,表示事件已被处理;否则,会调用`super.onTouchEvent(event)`。 引用[3]提到了`mBar`的初始化过程(在导航栏创建过程中): ```java private void addNavigationBar(){ if(mNavigationBarView == null) return; prepareNavigationBarview(); // 这里会初始化mBar(即NavigationBarView)的事件监听 mWindowManager.addView(mNavigationBarView,getNavigationBarLayoutParams()); } ``` 在`prepareNavigationBarView()`方法中,会为导航栏中的虚拟按键设置触摸事件监听器。因此,`mBar`很可能是一个`NavigationBarView`对象,而`interceptTouchEvent`是它的一个方法。 结合以上信息,我们可以推断: 1. `mBar`是`NavigationBarView`的实例(在SystemUI中代表导航栏)。 2. `interceptTouchEvent`方法用于拦截并处理触摸事件,判断导航栏是否应该消费该事件(例如,用户点击了返回键、Home键等虚拟按键)。 3. 在`onTouchEvent`中调用`mBar.interceptTouchEvent(event)`,将触摸事件传递给导航栏处理,并根据返回值决定是否继续传递事件。 **方法详解**: - **作用**:`mBar.interceptTouchEvent(event)`是导航栏视图(`NavigationBarView`)中用于处理触摸事件的核心方法。它负责将触摸事件分发给导航栏中的各个子视图(如虚拟按键),并判断触摸事件是否发生在导航栏的区域内且被某个子视图消费。 - **返回值**:如果触摸事件被导航栏中的某个子视图消费(例如用户按下了虚拟按键),则返回`true`;否则返回`false`。 - **使用场景**:在自定义视图(如`StatusBarView`)的`onTouchEvent`中,如果需要将触摸事件传递给导航栏处理,可以调用此方法。如果导航栏消费了事件,则无需再处理;否则,可以继续执行默认的触摸事件处理逻辑。 **注意**:在引用[2]的代码中,还有一个条件判断`Settings.System.getInt(...)`,它检查系统设置中是否禁用了SystemUI(例如通过开发者选项)。如果禁用了,则直接返回`false`,即不处理任何触摸事件。 **总结**: `mBar.interceptTouchEvent(event)`是SystemUI中导航栏处理触摸事件的关键方法。在自定义触摸事件处理时,可以通过调用此方法将事件传递给导航栏,并根据返回值决定后续处理逻辑。 §§相关问题§§ 1. Android SystemUI中导航栏的触摸事件处理流程是怎样的? 2. 如何自定义Android导航栏的触摸事件处理逻辑? 3.Android系统开发中,如何调试触摸事件的分发过程?</think>### Android 7.1 `mBar.interceptTouchEvent(event)` 方法详解 #### 1. **方法作用** `mBar.interceptTouchEvent(event)` 是 Android SystemUI 中处理**导航栏触摸事件拦截**的核心方法: - **核心功能**:拦截并处理导航栏区域的触摸事件(如虚拟按键点击、滑动操作) - **返回值逻辑**: - 返回 `true`:表示事件已被导航栏消费,不再向下传递 - 返回 `false`:表示事件未处理,由后续视图继续处理 - **典型场景**:处理返回键、Home键、最近任务键等虚拟按键的触摸事件[^3] #### 2. **实现原理** 在源码中(参考引用[2]的实现): ```java @Override public boolean onTouchEvent(MotionEvent event) { // 系统设置检查(如开发者选项) if(Settings.System.getInt(mContext.getContentResolver(), "systemui",0)!=0){ return false; } // 核心拦截逻辑 boolean barConsumedEvent = mBar.interceptTouchEvent(event); // 调试日志记录 if (DEBUG_GESTURES) { if (event.getActionMasked() != MotionEvent.ACTION_MOVE) { EventLog.writeEvent(...); // 记录触摸事件 } } return barConsumedEvent || super.onTouchEvent(event); } ``` 关键点: 1. **`mBar` 对象**:指向 `NavigationBarView` 实例(导航栏根视图)[^3] 2. **事件决策**:优先由导航栏处理事件,未处理时才调用 `super.onTouchEvent()` 3. **性能优化**:跳过 `ACTION_MOVE` 事件的日志记录减少开销 #### 3. **调用流程** 1. **导航栏创建**:在 `PhoneStatusBar.addNavigationBar()` 中初始化导航栏视图[^3] ```java private void addNavigationBar() { if (mNavigationBarView == null) return; prepareNavigationBarView(); // 初始化触摸监听器 mWindowManager.addView(mNavigationBarView, ...); // 添加窗口 } ``` 2. **触摸事件传递**: ```mermaid graph TD A[屏幕触摸事件] --> B{StatusBarView.onTouchEvent} B --> C[调用 mBar.interceptTouchEvent] C --> D{NavigationBarView 处理} D -->|是| E[生成 KeyEvent 或手势响应] D -->|否| F[调用 super.onTouchEvent] ``` #### 4. **实际应用场景** 1. **虚拟按键响应**:将触摸事件转化为按键事件(如 `KEYCODE_BACK`) 2. **手势导航**:处理滑动操作(如上滑返回桌面) 3. **输入事件拦截**:在特殊场景(如全屏游戏)中屏蔽导航栏触摸 4. **多窗口模式**:调整触摸事件分发策略[^4] #### 5. **自定义扩展** 如需修改行为,可重写相关方法: ```java // 示例:扩展触摸处理逻辑 @Override public boolean interceptTouchEvent(MotionEvent event) { if (isCustomGesture(event)) { handleCustomGesture(); // 自定义手势 return true; // 拦截事件 } return super.interceptTouchEvent(event); // 默认处理 } ``` > **注意**:在 Android 7.1 中,该方法位于 `com.android.systemui.statusbar.phone.NavigationBarView` 类中,实际实现涉及与 `PhoneStatusBar` 和 `CommandQueue` 的交互[^3][^4]。
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值