首页
社区
课程
招聘
[原创]改机系列 1 -为所有应用添加权限
发表于: 2023-8-14 14:49 4362

[原创]改机系列 1 -为所有应用添加权限

2023-8-14 14:49
4362

改机系列 1 -为所有应用添加权限
今天我们来说下,安卓应用在 app 中被解析,主要涉及到了 Package Manager Service(pms)PMS 是 Android 系统中的关键组件,负责处理与应用程序生命周期和权限相关的所有事务。那么,它是怎么完成一个 apk 解析的呢?它又是如何工作的?在这篇文章里,我们一起来看看。

学习目录
1.源码分析 pms 的加载流程
2.为安装的所有 app 添加权限
源码分析 pms 的加载流程
• 本文使用的是 aosp 安卓 11 的源码进行分析的;
从一个手机 fastboot 到手机内核启动再到 init 进程启动,这里边涉及到流程非常复杂,等后续会单独出一篇文章来讲,init 进程执行一系列的脚本包括 init.rc 和导入的/system/etc/init/hw/init.${ro.zygote}.rc 配置等文件,来启动一些服务和进程,启动的进程就包括我们经常说的 app_process64 进程,接着到 zygoteinit.java 中的 main 函数 Zygote 进程的入口点。

service zygote_secondary /system/bin/app_process64 -Xzygote /system/bin --zygote --socket-name=zygote_secondary
class main
priority -20
user root
group root readproc reserved_disk
socket zygote_secondary stream 660 root system
socket usap_pool_secondary stream 660 root system
onrestart restart zygote
writepid /dev/cpuset/foreground/tasks
zygoteServer = new ZygoteServer(isPrimaryZygote);
if (startSystemServer) {
Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
// {@code r == null} in the parent (zygote) process, and {@code r != null} in the
// child (system_server) process.
if (r != null) {
r.run();
return;
}
}

1
2
3
4
5
6
7
8
9
10
11
           /* Request to fork the system server process */
    pid = Zygote.forkSystemServer(
            parsedArgs.mUid, parsedArgs.mGid,
            parsedArgs.mGids,
            parsedArgs.mRuntimeFlags,
            null,
            parsedArgs.mPermittedCapabilities,
            parsedArgs.mEffectiveCapabilities);
} catch (IllegalArgumentException ex) {
    throw new RuntimeException(ex);
}

在 new zygoteserver 中请求启动 system server 进程以及涉及 new LocalServerSocket(fd);LocalServerSocket 用于在同一设备上的进程之间进行通信。这意味着它通常更安全(不暴露于外部攻击)且更高效(无需网络协议的开销)。

1
2
3
4
5
6
7
8
9
10
11
           /* Request to fork the system server process */
    pid = Zygote.forkSystemServer(
            parsedArgs.mUid, parsedArgs.mGid,
            parsedArgs.mGids,
            parsedArgs.mRuntimeFlags,
            null,
            parsedArgs.mPermittedCapabilities,
            parsedArgs.mEffectiveCapabilities);
} catch (IllegalArgumentException ex) {
    throw new RuntimeException(ex);
}

这里我们就请求启动 system server 进程 来到 systemserver.java 代码区域

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
public static void main(String[] args) {
    new SystemServer().run();
}
 
public SystemServer() {
    // Check for factory test mode.
    mFactoryTestMode = FactoryTest.getMode();
 
    // Record process start information.
    // Note SYSPROP_START_COUNT will increment by *2* on a FDE device when it fully boots;
    // one for the password screen, second for the actual boot.
    mStartCount = SystemProperties.getInt(SYSPROP_START_COUNT, 0) + 1;
    mRuntimeStartElapsedTime = SystemClock.elapsedRealtime();
    mRuntimeStartUptime = SystemClock.uptimeMillis();
    Process.setStartTimes(mRuntimeStartElapsedTime, mRuntimeStartUptime);
 
    // Remember if it's runtime restart(when sys.boot_completed is already set) or reboot
    // We don't use "mStartCount > 1" here because it'll be wrong on a FDE device.
    // TODO: mRuntimeRestart will *not* be set to true if the proccess crashes before
    // sys.boot_completed is set. Fix it.
    mRuntimeRestart = "1".equals(SystemProperties.get("sys.boot_completed"));
}
 
...    // Create the system service manager. 创建SystemServiceManager
        mSystemServiceManager = new SystemServiceManager(mSystemContext);
        mSystemServiceManager.setStartInfo(mRuntimeRestart,
                mRuntimeStartElapsedTime, mRuntimeStartUptime);
                //使用LocalServices.addService将SystemServiceManager添加到本地服务列表中。
        LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
        // Prepare the thread pool for init tasks that can be parallelized
        //使用SystemServerInitThreadPool.start()启动了一个线程池。以提高启动速度。
        SystemServerInitThreadPool.start();
        // Attach JVMTI agent if this is a debuggable build and the system property is set.
        if (Build.IS_DEBUGGABLE) {
            // Property is of the form "library_path=parameters".
            String jvmtiAgent = SystemProperties.get("persist.sys.dalvik.jvmtiagent");
            if (!jvmtiAgent.isEmpty()) {
                int equalIndex = jvmtiAgent.indexOf('=');
                String libraryPath = jvmtiAgent.substring(0, equalIndex);
                String parameterList =
                        jvmtiAgent.substring(equalIndex + 1, jvmtiAgent.length());
                // Attach the agent.
                try {
                    Debug.attachJvmtiAgent(libraryPath, parameterList, null);
                } catch (Exception e) {
                    Slog.e("System", "*************************************************");
                    Slog.e("System", "********** Failed to load jvmti plugin: " + jvmtiAgent);
                }
            }
 
               // Start services.  开启服务
    try {
        t.traceBegin("StartServices");
        startBootstrapServices(t);
        startCoreServices(t);
        startOtherServices(t);
    } catch (Throwable ex) {
        Slog.e("System", "******************************************");
        Slog.e("System", "************ Failure starting system services", ex);
        throw ex;
    } finally {
        t.traceEnd(); // StartServices
    }
        }...

找到 pms 服务添加的地方

// Start the package manager.
if (!mRuntimeRestart) {
FrameworkStatsLog.write(FrameworkStatsLog.BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,
FrameworkStatsLog
.BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__PACKAGE_MANAGER_INIT_START,
SystemClock.elapsedRealtime());
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
t.traceBegin("StartPackageManagerService");
try {
    Watchdog.getInstance().pauseWatchingCurrentThread("packagemanagermain");
    //这里执行 PackageManagerService.main
    mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
            mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
} finally {
    Watchdog.getInstance().resumeWatchingCurrentThread("packagemanagermain");
}
 
// Now that the package manager has started, register the dex load reporter to capture any
// dex files loaded by system server.
// These dex files will be optimized by the BackgroundDexOptService.
SystemServerDexLoadReporter.configureSystemServerDexReporter(mPackageManagerService);
 
mFirstBoot = mPackageManagerService.isFirstBoot();
mPackageManager = mSystemContext.getPackageManager();
t.traceEnd();
if (!mRuntimeRestart && !isFirstBootOrUpgrade()) {
    FrameworkStatsLog.write(FrameworkStatsLog.BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,
            FrameworkStatsLog
                    .BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__PACKAGE_MANAGER_INIT_READY,
            SystemClock.elapsedRealtime());
}
// Manages A/B OTA dexopting. This is a bootstrap service as we need it to rename
// A/B artifacts after boot, before anything else might touch/need them.
// Note: this isn't needed during decryption (we don't have /data anyways).
if (!mOnlyCore) {
    boolean disableOtaDexopt = SystemProperties.getBoolean("config.disable_otadexopt",
            false);
    if (!disableOtaDexopt) {
        t.traceBegin("StartOtaDexOptService");
        try {
            Watchdog.getInstance().pauseWatchingCurrentThread("moveab");
            OtaDexoptService.main(mSystemContext, mPackageManagerService);
        } catch (Throwable e) {
            reportWtf("starting OtaDexOptService", e);
        } finally {
            Watchdog.getInstance().resumeWatchingCurrentThread("moveab");
            t.traceEnd();
        }
    }
}

来到 PackageManagerService.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
PackageManagerService m = new PackageManagerService(injector, onlyCore, factoryTest);
  t.traceEnd(); // "create package manager"
 
  injector.getCompatibility().registerListener(SELinuxMMAC.SELINUX_LATEST_CHANGES,
          packageName -> {
              synchronized (m.mInstallLock) {
                  final AndroidPackage pkg;
                  final PackageSetting ps;
                  final SharedUserSetting sharedUser;
                  final String oldSeInfo;
                  synchronized (m.mLock) {
                      ps = m.mSettings.getPackageLPr(packageName);
                      if (ps == null) {
                          Slog.e(TAG, "Failed to find package setting " + packageName);
                          return;
                      }
                      pkg = ps.pkg;
                      sharedUser = ps.getSharedUser();
                      oldSeInfo = AndroidPackageUtils.getSeInfo(pkg, ps);
                  }
 
                  if (pkg == null) {
                      Slog.e(TAG, "Failed to find package " + packageName);
                      return;
                  }
                  final String newSeInfo = SELinuxMMAC.getSeInfo(pkg, sharedUser,
                          m.mInjector.getCompatibility());
 
                  if (!newSeInfo.equals(oldSeInfo)) {
                      Slog.i(TAG, "Updating seInfo for package " + packageName + " from: "
                              + oldSeInfo + " to: " + newSeInfo);
                      ps.getPkgState().setOverrideSeInfo(newSeInfo);
                      m.prepareAppDataAfterInstallLIF(pkg);
                  }
              }
          });
 
  m.installWhitelistedSystemPackages();
  ServiceManager.addService("package", m);
  //将PMS添加为系统服务
  final PackageManagerNative pmn = m.new PackageManagerNative();
  ServiceManager.addService("package_native", pmn);

初始化相关的操作都在初始化函数中做了,代码量有点大,只关心我们关注的一些代码,什么代码是我们关心的呢,比如解析 apk 路径或者 xml 文件相关的操作就是我们需要关注的,因为我们要看到他解析 xml 文件中的权限或者一些组件的解析。

public PackageManagerService(Injector injector, boolean onlyCore, boolean factoryTest) {
mContext = injector.getContext();
mFactoryTest = factoryTest;
mOnlyCore = onlyCore;
mMetrics = new DisplayMetrics();
mInstaller = injector.getInstaller();

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
// Create sub-components that provide services / data. Order here is important.
t.traceBegin("createSubComponents");
 
// Expose private service for system components to use.
mPmInternal = new PackageManagerInternalImpl();
LocalServices.addService(PackageManagerInternal.class, mPmInternal);
mUserManager = injector.getUserManagerService();
mComponentResolver = injector.getComponentResolver();
mPermissionManager = injector.getPermissionManagerServiceInternal();
mSettings = injector.getSettings();
mPermissionManagerService = (IPermissionManager) ServiceManager.getService("permissionmgr");
mIncrementalManager =
        (IncrementalManager) mContext.getSystemService(Context.INCREMENTAL_SERVICE);
PlatformCompat platformCompat = mInjector.getCompatibility();
mPackageParserCallback = new PackageParser2.Callback() {
    @Override
    public boolean isChangeEnabled(long changeId, @NonNull ApplicationInfo appInfo) {
        return platformCompat.isChangeEnabled(changeId, appInfo);
    }
 
    @Override
    public boolean hasFeature(String feature) {
        return PackageManagerService.this.hasSystemFeature(feature, 0);
    }
};
 
// CHECKSTYLE:ON IndentationCheck
t.traceEnd();
 
t.traceBegin("addSharedUsers");
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);
t.traceEnd();
//非核心模式调用scanDirTracedLI方法扫描sAppInstallDir目录。这个目录通常包含用户安装的应用。
       if (!mOnlyCore) {
        EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
                SystemClock.uptimeMillis());
        scanDirTracedLI(sAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0,
                packageParser, executorService);
 
    }

接着走到 scanDirLI 这个方法中

private void scanDirLI(File scanDir, int parseFlags, int scanFlags, long currentTime,
PackageParser2 packageParser, ExecutorService executorService) {
final File[] files = scanDir.listFiles();
if (ArrayUtils.isEmpty(files)) {
Log.d(TAG, "No files in app dir " + scanDir);
return;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
    if (DEBUG_PACKAGE_SCANNING) {
        Log.d(TAG, "Scanning app dir " + scanDir + " scanFlags=" + scanFlags
                + " flags=0x" + Integer.toHexString(parseFlags));
    }
 
    ParallelPackageParser parallelPackageParser =
            new ParallelPackageParser(packageParser, executorService);
 
    // 遍历目录中的文件并提交给解析器:
    int fileCount = 0;
    for (File file : files) {
        final boolean isPackage = (isApkFile(file) || file.isDirectory())
                && !PackageInstallerService.isStageName(file.getName());
        if (!isPackage) {
            // Ignore entries which are not packages
            continue;
        }
        parallelPackageParser.submit(file, parseFlags);
        fileCount++;
    }
 
 
    //这个方法并行地解析应用包并将结果放入一个队列中
      public void submit(File scanFile, int parseFlags) {
    mExecutorService.submit(() -> {
        ParseResult pr = new ParseResult();
        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parallel parsePackage [" + scanFile + "]");
        try {
            pr.scanFile = scanFile;
            pr.parsedPackage = parsePackage(scanFile, parseFlags);
        } catch (Throwable e) {
            pr.throwable = e;
        } finally {
            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
        }
        try {
            mQueue.put(pr);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            // Propagate result to callers of take().
            // This is helpful to prevent main thread from getting stuck waiting on
            // ParallelPackageParser to finish in case of interruption
            mInterruptedInThread = Thread.currentThread().getName();
        }
    });
}

进入 ParallelPackageParser.java 中,mPackageParser 是 private final PackageParser2 mPackageParser; PackageParser2 这个类

@VisibleForTesting
protected ParsedPackage parsePackage(File scanFile, int parseFlags)
throws PackageParser.PackageParserException {
return mPackageParser.parsePackage(scanFile, parseFlags, true);
}
进入 com.android.server.pm.parsing.PackageParser2 这个类中的 parsePackage(scanFile, parseFlags, true)这个方法,

//用于解析应用包
public ParsedPackage parsePackage(File packageFile, int flags, boolean useCaches)
throws PackageParserException {
if (useCaches && mCacher != null) {
ParsedPackage parsed = mCacher.getCachedResult(packageFile, flags);
if (parsed != null) {
return parsed;
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
    long parseTime = LOG_PARSE_TIMINGS ? SystemClock.uptimeMillis() : 0;
    ParseInput input = mSharedResult.get().reset();
    //涉及一个使用parsingUtils对象进行应用包解析的操作
    ParseResult<ParsingPackage> result = parsingUtils.parsePackage(input, packageFile, flags);
    if (result.isError()) {
        throw new PackageParserException(result.getErrorCode(), result.getErrorMessage(),
                result.getException());
    }
 
    ParsedPackage parsed = (ParsedPackage) result.getResult().hideAsParsed();
 
    long cacheTime = LOG_PARSE_TIMINGS ? SystemClock.uptimeMillis() : 0;
    if (mCacher != null) {
        mCacher.cacheResult(packageFile, flags, parsed);
    }
    if (LOG_PARSE_TIMINGS) {
        parseTime = cacheTime - parseTime;
        cacheTime = SystemClock.uptimeMillis() - cacheTime;
        if (parseTime + cacheTime > LOG_PARSE_TIMINGS_THRESHOLD_MS) {
            Slog.i(TAG, "Parse times for '" + packageFile + "': parse=" + parseTime
                    + "ms, update_cache=" + cacheTime + " ms");
        }
    }
 
    return parsed;
}

public ParseResult<ParsingPackage> parsePackage(ParseInput input, File packageFile,
int flags)
throws PackageParserException {
if (packageFile.isDirectory()) {
return parseClusterPackage(input, packageFile, flags);
} else {
return parseMonolithicPackage(input, packageFile, flags);
}
}
来到 android.content.pm.parsing.ParsingPackageUtils.java 中 parsePackage 方法

public ParseResult<ParsingPackage> parsePackage(ParseInput input, File packageFile,
int flags)
throws PackageParserException {
if (packageFile.isDirectory()) {
return parseClusterPackage(input, packageFile, flags);
} else {
return parseMonolithicPackage(input, packageFile, flags);
}
}
//函数parseBaseApk是一个关键的Android应用包解析函数,它解析基础APK文件的内容并返回解析后的ParsingPackage对象
private ParseResult<ParsingPackage> parseBaseApk(ParseInput input, File apkFile,
String codePath, AssetManager assets, int flags) {
final String apkPath = apkFile.getAbsolutePath();

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
String volumeUuid = null;
if (apkPath.startsWith(PackageParser.MNT_EXPAND)) {
    final int end = apkPath.indexOf('/', PackageParser.MNT_EXPAND.length());
    volumeUuid = apkPath.substring(PackageParser.MNT_EXPAND.length(), end);
}
 
if (PackageParser.DEBUG_JAR) Slog.d(TAG, "Scanning base APK: " + apkPath);
 
final int cookie = assets.findCookieForPath(apkPath);
if (cookie == 0) {
    return input.error(INSTALL_PARSE_FAILED_BAD_MANIFEST,
            "Failed adding asset path: " + apkPath);
}
 
try (XmlResourceParser parser = assets.openXmlResourceParser(cookie,
        PackageParser.ANDROID_MANIFEST_FILENAME)) {
    final Resources res = new Resources(assets, mDisplayMetrics, null);

//使用解析方法parseBaseApk来处理Manifest文件并返回ParsingPackage结果。
ParseResult<ParsingPackage> result = parseBaseApk(input, apkPath, codePath, res,
parser, flags);
if (result.isError()) {
return input.error(result.getErrorCode(),
apkPath + " (at " + parser.getPositionDescription() + "): "
+ result.getErrorMessage());
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
        final ParsingPackage pkg = result.getResult();
        if (assets.containsAllocatedTable()) {
            final ParseResult<?> deferResult = input.deferError(
                    "Targeting R+ (version " + Build.VERSION_CODES.R + " and above) requires"
                            + " the resources.arsc of installed APKs to be stored uncompressed"
                            + " and aligned on a 4-byte boundary",
                    DeferredError.RESOURCES_ARSC_COMPRESSED);
            if (deferResult.isError()) {
                return input.error(INSTALL_PARSE_FAILED_RESOURCES_ARSC_COMPRESSED,
                        deferResult.getErrorMessage());
            }
        }
 
        ApkAssets apkAssets = assets.getApkAssets()[0];
        if (apkAssets.definesOverlayable()) {
            SparseArray<String> packageNames = assets.getAssignedPackageIdentifiers();
            int size = packageNames.size();
            for (int index = 0; index < size; index++) {
                String packageName = packageNames.get(index);
                Map<String, String> overlayableToActor = assets.getOverlayableMap(packageName);
                if (overlayableToActor != null && !overlayableToActor.isEmpty()) {
                    for (String overlayable : overlayableToActor.keySet()) {
                        pkg.addOverlayable(overlayable, overlayableToActor.get(overlayable));
                    }
                }
            }
        }
 
        pkg.setVolumeUuid(volumeUuid);
 
        if ((flags & PackageParser.PARSE_COLLECT_CERTIFICATES) != 0) {
            pkg.setSigningDetails(getSigningDetails(pkg, false));
        } else {
            pkg.setSigningDetails(SigningDetails.UNKNOWN);
        }
 
        return input.success(pkg);
    } catch (Exception e) {
        return input.error(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
                "Failed to read manifest from " + apkPath, e);
    }
}

//走到这个函数
private ParseResult<ParsingPackage> parseBaseApk(ParseInput input, String apkPath,
String codePath, Resources res, XmlResourceParser parser, int flags)
throws XmlPullParserException, IOException, PackageParserException {
final String splitName;
final String pkgName;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
    ParseResult<Pair<String, String>> packageSplitResult =
            ApkLiteParseUtils.parsePackageSplitNames(input, parser, parser);
    if (packageSplitResult.isError()) {
        return input.error(packageSplitResult);
    }
 
    Pair<String, String> packageSplit = packageSplitResult.getResult();
    pkgName = packageSplit.first;
    splitName = packageSplit.second;
 
    if (!TextUtils.isEmpty(splitName)) {
        return input.error(
                PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME,
                "Expected base APK, but found split " + splitName
        );
    }
 
    final TypedArray manifestArray = res.obtainAttributes(parser, R.styleable.AndroidManifest);
    try {
        final boolean isCoreApp =
                parser.getAttributeBooleanValue(null, "coreApp", false);
        final ParsingPackage pkg = mCallback.startParsingPackage(
                pkgName, apkPath, codePath, manifestArray, isCoreApp);
        final ParseResult<ParsingPackage> result =
                parseBaseApkTags(input, pkg, manifestArray, res, parser, flags);
        if (result.isError()) {
            return result;
        }
 
        return input.success(pkg);
    } finally {
        manifestArray.recycle();
    }
}

在上述方法中parseBaseApkTags里会执行parseBaseApplication这个就是我们最终要找的解析xml文件的方法,解析四大组件都在这里

ParsingPackage用于表示待解析的Android应用程序包信息。它存储从AndroidManifest.xml文件中解析出的各种信息,如应用程序名称、权限、活动、服务等。
String tagName = parser.getName();
boolean isActivity = false;
switch (tagName) {
case "activity":
isActivity = true;
// fall-through
case "receiver":
ParseResult<ParsedActivity> activityResult =
ParsedActivityUtils.parseActivityOrReceiver(mSeparateProcesses, pkg,
res, parser, flags, PackageParser.sUseRoundIcon, input);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
        if (activityResult.isSuccess()) {
            ParsedActivity activity = activityResult.getResult();
            if (isActivity) {
                hasActivityOrder |= (activity.getOrder() != 0);
                pkg.addActivity(activity);
            } else {
                hasReceiverOrder |= (activity.getOrder() != 0);
                pkg.addReceiver(activity);
            }
        }
 
        result = activityResult;
        break;
    case "service":
        ParseResult<ParsedService> serviceResult =
                ParsedServiceUtils.parseService(mSeparateProcesses, pkg, res, parser,
                        flags, PackageParser.sUseRoundIcon, input);
        if (serviceResult.isSuccess()) {
            ParsedService service = serviceResult.getResult();
            hasServiceOrder |= (service.getOrder() != 0);
            pkg.addService(service);
        }
 
        result = serviceResult;
        break;
    case "provider":
        ParseResult<ParsedProvider> providerResult =
                ParsedProviderUtils.parseProvider(mSeparateProcesses, pkg, res, parser,
                        flags, PackageParser.sUseRoundIcon, input);
        if (providerResult.isSuccess()) {
            pkg.addProvider(providerResult.getResult());
        }
 
        result = providerResult;
        break;
    case "activity-alias":
        activityResult = ParsedActivityUtils.parseActivityAlias(pkg, res,
                parser, PackageParser.sUseRoundIcon, input);
        if (activityResult.isSuccess()) {
            ParsedActivity activity = activityResult.getResult();
            hasActivityOrder |= (activity.getOrder() != 0);
            pkg.addActivity(activity);
        }
 
        result = activityResult;
        break;
    default:
        result = parseBaseAppChildTag(input, tagName, pkg, res, parser, flags);
        break;
}

为安装的所有 app 添加权限
通过我们上述简单的探索了一下pmg的加载流程和执行的一些方法,还有很多方法过签名的方法也是对这其中的一些方法的参数和返回值以及变量来替换和入手的。分析到这里我们就可以拿到解析出的结果来添加我们想添加的权限了。如果你想白嫖记得点关注加再看,微信公众号搜索 小瑶在工地 回复“增加权限”获取代码。喜欢的可以加群,让我们一起一边摸鱼一遍学技术。
图片描述


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (1)
雪    币: 865
活跃值: (1599)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
如何让系统app支持读取外部存储呢?setting 是可以的 但是setting provider就不行 能否告知下为什么?
2023-8-24 18:52
0
游客
登录 | 注册 方可回帖
返回
//