android AMS 详解二

文章出处:https://blog.csdn.net/shift_wwx/article/details/46427509

接着之前的博文

android AMS 详解一

继续总结:

ActivityManagerService.setSystemProcess();

    public static void setSystemProcess() {
        try {
            ActivityManagerService m = mSelf;

            ServiceManager.addService(Context.ACTIVITY_SERVICE, m, true);
            ServiceManager.addService(ProcessStats.SERVICE_NAME, m.mProcessStats);
            ServiceManager.addService("meminfo", new MemBinder(m));
            ServiceManager.addService("gfxinfo", new GraphicsBinder(m));
            ServiceManager.addService("dbinfo", new DbBinder(m));
            if (MONITOR_CPU_USAGE) {
                ServiceManager.addService("cpuinfo", new CpuBinder(m));
            }
            ServiceManager.addService("permission", new PermissionController(m));

            ApplicationInfo info =
                mSelf.mContext.getPackageManager().getApplicationInfo(
                            "android", STOCK_PM_FLAGS);
            mSystemThread.installSystemApplicationInfo(info);

            synchronized (mSelf) {
                ProcessRecord app = mSelf.newProcessRecordLocked(info,
                        info.processName, false);
                app.persistent = true;
                app.pid = MY_PID;
                app.maxAdj = ProcessList.SYSTEM_ADJ;
                app.makeActive(mSystemThread.getApplicationThread(), mSelf.mProcessStats);
                mSelf.mProcessNames.put(app.processName, app.uid, app);
                synchronized (mSelf.mPidsSelfLocked) {
                    mSelf.mPidsSelfLocked.put(app.pid, app);
                }
                mSelf.updateLruProcessLocked(app, false, null);
                mSelf.updateOomAdjLocked();
            }
        } catch (PackageManager.NameNotFoundException e) {
            throw new RuntimeException(
                    "Unable to find android system package", e);
        }
    }

当初
android 查看内存使用情况提到了这个函数。

1)注册AMS

在SystemServer中会看到ServiceManager中会注册很多service,可是轮到AMS的时候直接调用的main,到这里才看到了注册。注意addService时候的第三个参数是true,一般默认是false。

2)注册procstats、meminfo、gfxinfo、dbinfo、cpuinfo、permission

3)getApplicationInfo

首先getPackageManager得到是在SystemServer中初始化的PM,这里的ApplicationInfo应该是在AMS.main的时候实例化LoadedApk时候new出来的?不太确定。

4)installSystemApplicationInfo

跟之前AMS.main中提到的getSystemContext一样,就是将ApplicationInfo绑定到mSystemContext

5)newProcessRecordLocked

final ProcessRecord newProcessRecordLocked(ApplicationInfo info, String customProcess,
        boolean isolated) {
    String proc = customProcess != null ? customProcess : info.processName;
    BatteryStatsImpl.Uid.Proc ps = null;
    BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
    int uid = info.uid;
    if (isolated) {
	......
    }
    return new ProcessRecord(stats, info, proc, uid);
}

    ProcessRecord(BatteryStatsImpl _batteryStats, ApplicationInfo _info,
            String _processName, int _uid) {
        mBatteryStats = _batteryStats;
        info = _info;
        isolated = _info.uid != _uid;
        uid = _uid;
        userId = UserHandle.getUserId(_uid);
        processName = _processName;
        pkgList.put(_info.packageName, null);
        maxAdj = ProcessList.UNKNOWN_ADJ;
        curRawAdj = setRawAdj = -100;
        curAdj = setAdj = -100;
        persistent = false;
        removed = false;
        lastStateTime = lastPssTime = nextPssTime = SystemClock.uptimeMillis();
    }

ProcessRecord记录了当前ApplicationInfo的uid号、userId、processName、以及进程优先级等,并且在pkgList保存了所有在当前进程中的package信息。具体的ProcessRecord后面继续说明。

6)app.persistent = true;

一直保持这个应用运行,应用是不会被随便kill的。

7)app.pid = MY_PID;

应用的pid应该是system_server的pid。

8)app.makeActive(mSystemThread.getApplicationThread(), mSelf.mProcessStats);

先来看一下第一个参数ApplicationThread:

final ApplicationThread mAppThread = new ApplicationThread();

在ActivityThread中定义了一个常量mAppThread,也就是说每实例化一个ActivityThread,就会跟这有个ApplicationThread。

这里的ApplicationThread也是AMS中的关键:

private class ApplicationThread extends ApplicationThreadNative {
    private static final String ONE_COUNT_COLUMN = "%21s %8d";
    private static final String TWO_COUNT_COLUMNS = "%21s %8d %21s %8d";
    private static final String DB_INFO_FORMAT = "  %8s %8s %14s %14s  %s";

    private int mLastProcessState = -1;

    public final void schedulePauseActivity(IBinder token, boolean finished,
            boolean userLeaving, int configChanges) {
            ......
    }

    public final void scheduleStopActivity(IBinder token, boolean showWindow,
            int configChanges) {
            ......
    }

    public final void scheduleResumeActivity(IBinder token, int processState,
            boolean isForward) {
            ......
    }

    // we use token to identify this activity without having to send the
    // activity itself back to the activity manager. (matters more with ipc)
    public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
            ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
            int procState, Bundle state, List<ResultInfo> pendingResults,
            List<Intent> pendingNewIntents, boolean notResumed, boolean isForward,
            String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler) {
            ......
    }

    public final void scheduleRelaunchActivity(IBinder token,
            List<ResultInfo> pendingResults, List<Intent> pendingNewIntents,
            int configChanges, boolean notResumed, Configuration config) {
            ......
    }

    public final void scheduleNewIntent(List<Intent> intents, IBinder token) {
    }

    public final void scheduleDestroyActivity(IBinder token, boolean finishing,
            int configChanges) {
            ......
    }

    public final void scheduleReceiver(Intent intent, ActivityInfo info,
            CompatibilityInfo compatInfo, int resultCode, String data, Bundle extras,
            boolean sync, int sendingUser, int processState) {
            ......
    }

    public final void scheduleCreateService(IBinder token,
            ServiceInfo info, CompatibilityInfo compatInfo, int processState) {
            ......
    }

    public final void scheduleBindService(IBinder token, Intent intent,
            boolean rebind, int processState) {
            ......
    }
    
    ......

    public final void scheduleStopService(IBinder token) {
        sendMessage(H.STOP_SERVICE, token);
    }

    public final void bindApplication(String processName,
            ApplicationInfo appInfo, List<ProviderInfo> providers,
            ComponentName instrumentationName, String profileFile,
            ParcelFileDescriptor profileFd, boolean autoStopProfiler,
            Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher,
            IUiAutomationConnection instrumentationUiConnection, int debugMode,
            boolean enableOpenGlTrace, boolean isRestrictedBackupMode, boolean persistent,
            Configuration config, CompatibilityInfo compatInfo, Map<String, IBinder> services,
            Bundle coreSettings) {
            ......
    }

   ......

    public void scheduleLowMemory() {
        sendMessage(H.LOW_MEMORY, null);
    }

    public void scheduleActivityConfigurationChanged(IBinder token) {
        sendMessage(H.ACTIVITY_CONFIGURATION_CHANGED, token);
    }
    
    ......
    
    public void dumpActivity(FileDescriptor fd, IBinder activitytoken,
            String prefix, String[] args) {
            
    }

    public void dumpProvider(FileDescriptor fd, IBinder providertoken,
            String[] args) {
            
    }

    @Override
    public void dumpMemInfo(FileDescriptor fd, Debug.MemoryInfo mem, boolean checkin,
            boolean dumpFullInfo, boolean dumpDalvik, String[] args) {
            
    }
    
    ......

}

四大组件之间的连接这里基本都涉及到了。对于AMS中的四大组件的详细串联过程,后期在《
ActivityManagerService 详解》中会继续补充。

回到之前的makeActive函数中,显然了这里的 _thread不是为null。之前ProcessRecord构造函数中并没有初始化thread,所以,这里thread是null的。

    public void makeActive(IApplicationThread _thread, ProcessStatsService tracker) {
        if (thread == null) {
            final ProcessStats.ProcessState origBase = baseProcessTracker;
            if (origBase != null) {
                origBase.setState(ProcessStats.STATE_NOTHING,
                        tracker.getMemFactorLocked(), SystemClock.uptimeMillis(), pkgList);
                origBase.makeInactive();
            }
            baseProcessTracker = tracker.getProcessStateLocked(info.packageName, info.uid,
                    processName);
            baseProcessTracker.makeActive();
            for (int i=0; i<pkgList.size(); i++) {
                ProcessStats.ProcessState ps = pkgList.valueAt(i);
                if (ps != null && ps != origBase) {
                    ps.makeInactive();
                }
                ps = tracker.getProcessStateLocked(pkgList.keyAt(i), info.uid, processName);
                if (ps != baseProcessTracker) {
                    ps.makeActive();
                }
                pkgList.setValueAt(i, ps);
            }
        }
        thread = _thread;
    }

注意这里的变量baseProcessTracker,ProcessRecord很多地方会用到这个tracker:

ProcessStats.ProcessState baseProcessTracker;

刚开始的时候肯定是null,所以初始化就在这里:

baseProcessTracker = tracker.getProcessStateLocked(info.packageName, info.uid, processName);
    public ProcessStats.ProcessState getProcessStateLocked(String packageName,
            int uid, String processName) {
        return mProcessStats.getProcessStateLocked(packageName, uid, processName);
    }

这里的mProcessStats是在AMS.main中构造函数里面初始化过。

    public ProcessState getProcessStateLocked(String packageName, int uid, String processName) {
        final PackageState pkgState = getPackageStateLocked(packageName, uid);
        ProcessState ps = pkgState.mProcesses.get(processName);
        if (ps != null) {
            return ps;
        }
        ProcessState commonProc = mProcesses.get(processName, uid);
        if (commonProc == null) {
            commonProc = new ProcessState(this, packageName, uid, processName);
            mProcesses.put(processName, uid, commonProc);
            if (DEBUG) Slog.d(TAG, "GETPROC created new common " + commonProc);
        }
        if (!commonProc.mMultiPackage) {
            if (packageName.equals(commonProc.mPackage)) {
                // This common process is not in use by multiple packages, and
                // is for the calling package, so we can just use it directly.
                ps = commonProc;
                if (DEBUG) Slog.d(TAG, "GETPROC also using for pkg " + commonProc);
            } else {
                if (DEBUG) Slog.d(TAG, "GETPROC need to split common proc!");
                // This common process has not been in use by multiple packages,
                // but it was created for a different package than the caller.
                // We need to convert it to a multi-package process.
                commonProc.mMultiPackage = true;
                // To do this, we need to make two new process states, one a copy
                // of the current state for the process under the original package
                // name, and the second a free new process state for it as the
                // new package name.
                long now = SystemClock.uptimeMillis();
                // First let's make a copy of the current process state and put
                // that under the now unique state for its original package name.
                final PackageState commonPkgState = getPackageStateLocked(commonProc.mPackage, uid);
                if (commonPkgState != null) {
                    ProcessState cloned = commonProc.clone(commonProc.mPackage, now);
                    if (DEBUG) Slog.d(TAG, "GETPROC setting clone to pkg " + commonProc.mPackage
                            + ": " + cloned);
                    commonPkgState.mProcesses.put(commonProc.mName, cloned);
                    // If this has active services, we need to update their process pointer
                    // to point to the new package-specific process state.
                    for (int i=commonPkgState.mServices.size()-1; i>=0; i--) {
                        ServiceState ss = commonPkgState.mServices.valueAt(i);
                        if (ss.mProc == commonProc) {
                            if (DEBUG) Slog.d(TAG, "GETPROC switching service to cloned: "
                                    + ss);
                            ss.mProc = cloned;
                        } else if (DEBUG) {
                            Slog.d(TAG, "GETPROC leaving proc of " + ss);
                        }
                    }
                } else {
                    Slog.w(TAG, "Cloning proc state: no package state " + commonProc.mPackage
                            + "/" + uid + " for proc " + commonProc.mName);
                }
                // And now make a fresh new process state for the new package name.
                ps = new ProcessState(commonProc, packageName, uid, processName, now);
                if (DEBUG) Slog.d(TAG, "GETPROC created new pkg " + ps);
            }
        } else {
            // The common process is for multiple packages, we need to create a
            // separate object for the per-package data.
            ps = new ProcessState(commonProc, packageName, uid, processName,
                    SystemClock.uptimeMillis());
            if (DEBUG) Slog.d(TAG, "GETPROC created new pkg " + ps);
        }
        pkgState.mProcesses.put(processName, ps);
        if (DEBUG) Slog.d(TAG, "GETPROC adding new pkg " + ps);
        return ps;
    }

这里会构造PackageState和ProcessState,并分别添加到mPackages和mProcesses数组中,并将ProcessState添加到PackageState的mProcesses数组中,从这里可以看到,一个Package可以运行在几个process里面,通过一个process也可以运行几个package。下面是上述几个类的结构图:

《android AMS 详解二》

最后将当前ProcessRecord加入到mProcessNames和mPidsSelfLocked数据结构当中。updateLruProcessLocked用于调整系统优先级,updateOomAdjLocked用于low memory killer,基本上ProcessRecord是没看懂,后期继续研究补充。

    原文作者:私房菜
    原文地址: https://blog.csdn.net/shift_wwx/article/details/46427509
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞