Cached_app_freezer 流程分析

概述:cached app freezer 是将原本需要不可见的随时可以被清理的Activity,进行冻结, 在下次使用时解冻, 从面提升系统保活能力.

开发者选项中开启的入口:

development_settings.xml


设置中开启cached app freezer 功能

CachedAppsFreezerPreferenceController.java

private DialogInterface.OnClickListener getRebootDialogOkListener(Object newValue) {
        return (dialog, which) -> {
            Settings.Global.putString(mContext.getContentResolver(),
                    Settings.Global.CACHED_APPS_FREEZER_ENABLED,
                    newValue.toString());

            updateState(mPreference);

            PowerManager pm = mContext.getSystemService(PowerManager.class);
            pm.reboot(null);
        };
    }

App Freeze 启用流程

CachedAppOptimizer.java

mAm.mHandler.post(() -> {
        if (useFreezer) {
            Slog.d(TAG_AM, "Freezer enabled");
            enableFreezer(true);

            if (!mCachedAppOptimizerThread.isAlive()) {
                mCachedAppOptimizerThread.start();
            }

            if (mFreezeHandler == null) {
                mFreezeHandler = new FreezeHandler();
            }

            Process.setThreadGroupAndCpuset(mCachedAppOptimizerThread.getThreadId(),
                    Process.THREAD_GROUP_SYSTEM);
        } else {
            Slog.d(TAG_AM, "Freezer disabled");
            enableFreezer(false);
        }
    });
}

冻结进程

private void freezeProcess(final ProcessRecord proc) {
    int pid = proc.getPid(); // Unlocked intentionally
    final String name = proc.processName;
    final long unfrozenDuration;
    final boolean frozen;
    final ProcessCachedOptimizerRecord opt = proc.mOptRecord;

    opt.setPendingFreeze(false);

    try {
        // pre-check for locks to avoid unnecessary freeze/unfreeze operations
        if (mProcLocksReader.hasFileLocks(pid)) {
            if (DEBUG_FREEZER) {
                Slog.d(TAG_AM, name + " (" + pid + ") holds file locks, not freezing");
            }
            return;
        }
    } catch (Exception e) {
        Slog.e(TAG_AM, "Not freezing. Unable to check file locks for " + name + "(" + pid
                + "): " + e);
        return;
    }

    synchronized (mProcLock) {
        pid = proc.getPid();
        if (proc.mState.getCurAdj() < ProcessList.CACHED_APP_MIN_ADJ
                || opt.shouldNotFreeze()) {
            if (DEBUG_FREEZER) {
                Slog.d(TAG_AM, "Skipping freeze for process " + pid
                        + " " + name + " curAdj = " + proc.mState.getCurAdj()
                        + ", shouldNotFreeze = " + opt.shouldNotFreeze());
            }
            return;
        }

        if (mFreezerOverride) {
            opt.setFreezerOverride(true);
            Slog.d(TAG_AM, "Skipping freeze for process " + pid
                    + " " + name + " curAdj = " + proc.mState.getCurAdj()
                    + "(override)");
            return;
        }

        if (pid == 0 || opt.isFrozen()) {
            // Already frozen or not a real process, either one being
            // launched or one being killed
            return;
        }

        // Freeze binder interface before the process, to flush any
        // transactions that might be pending.
        try {
            freezeBinder(pid, true);
        } catch (RuntimeException e) {
            Slog.e(TAG_AM, "Unable to freeze binder for " + pid + " " + name);
            mFreezeHandler.post(() -> {
                synchronized (mAm) {
                    proc.killLocked("Unable to freeze binder interface",
                            ApplicationExitInfo.REASON_OTHER,
                            ApplicationExitInfo.SUBREASON_FREEZER_BINDER_IOCTL, true);
                }
            });
        }

        long unfreezeTime = opt.getFreezeUnfreezeTime();

        try {
            Process.setProcessFrozen(pid, proc.uid, true);

            opt.setFreezeUnfreezeTime(SystemClock.uptimeMillis());
            opt.setFrozen(true);
        } catch (Exception e) {
            Slog.w(TAG_AM, "Unable to freeze " + pid + " " + name);
        }

        unfrozenDuration = opt.getFreezeUnfreezeTime() - unfreezeTime;
        frozen = opt.isFrozen();
    }

    if (!frozen) {
        return;
    }

    Slog.d(TAG_AM, "froze " + pid + " " + name);

    EventLog.writeEvent(EventLogTags.AM_FREEZE, pid, name);

    // See above for why we're not taking mPhenotypeFlagLock here
    if (mRandom.nextFloat() < mFreezerStatsdSampleRate) {
        FrameworkStatsLog.write(FrameworkStatsLog.APP_FREEZE_CHANGED,
                FrameworkStatsLog.APP_FREEZE_CHANGED__ACTION__FREEZE_APP,
                pid,
                name,
                unfrozenDuration);
    }

    try {
        // post-check to prevent races
        if (mProcLocksReader.hasFileLocks(pid)) {
            if (DEBUG_FREEZER) {
                Slog.d(TAG_AM, name + " (" + pid + ") holds file locks, reverting freeze");
            }

            synchronized (mAm) {
                synchronized (mProcLock) {
                    unfreezeAppLSP(proc);
                }
            }
        }
    } catch (Exception e) {
        Slog.e(TAG_AM, "Unable to check file locks for " + name + "(" + pid + "): " + e);
        synchronized (mAm) {
            synchronized (mProcLock) {
                unfreezeAppLSP(proc);
            }
        }
    }
}

通过 Process.setProcessFrozen(pid, proc.uid, true); 来冻结目标进程

//TODO

// native层冻结原理分析

你可能感兴趣的:(Android,java,开发语言)