Android4.4增加了/system/priv-app/目录,那么它与/system/app/目录有什么差别?
本文主要从定义,作用,具体效果等方面进行分析。
有一些是网上没有介绍到的内容。
如果只是知道 priv-app 目录比 app目录权限大一点,但是不了解具体区别的可以看看。
4.4 之前没有/system/priv-app 目录,所有 /system/app 下的软件都能使用系统级的权限。
/system/priv-app和/system/app目录下的文件都是不可手动删除的。
手机被 root 后,通过 adb push 可以把 apk 推送到这两个目录,作为系统应用,用户无法删除。
/system/priv-app 中包含 Launcher,SystemUI, SettingsProvider 以及系统一些重要服务等系统的核心应用,这些应用能使用系统级的权限。
/system/app 中包含 一些基础应用和一些三方应用,比如日历,闹钟,天气,魔镜,音乐,这些有的是系统签名应用,有的不是系统签名应用,都是用户无法手动卸载的。
放到 /system/priv-app 下的应用比放到 /system/app 下的应用可以声明获得更多的权限,比如要使用系统限制的权限(比如: android.permission.WRITE_SECURE_SETTINGS),我们就需要把程序安装到 /system/priv-app 下。
从应用的运行角度来说,/system/priv-app 中的 service 是不能被 kill 掉的,就算通过 adb kill 掉后系统也会重新拉起。例如:
ActivityManager: Scheduling restart of crashed service com.xxx.xxx/.xxx.xxxin 1000ms
ActivityManager: Start proc 5668:com.xxx.xxx/u0a68 for restart com.xxx.xxx
好处是进程可以保持始终运行,并且能拿到最多的权限;坏处是无法正常升级,因为一被 kill 马上又被拉起来,并且升级完成后,再起来的还是旧版本的 service。
所以,我们的应用被预装到终端手机 ROM 中时,为了保活,并且尽量减少终端厂商的工作量,如果能解决升级的问题,对于终端厂商来说就只需要把应用 push 到 /system/priv-app 下就可以了。没有找到解决升级的办法,最终采用的方案往往是 push 到 /system/app,系统通过一个 service(如 phone)来 bind 我们的 service,一旦 disconnect 之后再来 bind,实现保活。
在 PackageManagerService 中对是否是 System App 的判断:
private static boolean isSystemApp(PackageParser.Package pkg) {
return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
}
private static boolean isSystemApp(PackageSetting ps) {
return (ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0;
}
具有 ApplicationInfo.FLAG_SYSTEM 标记的,被视为 System App。
(1)特定 shared uid 的 App
例如: shared uid 为 android.uid.system,android.uid.phone,android.uid.log,android.uid.nfc,android.uid.bluetooth,android.uid.shell。这类 App 都被赋予了 ApplicationInfo.FLAG_SYSTEM 标志。
(2)特定目录中的 App
特定目录包括:/vendor/overlay,/system/framework,/system/priv-app,/system/app,/vendor/app,/oem/app。这些目录中的 App,被视为 System App。
Privileged App,即「特权应用」,主要原因是此类特权 App 可以使用 protectionLevel 为 signatureOrSystem 或者 protectionLevel 为 signature|privileged 的权限。
从 PackageManagerService 的 isPrivilegedApp() 可以看出特权 App 是具有 ApplicationInfo.PRIVATE_FLAG_PRIVILEGED 标志的一类 App。
private static boolean isPrivilegedApp(PackageParser.Package pkg) {
return (pkg.applicationInfo.privateFlags &
ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0;
}
特权 App 首先必须是 System App,也就是说 System App 分为普通的 System App 和特权的 System App(System App = 普通 System App + 特权 App)。
一般来说普通的 System App 就是 /system/app 目录中的 App,
特权的 System App 就是 /system/priv-app 目录中的 App(priv-app 是 privileged app 的简写)。
特权 App 首先是 System App,然后要具有 ApplicationInfo.PRIVATE_FLAG_PRIVILEGED 标志。
有两类 App 属于 Privileged App(特权 App):
shared uid 为 android.uid.system,android.uid.phone,android.uid.log,android.uid.nfc,android.uid.bluetooth,android.uid.shell 的 App 被赋予了 privileged 的权限。这些 App 同时也是 System App。
/system/framework 和 /system/priv-app 目录下的 App 被赋予了 privileged 的权限。
其中 /system/framework 目录中的 apk,只是包含资源,不包含代码(dex)。
系统一些应用会使用到特殊权限,这时候要在系统配置一下否则系统会一直重启。
之前分析的缺少特殊权限系统一直重启的文章:
https://blog.csdn.net/wenzhi20102321/article/details/135424700
系统特殊权限有哪些?具体的可以看 framework\base\core\res\AndroidManifest.xml 的定义
部分私有权限如下:
<permission android:name="android.permission.READ_WIFI_CREDENTIAL"
android:protectionLevel="signature|privileged" />
<permission android:name="android.permission.TETHER_PRIVILEGED"
android:protectionLevel="signature|privileged" />
<permission android:name="android.permission.RECEIVE_WIFI_CREDENTIAL_CHANGE"
android:protectionLevel="signature|privileged" />
<permission android:name="android.permission.OVERRIDE_WIFI_CONFIG"
android:protectionLevel="signature|privileged|knownSigner"
android:knownCerts="@array/wifi_known_signers" />
。。。
从上面的特殊权限定义可以看到,protectionLevel 是包含等级是 privileged,
一般还需要 signature ,就是系统签名应用,所以有特殊权限的应用基本都是系统签名应用,
值得注意的是使用 privileged特殊权限的应用需要放在 /system/priv-app/ 目录才能正常运行。
apk对Setting数据库进行读写,该操作需要signatureOrSystem权限
Settings.Global.putInt(getContentResolver(), Settings.Global.WIFI_ON, 1); //获取wifi开关状态
测试情况:
(1)普通签名,将apk放在/system/priv-app/下面
测试结果:apk能够正常写入参数
(2)普通签名,将apk放在/system/app/下面
测试结果:apk直接闪退,提示没有权限
(3)对apk进行系统签名,放入到/system/app/下面
测试结果:apk可以正常写入参数
(3)对apk进行系统签名,使用Studio直接安装或者手动安装进去,目录是在/data/app/包名XXX/下面
测试结果:apk可以正常写入参数
结论:
/system/priv-app/下的apk不用系统签名,就能够获取signatureOrSystem权限。
/system/app/下的apk,要获取signatureOrSystem权限,必须用系统签名才行
安装在其他目录的apk使用系统签名也能获取到signatureOrSystem系统权限。
priv-app
和app
目录小结在Android系统中的system的priv-app
和app
目录是用于存放应用程序的两个不同的目录,具有一些区别:
1、 `priv-app`目录:`priv-app`是"privileged application"的缩写,意为特权应用程序。
`priv-app`目录用于存放一些系统级别的应用程序,这些应用程序通常具有更高的权限和特权,可以访问和执行一些敏感的系统操作。
这些应用程序通常是由设备制造商或系统开发者预装在系统分区中的。
因为这些应用程序具有更高的权限,所以它们可以访问一些普通应用程序无法访问的系统资源和功能。
2、 `app`目录:`app`目录用于存放普通的第三方应用程序,这些应用程序是由用户或开发者安装在设备上的。
这些应用程序通常没有特权访问系统资源的权限,只能在用户授权的范围内运行,并且受到操作系统的安全限制。
总的来说,priv-app
目录用于存放系统级别的特权应用程序,而app
目录用于存放普通的第三方应用程序。这种区分有助于确保系统级别的应用程序和普通应用程序之间的安全性和权限控制。
3、Android 源码中编译apk的脚步控制目录的代码
Android.bp:
//是否系统签名
certificate: "platform",
platform_apis: true,
//是否生成到priv-app目录
privileged: true,
Android.mk
# 设置系统权限和目录
LOCAL_CERTIFICATE := platform
LOCAL_PRIVATE_PLATFORM_APIS := true
# 设置是否编译在 priv-app,如果没有指定目录默认为 system/priv-app
LOCAL_PRIVILEGED_MODULE := true
(1)普通应用。只用到了普通权限,比如上网权限等等。
(2)system/app 系统应用,用来可以限制无法手动卸载,对系统权限没有要求的情况,无法调用系统api
(3)system/app 系统应用(未设置uid),无法手动卸载,可以调用部分系统api
(4)系统签名应用普通安装的方式,可以调用系统相关api,同时也可以被手动卸载
(5)system/priv-app 系统应用(设置uid),无法手动卸载,可以调用全部系统api,可以添加privileged特殊权限
了解到不同的权限需求,应用要安装/编译在什么目录心里就有个底了。