system apk

简介: system apk

1 哪些app属于system app?

为了区分privilege app和system app,这里先说明system app是什么,避免之后的讨论概念混乱。

在PackageManagerService中对是否是system app的判断:

具有ApplicationInfo.FLAG_SYSTEM标记的,被视为System app。

frameworks\base\services\core\java\com\android\server\pm\PackageManagerService.java

final boolean isSystem = isSystemApp(pkgSetting) || isUpdatedSystemApp(pkgSetting);
    private static boolean isSystemApp(PackageSetting ps) {
        return (ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0;
    }
 
    private static boolean isUpdatedSystemApp(PackageSetting ps) {
        return (ps.pkgFlags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0;
    }

有两类app属于System app:

1.1 第一类System app: 特定的shared uid的app 属于system 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标志。在PackageManagerService的构造方法中,代码如下:

        mSettings.addSharedUserLPw("android.uid.system", Process.SYSTEM_UID,
                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
        mSettings.addSharedUserLPw("android.uid.phone", RADIO_UID,
                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
        mSettings.addSharedUserLPw("android.uid.log", LOG_UID,
                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
        mSettings.addSharedUserLPw("android.uid.nfc", NFC_UID,
                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
        mSettings.addSharedUserLPw("android.uid.bluetooth", BLUETOOTH_UID,
                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
        mSettings.addSharedUserLPw("android.uid.shell", SHELL_UID,
                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
        mSettings.addSharedUserLPw("android.uid.se", SE_UID,
                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
        mSettings.addSharedUserLPw("android.uid.networkstack", NETWORKSTACK_UID,
                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);

1.2 第二类System app: 特定目录中的app属于system app

特定目录包括:/vendor/overlay,/system/framework,/system/priv-app,/system/app,/vendor/app,/oem/app。这些目录中的app,被视为system app。

在PackageManagerService的构造方法中,代码如下:

// /vendor/overlay folder
File vendorOverlayDir = new File(VENDOR_OVERLAY_DIR);
scanDirLI(vendorOverlayDir, PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags | SCAN_TRUSTED_OVERLAY, 0);
 
// Find base frameworks (resource packages without code). /system/framework folder
File frameworkDir = new File(Environment.getRootDirectory(), "framework");
scanDirLI(frameworkDir, PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR
| PackageParser.PARSE_IS_PRIVILEGED,
scanFlags | SCAN_NO_DEX, 0);
 
// Collected privileged system packages. /system/priv-app folder
final File privilegedAppDir = new File(Environment.getRootDirectory(), "priv-app");
scanDirLI(privilegedAppDir, PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR
| PackageParser.PARSE_IS_PRIVILEGED, scanFlags, 0);
 
// Collect ordinary system packages. /system/app folder
final File systemAppDir = new File(Environment.getRootDirectory(), "app");
scanDirLI(systemAppDir, PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
 
// Collect all vendor packages.
File vendorAppDir = new File("/vendor/app");
scanDirLI(vendorAppDir, PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
 
// Collect all OEM packages. /oem/app folder
final File oemAppDir = new File(Environment.getOemDirectory(), "app");
scanDirLI(oemAppDir, PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);

2 什么是privileged app(特权app)

注:privileged app,在本文中称之为 特权app,主要原因是此类特权app可以使用protectionLevel为signatureOrSystem或者protectionLevel为signature|privileged的权限。

从PackageManagerService的isPrivilegedApp()可以看出特权app是具有ApplicationInfo.PRIVATE_FLAG_PRIVILEGED标志的一类app。

resolveInfo.activityInfo.applicationInfo.isPrivilegedApp()
frameworks/base/core/java/android/content/pm/ApplicationInfo.java
public boolean isPrivilegedApp() {
        return (privateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0;
    }
 

特权app首先必须是System app。也就是说 System app分为普通的system app和特权的system app。

直观的(但不准确严谨)说,普通的system app就是/system/app目录中的app,特权的system app就是/system/priv-app目录中的app。

区分普通system app和特权app的目的是澄清这个概念:"signatureOrSystem"权限中的System不是为普通system app提供的,而是只有特权app能够使用。

所以,当我们说起system app时,通常指具有特定uid和特定目录中的app,包含了普通的system app和特权app。当我们说起有访问System权限或者privileged权限的app时,通常指特权app。

3 哪些app属于privileged app(特权app)?

特权app首先是System app,然后要具有ApplicationInfo.PRIVATE_FLAG_PRIVILEGED标志。

有两类app属于privileged app(特权app):

参考PackageManagerService的构造方法。

3.1 第一类privileged app: 特定uid的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。

代码如下:

        mSettings.addSharedUserLPw("android.uid.system", Process.SYSTEM_UID,
                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
        mSettings.addSharedUserLPw("android.uid.phone", RADIO_UID,
                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
        mSettings.addSharedUserLPw("android.uid.log", LOG_UID,
                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
        mSettings.addSharedUserLPw("android.uid.nfc", NFC_UID,
                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
        mSettings.addSharedUserLPw("android.uid.bluetooth", BLUETOOTH_UID,
                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
        mSettings.addSharedUserLPw("android.uid.shell", SHELL_UID,
                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
        mSettings.addSharedUserLPw("android.uid.se", SE_UID,
                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
        mSettings.addSharedUserLPw("android.uid.networkstack", NETWORKSTACK_UID,
                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);

3.2 第二类privileged app:/system/framework和/system/priv-app目录下的app

/system/framework和/system/priv-app目录下的app被赋予了privileged的权限。

其中/system/framework目录中的apk,只是包含资源,不包含代码(dex)。

/ PackageManagerService的构造方法
// /system/framework
File frameworkDir = new File(Environment.getRootDirectory(), "framework");
scanDirLI(frameworkDir, PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR
| PackageParser.PARSE_IS_PRIVILEGED,
scanFlags | SCAN_NO_DEX, 0);
 
// /system/priv-app
final File privilegedAppDir = new File(Environment.getRootDirectory(), "priv-app");
scanDirLI(privilegedAppDir, PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR
| PackageParser.PARSE_IS_PRIVILEGED, scanFlags, 0);
 
PackageParser.PARSE_IS_PRIVILEGED标志最终会转换为Package的ApplicationInfo.PRIVATE_FLAG_PRIVILEGED标志。大概的代码流程,如下:
 
scanDirLI(PackageParser.PARSE_IS_PRIVILEGED)
 
-> scanPackageLI(file, parseFlags | PackageParser.PARSE_MUST_BE_APK, scanFlags, currentTime, null);
 
-> PackageParser.Package scannedPkg = scanPackageLI(pkg, parseFlags, scanFlags | SCAN_UPDATE_SIGNATURE, currentTime, user);
 
-> final PackageParser.Package res = scanPackageDirtyLI(pkg, parseFlags, scanFlags, currentTime, user);
 
-> scanPackageDirtyLI()中
if ((parseFlags & PackageParser.PARSE_IS_PRIVILEGED) != 0) {
pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
}

4.1 验证某个app是否获得了某个权限的方法

可以用下面2个命令来验证:

adb shell dumpsys package permission <权限名>

adb shell dumpsys package <包名>

 

其中,adb shell dumpsys package permission <权限名>可以查看某个权限是谁声明的,谁使用了。

adb shell dumpsys package <包名>可以看到某个app是否获得了某个权限。


哪些app可以使用某app提供的signature权限或signatureOrSystem权限?


如果App A声明了signatureOrSystem权限,即android:protectionLevel="signature|privileged"或者android:protectionLevel="signatureOrSystem",则可以使用该权限的app包括:

(1)与App A有相同签名的app

(2)与系统签名相同的app,即与厂商签名(厂商ROM中的系统app签名)相同的app

(3)在/system/priv-app目录中的app,不管是否满足(1)和(2)的条件。即任意app只要放到了/system/priv-app就可以使用App A的signatureOrSystem级别的权限。


如果App A声明了signature权限,即android:protectionLevel="signature",则可以使用该权限的app包括:

(1)与App A有相同签名的app

(2)与系统签名相同的app,即与厂商签名(厂商ROM中的系统app签名)相同的app

注意:与系统签名相同,即与厂商签名相同,这是指厂商推出的app,这些app有很大的访问权限。


目录
相关文章
|
Android开发
我的Android进阶之旅------&gt;解决如下错误failed to copy 'Settings2.apk' to '/system/app//Settings2.apk': Read-only
push apk的时候报错 ouyangpeng@oyp-ubuntu:~/apk升级$ adb push Settings2.apk /system/app/ failed to copy 'Settings2.
1196 0
|
6月前
|
Android开发 开发者
Android Split APK介绍
【2月更文挑战第5天】
|
数据安全/隐私保护 Android开发
Android bundetool 转换 .aab 为apk 步骤
Android bundetool 转换 .aab 为apk 步骤
555 0
Android bundetool 转换 .aab 为apk 步骤
|
SQL 人工智能 算法
Android性能优化之应用瘦身(APK瘦身)
Android性能优化之应用瘦身(APK瘦身)
|
5月前
|
Android开发
Android Gradle开发—脚本实现自动打包后复制一份APK文件,并修改APK名称,到指定目录作备份
Android Gradle开发—脚本实现自动打包后复制一份APK文件,并修改APK名称,到指定目录作备份
257 0
|
6月前
|
XML API Android开发
android S 上 安装apk出现android.os.FileUriExposedException
android S 上 安装apk出现android.os.FileUriExposedException
72 6
|
6月前
|
设计模式 缓存 Java
补齐Android技能树——从AGP构建过程到APK打包过程,安卓rxjava面试
补齐Android技能树——从AGP构建过程到APK打包过程,安卓rxjava面试
|
6月前
|
XML 存储 开发工具
Android Studio如何将APK下载
【5月更文挑战第16天】
|
6月前
|
XML Dart Java
Flutter插件开发之APK自动安装,字节跳动Android岗面试题
Flutter插件开发之APK自动安装,字节跳动Android岗面试题
|
6月前
|
Android开发
Android 高通平台集成无源码apk示例
Android 高通平台集成无源码apk示例
92 0