先来看一个实例,通过BLUETOOTH_STACK和DIAGNOSTIC permission获取linux的net_bt_stack和input guid权限
1.在app的AndroidManifest中声明如下permission,BLUETOOTH_STACK将应用加入到net_bt_stack用户组,可读写/dev/uinput设备,DIAGNOSTIC将应用加入到input组,可读写/dev/input/下的event设备
<uses-permission android:name="android.permission.BLUETOOTH_STACK" /> <uses-permission android:name="android.permission.DIAGNOSTIC" />
2.用platform签名给应用apk签名
以上两个权限都是要platform签名的
java -jar out/host/linux-x86/framework/signapk.jar build/target/product/security/platform.x509.pem build/target/product/security/platform.pk8 your_app.apk your_app_signed.apk
3.安装应用apk,不需要安装到/system/app目录,按照普通app安装方式即可
当app运行起来的时候,app已经是input、net_bt_stack组了,可以操作对应的linux设备文件
用ps查看app运行时的进程号PID,查看/proc/PID/status文件,可以看到app所属的guid
添加自定义permission获取guid
为了使用方便,可能需要自定义permission
比如我们需要添加一个叫做“android.permission.CONTROL”的permission,可以在frameworks/base/data/etc/platform.xml,添加
<permission name="android.permission.CONTROL" > <group gid="net_bt_stack" /> <group gid="input" /> </permission>
然后在app的AndroidManifest.xml中声明该permission,可参考frameworks/base/core/res/AndroidManifest.xml进行声明
<permission android:name="android.permission.CONTROL" android:protectionLevel="normal" />protectionLevel可以使用normal、dangerous、signature、system以及signature|system的组合 如果需要添加新的guid,可以修改system/core/include/private/android_filesystem_config.h 可以将app的源代码集成到package/app/下与android代码一起编译,也可以使用app生成好的apk集成 参考《如何预置Android 手机 APK》
如何将无源码的 APK 预置进系统? 1) 在 packages/apps 下面以需要预置的 APK 名字创建文件夹,以预置一个名为Test的APK为例 2) 将 Test.apk 放到 packages/apps/Test 下面 3) 在 packages/apps/Test 下面创建文件 Android.mk,文件内容如下:LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) # Module name should match apk name to be installed LOCAL_MODULE := Test LOCAL_MODULE_TAGS := optional LOCAL_SRC_FILES := $(LOCAL_MODULE).apk LOCAL_MODULE_CLASS := APPS LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX) LOCAL_CERTIFICATE := PRESIGNED include $(BUILD_PREBUILT)这样Test.apk将预制到/system/app/目录下 如果想预制到/data/data/下,可添加一行LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) # Module name should match apk name to be installed LOCAL_MODULE := Test LOCAL_MODULE_TAGS := optional LOCAL_SRC_FILES := $(LOCAL_MODULE).apk LOCAL_MODULE_CLASS := APPS LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX) LOCAL_CERTIFICATE := PRESIGNED LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS) include $(BUILD_PREBUILT)在cubieboard2的android源码中,只需要将apk添加到android/device/softwinner/wing-common/preinstallapk/目录即可
烧写image到设备上,运行我们的app,就能获取到net_bt_stack和input guid权限了(经测试,预制到/data/分区不能成功,在/system/下可以成功;也可以单独写一个声明permission的app,预制到/system/app/下,其他app使用这个permission就能成功了)
注意:通过修改android设备中的/etc/permissions/platform.xml,并将app安装到设备(push到/system/app/或者安装到/data/data/)的方式不能成功,出现如下错误:
W/PackageManager(2330): Removing dangling permission: android.permission.CONTROL from package null但通过在android源码中build的方式可以成功,可能跟没有清除数据有关
更新:直接修改android设备中的/etc/permissions/platform.xml,需要删除/data/system/packages.xml、/data/system/packages-backup.xml,重启之后重新扫描重构packages信息,这样就能成功获取permission对应的guid权限了 "packages.xml"在frameworks/base/services/java/com/android/server/pm/Settings.java中定义:
Settings(Context context, File dataDir) { mContext = context; mSystemDir = new File(dataDir, "system"); mSystemDir.mkdirs(); FileUtils.setPermissions(mSystemDir.toString(), FileUtils.S_IRWXU|FileUtils.S_IRWXG |FileUtils.S_IROTH|FileUtils.S_IXOTH, -1, -1); mSettingsFilename = new File(mSystemDir, "packages.xml"); mBackupSettingsFilename = new File(mSystemDir, "packages-backup.xml"); mPackageListFilename = new File(mSystemDir, "packages.list"); FileUtils.setPermissions(mPackageListFilename, 0660, SYSTEM_UID, PACKAGE_INFO_GID); // Deprecated: Needed for migration mStoppedPackagesFilename = new File(mSystemDir, "packages-stopped.xml"); mBackupStoppedPackagesFilename = new File(mSystemDir, "packages-stopped-backup.xml"); }
frameworks/base/services/java/com/android/server/pm/PackageManagerService.java中定义了isFirstBoot()
public PackageManagerService(Context context, boolean factoryTest, boolean onlyCore) {
…
mRestoredSettings = mSettings.readLPw(getUsers());
…
}
public boolean isFirstBoot() {
return !mRestoredSettings;
}
PMS会调用mSettings的readLPw,读取packages-backup.xml和packages.xml,如果不存在返回false,进而isFirstBoot()返回true
与抛出”Removing dangling permission”异常相关的代码位于PackageManagerService.java的updatePermissionsLPw()