android O版本 pms 强制编译流程

adb shell cmd package compile -m XXX 强制编译

流程研究

Pm.java


    private int runShellCommand(String serviceName, String[] args) {
        final HandlerThread handlerThread = new HandlerThread("results");
        handlerThread.start();
        try {
            ServiceManager.getService(serviceName).shellCommand(
                    FileDescriptor.in, FileDescriptor.out, FileDescriptor.err,
                    args, new MyShellCallback(),
                    new ResultReceiver(new Handler(handlerThread.getLooper())));
            return 0;
        } catch (RemoteException e) {
            e.printStackTrace();
        } finally {
            handlerThread.quitSafely();
        }
        return -1;
    }

—>

Binder.java

    /**
     * @param in The raw file descriptor that an input data stream can be read from.
     * @param out The raw file descriptor that normal command messages should be written to.
     * @param err The raw file descriptor that command error messages should be written to.
     * @param args Command-line arguments.
     * @param callback Callback through which to interact with the invoking shell.
     * @param resultReceiver Called when the command has finished executing, with the result code.
     * @throws RemoteException
     * @hide
     */
    public void shellCommand(@Nullable FileDescriptor in, @Nullable FileDescriptor out,
            @Nullable FileDescriptor err,
            @NonNull String[] args, @Nullable ShellCallback callback,
            @NonNull ResultReceiver resultReceiver) throws RemoteException {
        onShellCommand(in, out, err, args, callback, resultReceiver);
    }

    /**
     * Handle a call to {@link #shellCommand}.  The default implementation simply prints
     * an error message.  Override and replace with your own.
     * <p class="caution">Note: no permission checking is done before calling this method; you must
     * apply any security checks as appropriate for the command being executed.
     * Consider using {@link ShellCommand} to help in the implementation.</p>
     * @hide
     */
    public void onShellCommand(@Nullable FileDescriptor in, @Nullable FileDescriptor out,
            @Nullable FileDescriptor err,
            @NonNull String[] args, @Nullable ShellCallback callback,
            @NonNull ResultReceiver resultReceiver) throws RemoteException {
        FileOutputStream fout = new FileOutputStream(err != null ? err : out);
        PrintWriter pw = new FastPrintWriter(fout);
        pw.println("No shell command implementation.");
        pw.flush();
        resultReceiver.send(0, null);
    }

–>

PackageManagerService.java

    @Override
    public void onShellCommand(FileDescriptor in, FileDescriptor out,
            FileDescriptor err, String[] args, ShellCallback callback,
            ResultReceiver resultReceiver) {
        (new PackageManagerShellCommand(this)).exec(
                this, in, out, err, args, callback, resultReceiver);
    }

–>PackageManagerShellCommand.java:ShellCommand

    public int exec(Binder target, FileDescriptor in, FileDescriptor out, FileDescriptor err,
            String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
        String cmd;
        int start;
        if (args != null && args.length > 0) {
            cmd = args[0];
            start = 1;
        } else {
            cmd = null;
            start = 0;
        }
        init(target, in, out, err, args, callback, start);
        mCmd = cmd;
        mResultReceiver = resultReceiver;

        if (DEBUG) Slog.d(TAG, "Starting command " + mCmd + " on " + mTarget);
        int res = -1;
        try {
            res = onCommand(mCmd);
            if (DEBUG) Slog.d(TAG, "Executed command " + mCmd + " on " + mTarget);
        } catch (SecurityException e) {
            ...
        } catch (Throwable e) {
            ...
        } finally {
            ...
            mResultReceiver.send(res, null);
        }
        if (DEBUG) Slog.d(TAG, "Finished command " + mCmd + " on " + mTarget);
        return res;
    }

–>

    @Override
    public int onCommand(String cmd) {
        if (cmd == null) {
            return handleDefaultCommands(cmd);
        }

        final PrintWriter pw = getOutPrintWriter();
        try {
            switch(cmd) {
                case "install":
                    return runInstall();
                case "install-abandon":
                case "install-destroy":
                    return runInstallAbandon();
                case "install-commit":
                    return runInstallCommit();
                case "install-create":
                    return runInstallCreate();
                case "install-remove":
                    return runInstallRemove();
                case "install-write":
                    return runInstallWrite();
                case "install-existing":
                    return runInstallExisting();
                case "compile":
                    return runCompile();
                case "reconcile-secondary-dex-files":
                    return runreconcileSecondaryDexFiles();
                case "bg-dexopt-job":
                    return runDexoptJob();
                case "dump-profiles":
                    return runDumpProfiles();
                case "list":
                    return runList();
                case "uninstall":
                    return runUninstall();
                case "resolve-activity":
                    return runResolveActivity();
                case "query-activities":
                    return runQueryIntentActivities();
                case "query-services":
                    return runQueryIntentServices();
                case "query-receivers":
                    return runQueryIntentReceivers();
                case "suspend":
                    return runSuspend(true);
                case "unsuspend":
                    return runSuspend(false);
                case "set-home-activity":
                    return runSetHomeActivity();
                case "get-privapp-permissions":
                    return runGetPrivappPermissions();
                case "get-instantapp-resolver":
                    return runGetInstantAppResolver();
                case "has-feature":
                    return runHasFeature();
                default:
                    return handleDefaultCommands(cmd);
            }
        } catch (RemoteException e) {
            pw.println("Remote exception: " + e);
        }
        return -1;
    }

–>

runCompile

    private int runCompile() throws RemoteException {
        final PrintWriter pw = getOutPrintWriter();
        boolean checkProfiles = SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false);
        boolean forceCompilation = false;
        boolean allPackages = false;
        boolean clearProfileData = false;
        String compilerFilter = null;
        String compilationReason = null;
        String checkProfilesRaw = null;
        boolean secondaryDex = false;
        String split = null;

        String opt;
        while ((opt = getNextOption()) != null) {
            switch (opt) {
                case "-a":
                    allPackages = true;
                    break;
                case "-c":
                    clearProfileData = true;
                    break;
                case "-f":
                    forceCompilation = true;
                    break;
                case "-m":
                    compilerFilter = getNextArgRequired(); 获取filter
                    break;
                case "-r":
                    compilationReason = getNextArgRequired(); 获取reason
                    break;
                case "--check-prof":
                    checkProfilesRaw = getNextArgRequired();
                    break;
                case "--reset":
                    forceCompilation = true;
                    clearProfileData = true;
                    compilationReason = "install";
                    break;
                case "--secondary-dex":
                    secondaryDex = true;
                    break;
                case "--split":
                    split = getNextArgRequired();
                    break;
                default:
                    pw.println("Error: Unknown option: " + opt);
                    return 1;
            }
        }

        if (checkProfilesRaw != null) {
            if ("true".equals(checkProfilesRaw)) {
                checkProfiles = true;
            } else if ("false".equals(checkProfilesRaw)) {
                checkProfiles = false;
            } else {
                pw.println("Invalid value for \"--check-prof\". Expected \"true\" or \"false\".");
                return 1;
            }
        }

        if (compilerFilter != null && compilationReason != null) {
            pw.println("Cannot use compilation filter (\"-m\") and compilation reason (\"-r\") " +
                    "at the same time");
            return 1;
        }
        if (compilerFilter == null && compilationReason == null) {
            pw.println("Cannot run without any of compilation filter (\"-m\") and compilation " +
                    "reason (\"-r\") at the same time");
            return 1;
        }

        if (allPackages && split != null) {
            pw.println("-a cannot be specified together with --split");
            return 1;
        }

        if (secondaryDex && split != null) {
            pw.println("--secondary-dex cannot be specified together with --split");
            return 1;
        }

        String targetCompilerFilter;
        //如果有filter 则设置filter 否则根据reason 获取reason对应的filter
        if (compilerFilter != null) {
            if (!DexFile.isValidCompilerFilter(compilerFilter)) {
                pw.println("Error: \"" + compilerFilter +
                        "\" is not a valid compilation filter.");
                return 1;
            }
            targetCompilerFilter = compilerFilter;
        } else {
            int reason = -1;
            for (int i = 0; i < PackageManagerServiceCompilerMapping.REASON_STRINGS.length; i++) {
                if (PackageManagerServiceCompilerMapping.REASON_STRINGS[i].equals(
                        compilationReason)) {
                    reason = i;
                    break;
                }
            }
            if (reason == -1) {
                pw.println("Error: Unknown compilation reason: " + compilationReason);
                return 1;
            }
            targetCompilerFilter =
                    PackageManagerServiceCompilerMapping.getCompilerFilterForReason(reason);
        }


        List<String> packageNames = null;
        if (allPackages) {
            packageNames = mInterface.getAllPackages();
        } else {
            String packageName = getNextArg();
            if (packageName == null) {
                pw.println("Error: package name not specified");
                return 1;
            }
            packageNames = Collections.singletonList(packageName);
        }

        List<String> failedPackages = new ArrayList<>();
        int index = 0;
        for (String packageName : packageNames) {
            if (clearProfileData) {
                mInterface.clearApplicationProfileData(packageName);
            }

            if (allPackages) {
                pw.println(++index + "/" + packageNames.size() + ": " + packageName);
                pw.flush();
            }

 boolean result = secondaryDex ? mInterface.performDexOptSecondary(packageName, targetCompilerFilter, forceCompilation) : mInterface.performDexOptMode(packageName, checkProfiles, targetCompilerFilter, forceCompilation, true /* bootComplete */, split);
              进行dexopt 优化
            if (!result) {
                failedPackages.add(packageName);
            }
        }

        if (failedPackages.isEmpty()) {
            pw.println("Success");
            return 0;
        } else if (failedPackages.size() == 1) {
            pw.println("Failure: package " + failedPackages.get(0) + " could not be compiled");
            return 1;
        } else {
            pw.print("Failure: the following packages could not be compiled: ");
            boolean is_first = true;
            for (String packageName : failedPackages) {
                if (is_first) {
                    is_first = false;
                } else {
                    pw.print(", ");
                }
                pw.print(packageName);
            }
            pw.println();
            return 1;
        }
    }

–> 如果secondaryDex为false

mInterface.performDexOptMode(packageName,
                            checkProfiles, targetCompilerFilter, forceCompilation,
                            true /* bootComplete */, split);

–>PackageManagerService.java

    @Override
    public boolean performDexOptMode(String packageName,
            boolean checkProfiles, String targetCompilerFilter, boolean force,
            boolean bootComplete, String splitName) {
        int flags = (checkProfiles ? DexoptOptions.DEXOPT_CHECK_FOR_PROFILES_UPDATES : 0) |
                (force ? DexoptOptions.DEXOPT_FORCE : 0) |
                (bootComplete ? DexoptOptions.DEXOPT_BOOT_COMPLETE : 0);
        return performDexOpt(new DexoptOptions(packageName, targetCompilerFilter,
                splitName, flags));
    }

    原文作者:路人戊戌乙亥
    原文地址: https://blog.csdn.net/passerbysrs/article/details/79521043
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞