【framework】framework中为systemserver添加权限

来源:互联网 发布:淘宝店铺主图多大尺寸 编辑:程序博客网 时间:2024/06/03 19:59

      之前以为在framework中不需要申请权限就可以直接使用,直到最近移植android6.0时,发现原来4.4上的代码移植到6.0上后无法正常使用,排查原因发现是在读写sdcard时因为没有读写权限导致出错,这才直到原来framework中的服务也是需要配置权限相关的东西的,只是方法和app中配置的方法不一样。如下记录该问题解决的方法:

1、测试代码

我在system server中自定义的服务中加入一段读写外置存储的测试代码,代码实现的功能非常简单,主要用三个方法构成,一个用于检测外置存储设备的挂载状态,一个用于读取显示外置存储中的文件列表,第三个方法用于向外置存储设备中创建一个测试文件,创建前如果存在就先删除。

private final static String[] sStorageArray = { "/mnt/extsd","/mnt/extsd2", "/mnt/usbhost/Storage01", "/mnt/usbhost/Storage02","/mnt/usbhost/Storage03" };@RequiresPermission(anyOf = {"android.permission.READ_EXTERNAL_STORAGE", "android.permission.WRITE_EXTERNAL_STORAGE"})private static void checkStorageState() {String state = Environment.getExtsdStorageState();Log.d(TAG, "getExtsdStorageState=" + state);state = Environment.getExtsd2StorageState();Log.d(TAG, "getExtsd2StorageState=" + state);state = Environment.getUsbStorageState();Log.d(TAG, "getUsbStorageState=" + state);state = Environment.getExtsd2StorageState();Log.d(TAG, "getExtsd2StorageState=" + state);}@RequiresPermission(anyOf = {"android.permission.READ_EXTERNAL_STORAGE", "android.permission.WRITE_EXTERNAL_STORAGE"})private static void listFile(final String home) {Log.d(TAG, "Home ="+home);File f = new File(home);if (null != f && f.exists()) {Log.d(TAG, "Home " + home + "  is avaiable!");File list[] = f.listFiles();if (null != list && 0 < list.length) {Log.d(TAG, "File list is not empty.");for (File tf : list) {if (null != tf) {Log.d(TAG, "File name=" + tf.getName());}}}else {Log.e(TAG, "File list is empty.");}} else {Log.e(TAG, "Home " + home + " is not avaiable.");}}@RequiresPermission(anyOf = {"android.permission.READ_EXTERNAL_STORAGE", "android.permission.WRITE_EXTERNAL_STORAGE"})private static void writeFile(final String home) {Log.d(TAG, "Home ="+home);File f = new File(home);if (null != f && f.exists()) {Log.d(TAG, "Home " + home + "  is avaiable!");final String fname = new StringBuilder().append(home).append(File.separatorChar).append("test.file").toString();File tf = new File(fname);try {tf.deleteOnExit();tf.createNewFile();Log.d(TAG, "Create "+fname+" success!");} catch (IOException e) {Log.e(TAG, "Write file:"+fname+" failed.");e.printStackTrace();}} else {Log.e(TAG, "Home " + home + " is not avaiable.");}}

2、问题描述

执行上述的测试代码后,发现获取存储设备状态成功,但是读取设备列表时始终为null,而创建文件时则直接抛出异常,异常原因是无权限。报错的主要日志如下:

01-01 08:00:50.661 E/UpdateManagerService( 2591): Write file:/mnt/usbhost/Storage02/test.file failed.01-01 08:00:50.661 W/System.err( 2591): java.io.IOException: open failed: EACCES (Permission denied)01-01 08:00:50.665 W/System.err( 2591):     at java.io.File.createNewFile(File.java:939)01-01 08:00:50.665 W/System.err( 2591):     at com.android.server.update.UpdateManagerService.writeFile(UpdateManagerService.java:77)01-01 08:00:50.665 W/System.err( 2591):     at com.android.server.update.UpdateManagerService.-wrap2(UpdateManagerService.java)01-01 08:00:50.665 W/System.err( 2591):     at com.android.server.update.UpdateManagerService$Lifecycle$1.run(UpdateManagerService.java:119)01-01 08:00:50.665 W/System.err( 2591):     at java.lang.Thread.run(Thread.java:818)01-01 08:00:50.665 W/System.err( 2591): Caused by: android.system.ErrnoException: open failed: EACCES (Permission denied)01-01 08:00:50.669 W/System.err( 2591):     at libcore.io.Posix.open(Native Method)01-01 08:00:50.670 W/System.err( 2591):     at libcore.io.BlockGuardOs.open(BlockGuardOs.java:186)01-01 08:00:50.670 W/System.err( 2591):     at java.io.File.createNewFile(File.java:932)01-01 08:00:50.670 W/System.err( 2591):     ... 4 more

3、问题分析

(1)、查看当前进程所属的用户组

通过上述错误日志,找到对应的进程号,如本例中的进程号为2591。进入/proc虚拟文件系统下进程的相关目录,查看进程的运行信息,如本例中的进程目录:

cd /proc/2951
通过如下命令查看进程的信息:

cat status
进程信息中有一个Groups属性,包含了当前进程所属的用户组,该进程仅仅拥有所属组所具备的权限。


上面的里面是我修改过具备读写外置存储设备后的status,修改之前Groups中不包含1015组。

(2)、查看所属用户组具备的权限

上一步得到的用户组都是int型,其定义在android/system/core/include/private/android_filesystem_config.h文件中,本文列出其中部分定义说明,具体的可以自行查阅相关代码。从代码中可以看到外置存储卡写权限属于AID_SDCARD_RW组,即1015(上面说过,我在修改前system_server是不具备1015的用户组的,所以导致读写外置存储卡时抛出了权限问题)。

/* This is the master Users and Groups config for the platform. * DO NOT EVER RENUMBER */#define AID_ROOT             0  /* traditional unix root user */#define AID_SYSTEM        1000  /* system server */#define AID_RADIO         1001  /* telephony subsystem, RIL */#define AID_BLUETOOTH     1002  /* bluetooth subsystem */#define AID_GRAPHICS      1003  /* graphics devices */#define AID_INPUT         1004  /* input devices */#define AID_AUDIO         1005  /* audio devices */#define AID_CAMERA        1006  /* camera devices */#define AID_LOG           1007  /* log devices */#define AID_COMPASS       1008  /* compass device */#define AID_MOUNT         1009  /* mountd socket */#define AID_WIFI          1010  /* wifi subsystem */#define AID_ADB           1011  /* android debug bridge (adbd) */#define AID_INSTALL       1012  /* group for installing packages */#define AID_MEDIA         1013  /* mediaserver process */#define AID_DHCP          1014  /* dhcp client */#define AID_SDCARD_RW     1015  /* external storage write access */#define AID_VPN           1016  /* vpn system */#define AID_KEYSTORE      1017  /* keystore subsystem */#define AID_USB           1018  /* USB devices */#define AID_DRM           1019  /* DRM server */#define AID_MDNSR         1020  /* MulticastDNSResponder (service discovery) */#define AID_GPS           1021  /* GPS daemon */#define AID_UNUSED1       1022  /* deprecated, DO NOT USE */#define AID_MEDIA_RW      1023  /* internal media storage write access */#define AID_MTP           1024  /* MTP USB driver access */#define AID_UNUSED2       1025  /* deprecated, DO NOT USE */#define AID_DRMRPC        1026  /* group for drm rpc */#define AID_NFC           1027  /* nfc subsystem */#define AID_SDCARD_R      1028  /* external storage read access */#define AID_CLAT          1029  /* clat part of nat464 */#define AID_LOOP_RADIO    1030  /* loop radio devices */#define AID_MEDIA_DRM     1031  /* MediaDrm plugins */#define AID_PACKAGE_INFO  1032  /* access to installed package details */#define AID_SDCARD_PICS   1033  /* external storage photos access */#define AID_SDCARD_AV     1034  /* external storage audio/video access */#define AID_SDCARD_ALL    1035  /* access all users external storage */#define AID_LOGD          1036  /* log daemon */#define AID_SHARED_RELRO  1037  /* creator of shared GNU RELRO files */#define AID_SHELL         2000  /* adb and debug shell user */#define AID_CACHE         2001  /* cache access */#define AID_DIAG          2002  /* access to diagnostic resources *//* The range 2900-2999 is reserved for OEM, and must never be * used here */#define AID_OEM_RESERVED_START 2900#define AID_OEM_RESERVED_END   2999/* The 3000 series are intended for use as supplemental group id's only. * They indicate special Android capabilities that the kernel is aware of. */#define AID_NET_BT_ADMIN  3001  /* bluetooth: create any socket */#define AID_NET_BT        3002  /* bluetooth: create sco, rfcomm or l2cap sockets */#define AID_INET          3003  /* can create AF_INET and AF_INET6 sockets */#define AID_NET_RAW       3004  /* can create raw INET sockets */#define AID_NET_ADMIN     3005  /* can configure interfaces and routing tables. */#define AID_NET_BW_STATS  3006  /* read bandwidth statistics */#define AID_NET_BW_ACCT   3007  /* change bandwidth statistics accounting */#define AID_NET_BT_STACK  3008  /* bluetooth: access config files */#define AID_EVERYBODY     9997  /* shared between all apps in the same profile */#define AID_MISC          9998  /* access to misc storage */#define AID_NOBODY        9999#define AID_APP          10000  /* first app user */#define AID_ISOLATED_START 99000 /* start of uids for fully isolated sandboxed processes */#define AID_ISOLATED_END   99999 /* end of uids for fully isolated sandboxed processes */#define AID_USER        100000  /* offset for uid ranges for each user */#define AID_SHARED_GID_START 50000 /* start of gids for apps in each user to share */#define AID_SHARED_GID_END   59999 /* start of gids for apps in each user to share */
(3)、查看system_server启动参数

system_server是由ZygoteInit类负责初始化和启动的,相关的代码在sdk的android/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java文件中。其中关键的启动代码如下。从代码中可以看到,在启动sysetm_server时通过--setgroups为其设置了所属用户组。

    private static boolean startSystemServer(String abiList, String socketName)            throws MethodAndArgsCaller, RuntimeException {        long capabilities = posixCapabilitiesAsBits(            OsConstants.CAP_BLOCK_SUSPEND,            OsConstants.CAP_KILL,            OsConstants.CAP_NET_ADMIN,            OsConstants.CAP_NET_BIND_SERVICE,            OsConstants.CAP_NET_BROADCAST,            OsConstants.CAP_NET_RAW,            OsConstants.CAP_SYS_MODULE,            OsConstants.CAP_SYS_NICE,            OsConstants.CAP_SYS_RESOURCE,            OsConstants.CAP_SYS_TIME,            OsConstants.CAP_SYS_TTY_CONFIG        );        /* Hardcoded command line to start the system server */        String args[] = {            "--setuid=1000",            "--setgid=1000",            "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1015,1018,1021,1032,3001,3002,3003,3006,3007",            "--capabilities=" + capabilities + "," + capabilities,            "--nice-name=system_server",            "--runtime-args",            "com.android.server.SystemServer",        };        ZygoteConnection.Arguments parsedArgs = null;        int pid;        try {            parsedArgs = new ZygoteConnection.Arguments(args);            ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);            ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);            /* Request to fork the system server process */            pid = Zygote.forkSystemServer(                    parsedArgs.uid, parsedArgs.gid,                    parsedArgs.gids,                    parsedArgs.debugFlags,                    null,                    parsedArgs.permittedCapabilities,                    parsedArgs.effectiveCapabilities);        } catch (IllegalArgumentException ex) {            throw new RuntimeException(ex);        }        /* For child process */        if (pid == 0) {            if (hasSecondZygote(abiList)) {                waitForSecondaryZygote(socketName);            }            handleSystemServerProcess(parsedArgs);        }        return true;    }
注意:上述代码已经是我修改后(即添加用户组1015后)的代码,此时编译的system_server已经具备了读写外置存储的权限。

4、解决方法

在第三步的“问题分析”的最中其实已经给出了解决办法,但是这里还是重新说明下。问题总结主要几个方面:

(1)、查看进程当前所属的组;

(2)、查看所需权限所属的组;

(3)、比对当前进程是否属于需要权限的组;

(4)、修改启动参数添加组;

故,本文最后修改了ZygoteInit.java类,然后在--setgroups参数中增加了1015用户组。

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 我的手机收不到短信通知怎么办? 淘宝卖家发货物流单号写错了怎么办 商铺买东西不给调换大小怎么办 圆通快递物流信息一直没更新怎么办 中通快递三天没更新物流信息怎么办 快递已经到了物流信息不更新怎么办 天天快递查询不更新物流信息怎么办 买车下个月分期全部付清怎么办手续 天猫客服介入以后商家不退款怎么办 淘宝上买代购奢侈品买到假货怎么办 淘宝退货卖家收到货拒绝退款怎么办 没收到货但申请了退货退款怎么办 小米商城预约中德手机没货怎么办 电脑用百度网盘下载速度超慢怎么办 ios网盘下载速度太慢怎么办 小米手机4x卡机了怎么办 小米手机4x屏幕点不动了怎么办 苹果手机连接u盘没反应怎么办 苹果官网储蓄卡分期额度不够怎么办 京东买东西发票信息填写错了怎么办 华为v9手机激活密码忘了怎么办 公司报销发票纸质的丢了怎么办 在京东上买的小天才手表坏了怎么办 美亚买东西过几天降价了怎么办 天猫买东西退款后又不想退了怎么办 自己写错了地址快递被签收了怎么办 在天猫购买东西不发货怎么办 在天猫买了东西不给我发货怎么办 天猫退货卖家收到货不退款怎么办 唯品会的账号找不回来了怎么办 从网上买的沙发物流超级慢怎么办 三星c5手机玩王者荣耀卡怎么办 买手机送话费的卡不想用了怎么办 到银行存钱被骗买保险了怎么办 去银行存钱被骗买了保险怎么办 京东申请退款后卖家又发货了怎么办 苹果6s没有4g网怎么办 花呗分期付款买手机额度不够怎么办 手机天猫不支持购买淘宝商品怎么办 天猫国际购买商品狠盾怎么办 在微信上微拍堂买东西被骗了怎么办