《深入理解Android2》读书笔记(八)

接上篇《深入理解Android2》读书笔记(七)

AMS中的进程管理

AMS对进程的管理仅涉及两个方面

1.调节进程的调度优先级和调度策略

2.调节进程的oom值

调度优先级和调度策略

1.相对于在OS(操作系统)上运行的应用进程个数来说,CPU的资源非常有限

2.调度优先级是OS分配CPU资源给应用进程时(即调度应用进程运行)需要参考的一个指标。一般而言,优先级高的进程将更有机会得到CPU资源

3.除了优先级,还有一个需要考虑的重要因素是,每个进程所分配的时间片及它们的使用情况

Android应用进程分类:Forground类、Visible类、Service类、Background类及Empty类

Forground类

属于该类的进程包括下面几种情况

(1)含一个前端Activity(即onResume函数被调用过了,或者说当前正在显示的那个Activity)

(2)含一个Service,并且该Service和一个前端Activity绑定(例如Music应用包括一个前端界面和一个播放Service,当我们一边听歌一边操作Music界面时,该Service即和一个前端Activity绑定)

(3)含一个调用了startForground的Service,或者该进程的Service正在调用其生命周期的函数(onCreate、onStart或onDestroy)

(4)该进程中有BroadcastReceiver实例正在执行onReceive函数

Visible类

看属于Visible类的进程中没有处于前端的组件,但是用户仍然能看到它们,例如位于一个对话框后的Activity界面。该类进程包括两种

(1)该进程包含一个仅onPaus被调用的Activity(即它还在前台,只不过部分界面被遮住)

(2)包含一个Service,并且该Service和一个Visible(或Forground)的Activity绑定

Service类

该类进程包含一个Service。此Service通过startService启动,并且不属于前面两类进程。这种进程一般在后台默默干活。

Background类

该类进程包含当前不可见的Activity(即它们的onStop被调用过)。系统保存这些进程到一个LRU(最近最少使用)列表。当系统需要回收内存时,该列表中哪些最近最少使用的进程将被杀死

Empty类

这类进程不包含任何组件。为什么会出现这种不包括任何组件的进程呢?是因为,假设该进程进创建一个Activity,它完成工作后主动调用finish函数销毁(destory)自己,之后该进程就会成为Empty进程。系统保留Empty进程的原因是当又重新需要它们时(例如用户在别的进程中通过startActivity启动了它们),可以省去fork进程、创建Android运行环境等一系列漫长而艰苦的工作

应用进程Crash处理

private static class UncaughtHandler implements Thread.UncaughtExceptionHandler {
    public void uncaughtException(Thread t, Throwable e) {
        try {
            // Don't re-enter -- avoid infinite loops if crash-reporting crashes.
            if (mCrashing) return;
            mCrashing = true;

            if (mApplicationObject == null) {
                Clog_e(TAG, "*** FATAL EXCEPTION IN SYSTEM PROCESS: " + t.getName(), e);
            } else {
                StringBuilder message = new StringBuilder();
                message.append("FATAL EXCEPTION: ").append(t.getName()).append("
");
                final String processName = ActivityThread.currentProcessName();
                if (processName != null) {
                    message.append("Process: ").append(processName).append(", ");
                }
                message.append("PID: ").append(Process.myPid());
                Clog_e(TAG, message.toString(), e);
            }

            // Bring up crash dialog, wait for it to be dismissed
            ActivityManagerNative.getDefault().handleApplicationCrash(
                    mApplicationObject, new ApplicationErrorReport.CrashInfo(e));
        } catch (Throwable t2) {
            try {
                Clog_e(TAG, "Error reporting crash", t2);
            } catch (Throwable t3) {
                // Even Clog_e() fails!  Oh well.
            }
        } finally {
            // Try everything to make sure this process goes away.
            Process.killProcess(Process.myPid());
            System.exit(10);
        }
    }
}

AMS

public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
    ProcessRecord r = findAppProcess(app, "Crash");
    final String processName = app == null ? "system_server"
            : (r == null ? "unknown" : r.processName);

    handleApplicationCrashInner("crash", r, processName, crashInfo);
}
private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
    long timeMillis = System.currentTimeMillis();
    String shortMsg = crashInfo.exceptionClassName;
    String longMsg = crashInfo.exceptionMessage;
    String stackTrace = crashInfo.stackTrace;
    if (shortMsg != null && longMsg != null) {
        longMsg = shortMsg + ": " + longMsg;
    } else if (shortMsg != null) {
        longMsg = shortMsg;
    }

    AppErrorResult result = new AppErrorResult();
    synchronized (this) {
        if (mController != null) {
            try {
                String name = r != null ? r.processName : null;
                int pid = r != null ? r.pid : Binder.getCallingPid();
                int uid = r != null ? r.info.uid : Binder.getCallingUid();
                if (!mController.appCrashed(name, pid,
                        shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
                    if ("1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"))
                            && "Native crash".equals(crashInfo.exceptionClassName)) {
                        Slog.w(TAG, "Skip killing native crashed app " + name
                                + "(" + pid + ") during testing");
                    } else {
                        Slog.w(TAG, "Force-killing crashed app " + name
                                + " at watcher's request");
                        if (r != null) {
                            r.kill("crash", true);
                        } else {
                            // Huh.
                            Process.killProcess(pid);
                            killProcessGroup(uid, pid);
                        }
                    }
                    return;
                }
            } catch (RemoteException e) {
                mController = null;
                Watchdog.getInstance().setActivityController(null);
            }
        }

        final long origId = Binder.clearCallingIdentity();

        // If this process is running instrumentation, finish it.
        if (r != null && r.instrumentationClass != null) {
            Slog.w(TAG, "Error in app " + r.processName
                  + " running instrumentation " + r.instrumentationClass + ":");
            if (shortMsg != null) Slog.w(TAG, "  " + shortMsg);
            if (longMsg != null) Slog.w(TAG, "  " + longMsg);
            Bundle info = new Bundle();
            info.putString("shortMsg", shortMsg);
            info.putString("longMsg", longMsg);
            finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
            Binder.restoreCallingIdentity(origId);
            return;
        }

        // Log crash in battery stats.
        if (r != null) {
            mBatteryStatsService.noteProcessCrash(r.processName, r.uid);
        }

        // If we can't identify the process or it's already exceeded its crash quota,
        // quit right away without showing a crash dialog.
        if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
            Binder.restoreCallingIdentity(origId);
            return;
        }

        Message msg = Message.obtain();
        msg.what = SHOW_ERROR_MSG;
        HashMap data = new HashMap();
        data.put("result", result);
        data.put("app", r);
        msg.obj = data;
        mUiHandler.sendMessage(msg);

        Binder.restoreCallingIdentity(origId);
    }

    int res = result.get();

    Intent appErrorIntent = null;
    synchronized (this) {
        if (r != null && !r.isolated) {
            // XXX Can't keep track of crash time for isolated processes,
            // since they don't have a persistent identity.
            mProcessCrashTimes.put(r.info.processName, r.uid,
                    SystemClock.uptimeMillis());
        }
        if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
            appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
        }
    }

    if (appErrorIntent != null) {
        try {
            mContext.startActivityAsUser(appErrorIntent, new UserHandle(r.userId));
        } catch (ActivityNotFoundException e) {
            Slog.w(TAG, "bug report receiver dissappeared", e);
        }
    }
}
private boolean makeAppCrashingLocked(ProcessRecord app,
        String shortMsg, String longMsg, String stackTrace) {
    app.crashing = true;
    app.crashingReport = generateProcessError(app,
            ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
    startAppProblemLocked(app);
    app.stopFreezingAllLocked();
    return handleAppCrashLocked(app, "force-crash" /*reason*/, shortMsg, longMsg, stackTrace);
}

面试:什么情况需要把进程移到前台?

解析:

1)进程中的某个Activity正在与用户进行交互(Activity的onResume()方法被调用)

2)绑定到与当前用户正在交互的activity的service所在的进程

3)进程中的某个service正运行在前台,即这个service的startForeground()方法被调用

4)进程中的某个Service正在执行生命周期回调方法(比如:onCreate()、onStart()或者onDestory())

5)进程中的BroadcastReceiver正在执行onReceive()方法

原文地址:https://www.cnblogs.com/anni-qianqian/p/7093742.html