我是靠谱客的博主 健壮黑猫,这篇文章主要介绍Android5.1--SystemServer进程SystemServer的创建过程SystemServer中的Watchdog,现在分享给大家,希望可以做个参考。
这篇博客作为自己的学习心得记录下来,欢迎提出问题,一起学习进步。
SystemServer是Android系统的核心之一,大部分Android提供的服务都运行在这个进程里,SystemServer中运行的服务总共有60多种。为了防止应用进程对系统造成破坏,Android的应用进程没有权限访问设备的底层资源,只能通过SystemServer中的服务代理访问。通过Binder,用户进程使用systemServer中的服务并没有太多的不便之处。
下面我们重点看下SystemServer的启动过程和它的WatchDog模块。
SystemServer的创建过程
SystemServer的创建可以分成两部分,一部分是在Zygote进程中fork并初始化SystemServer进程,另一部分是执行SystemServer类的main()方法来启动系统的服务。
创建SystemServer进程
Init.rc文件中定义的Zygote进程的启动参数包括了“--start-system-server”,因此,在ZygoteInit类的main()方法里会调用startSystemServer()方法,如下:
复制代码
1
2
3
4if (startSystemServer) { startSystemServer(abiList, socketName); }
复制代码
在startSystemServer()方法中,主要做了3件事,一是为SystemServer准备启动参数,从参数可以看到:SystemServer的进程Id和组Id都被指定为1000.SystemServer的执行类是com.android.server.SystemServer。二是调用Zygote类的forkSystemServer()来fork出SystemServer子进程。Zygote会检查SystemServer是否启动成功,如果不成功,Zygote进程会自动退出,重新启动一遍。三是fork出systemServer后,调用handleSystemServerProcess()来初始化SystemServer进程。如下:
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/** * Prepare the arguments and fork for the system server process. */ private static boolean startSystemServer(String abiList, String socketName) throws MethodAndArgsCaller, RuntimeException { long capabilities = posixCapabilitiesAsBits( OsConstants.CAP_BLOCK_SUSPEND, OsConstants.CAP_KILL, OsConstants.CAP_NET_ADMIN, OsConstants.CAP_NET_BIND_SERVICE, OsConstants.CAP_NET_BROADCAST, OsConstants.CAP_NET_RAW, OsConstants.CAP_SYS_MODULE, OsConstants.CAP_SYS_NICE, OsConstants.CAP_SYS_RESOURCE, OsConstants.CAP_SYS_TIME, OsConstants.CAP_SYS_TTY_CONFIG ); /* Hardcoded command line to start the system server */ String args[] = {//指定forkSystemServer所需要的参数 "--setuid=1000",//SYSTEM_UID "--setgid=1000", "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1032,3001,3002,3003,3006,3007", "--capabilities=" + capabilities + "," + capabilities, "--runtime-init", "--nice-name=system_server",//进程的名字 "com.android.server.SystemServer",//systemServer类的位置 }; ZygoteConnection.Arguments parsedArgs = null; int pid; try { parsedArgs = new ZygoteConnection.Arguments(args);//根据指定的参数,生成一个ZygoteConnection.Arguments对象 ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);//根据ro.debuggable属性值,设置parseArgs.debugFlags的值 ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs); /* Request to fork the system server process */ pid = Zygote.forkSystemServer( parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, parsedArgs.debugFlags, null, parsedArgs.permittedCapabilities, parsedArgs.effectiveCapabilities); } catch (IllegalArgumentException ex) { throw new RuntimeException(ex); } /* For child process */ if (pid == 0) { if (hasSecondZygote(abiList)) { waitForSecondaryZygote(socketName); } handleSystemServerProcess(parsedArgs); } return true; }
复制代码
handleSystemServerProcess()方法首先关闭了从zygote继承来的socket,接着将systemServer进程的umask设为0077(S_IRWXG|S_IRWXO),这样systemServer创建的文件的属性就是0700,只有systemServer进程可以访问。同时,进程名称修改为system_server。因为参数invokeWith通常为null,还是通过RuntimeInit的zygoteInit()方法来调用systemServer类的mian()方法。
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/** * Finish remaining work for the newly forked system server process. */ private static void handleSystemServerProcess( ZygoteConnection.Arguments parsedArgs) throws ZygoteInit.MethodAndArgsCaller { closeServerSocket();//Close and clean up zygote sockets. // set umask to 0077 so new files and directories will default to owner-only permissions. Os.umask(S_IRWXG | S_IRWXO); if (parsedArgs.niceName != null) { Process.setArgV0(parsedArgs.niceName);//修改进程名 } final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH"); if (systemServerClasspath != null) { performSystemServerDexOpt(systemServerClasspath); } if (parsedArgs.invokeWith != null) {//invokeWith通常为空 String[] args = parsedArgs.remainingArgs; // If we have a non-null system server class path, we'll have to duplicate the // existing arguments and append the classpath to it. ART will handle the classpath // correctly when we exec a new process. if (systemServerClasspath != null) { String[] amendedArgs = new String[args.length + 2]; amendedArgs[0] = "-cp"; amendedArgs[1] = systemServerClasspath; System.arraycopy(parsedArgs.remainingArgs, 0, amendedArgs, 2, parsedArgs.remainingArgs.length); } WrapperInit.execApplication(parsedArgs.invokeWith, parsedArgs.niceName, parsedArgs.targetSdkVersion, null, args); } else { ClassLoader cl = null; if (systemServerClasspath != null) { cl = new PathClassLoader(systemServerClasspath, ClassLoader.getSystemClassLoader()); Thread.currentThread().setContextClassLoader(cl); } /* * Pass the remaining arguments to SystemServer. */ RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl); } /* should never reach here */ }
SystemServer初始化
systemServer是java类,入口是mian()方法,如下:
复制代码
main()方法的主要作用是:
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90/** * The main entry point from zygote. */ public static void main(String[] args) { new SystemServer().run(); } public SystemServer() { // Check for factory test mode. mFactoryTestMode = FactoryTest.getMode(); } private void run() { // If a device's clock is before 1970 (before 0), a lot of // APIs crash dealing with negative numbers, notably // java.io.File#setLastModified, so instead we fake it and // hope that time from cell towers or NTP fixes it shortly. if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) { Slog.w(TAG, "System clock is before 1970; setting to 1970."); SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME); }//调整系统时间 // Here we go! Slog.i(TAG, "Entered the Android system server!"); EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, SystemClock.uptimeMillis()); // In case the runtime switched since last boot (such as when // the old runtime was removed in an OTA), set the system // property so that it is in sync. We can't do this in // libnativehelper's JniInvocation::Init code where we already // had to fallback to a different runtime because it is // running as root and we need to be the system user to set // the property. http://b/11463182 SystemProperties.set("persist.sys.dalvik.vm.lib.2", VMRuntime.getRuntime().vmLibrary());//设置当前虚拟机的运行库路径 // Enable the sampling profiler. if (SamplingProfilerIntegration.isEnabled()) { SamplingProfilerIntegration.start(); mProfilerSnapshotTimer = new Timer(); mProfilerSnapshotTimer.schedule(new TimerTask() { @Override public void run() { SamplingProfilerIntegration.writeSnapshot("system_server", null); } }, SNAPSHOT_INTERVAL, SNAPSHOT_INTERVAL); } // Mmmmmm... more memory! VMRuntime.getRuntime().clearGrowthLimit(); // The system server has to run all of the time, so it needs to be // as efficient as possible with its memory usage. VMRuntime.getRuntime().setTargetHeapUtilization(0.8f); // Some devices rely on runtime fingerprint generation, so make sure // we've defined it before booting further. Build.ensureFingerprintProperty(); // Within the system server, it is an error to access Environment paths without // explicitly specifying a user. Environment.setUserRequired(true); // Ensure binder calls into the system always run at foreground priority. BinderInternal.disableBackgroundScheduling(true); // Prepare the main looper thread (this thread). android.os.Process.setThreadPriority( android.os.Process.THREAD_PRIORITY_FOREGROUND); android.os.Process.setCanSelfBackground(false); Looper.prepareMainLooper(); // Initialize native services. System.loadLibrary("android_servers");//装载libandroid_servers.so nativeInit();//启动native层的service,Called to initialize native system services. // Check whether we failed to shut down last time we tried. // This call may not return. performPendingShutdown(); // Initialize the system context. createSystemContext(); // Create the system service manager. mSystemServiceManager = new SystemServiceManager(mSystemContext); LocalServices.addService(SystemServiceManager.class, mSystemServiceManager); // Start services. try {//启动所有的java service startBootstrapServices(); startCoreServices(); startOtherServices(); } catch (Throwable ex) { Slog.e("System", "******************************************"); Slog.e("System", "************ Failure starting system services", ex); // throw ex; } // For debug builds, log event loop stalls to dropbox for analysis. if (StrictMode.conditionallyEnableDebugLogging()) { Slog.i(TAG, "Enabled StrictMode for system server main thread."); } // Loop forever. Looper.loop(); throw new RuntimeException("Main thread loop unexpectedly exited"); }
(1)、设置属性persist.sys.dalvik.vm.lib.2的值为当前虚拟机的运行库路径。
(2)、调整时间。
(3)、调整虚拟机堆的内存。设定虚拟机堆利用率为0.8,当实际的使用率偏离设定的比率时,虚拟机在垃圾回收的时候将调整堆的大小,使实际使用率接近设定的百分比。
(4)、装载libandroid_servers.so库。这个库的源文件位于frameworksbaseservicescorejni。
(5)、调用nativeInit()方法初始化native层的Binder服务。这里native层的服务只有SensorService。
对应的native层函数是android_server_SystemServer_nativeInit(),如下:
复制代码
如果属性system_init.startsensorservice设置为1,就启动SensorService服务。SensorService提供的是各种传感器的服务,也是SystemServer中唯一的本地服务。
1
2
3
4
5
6
7
8static void android_server_SystemServer_nativeInit(JNIEnv* env, jobject clazz) { char propBuf[PROPERTY_VALUE_MAX]; property_get("system_init.startsensorservice", propBuf, "1"); if (strcmp(propBuf, "1") == 0) { // Start the sensor service SensorService::instantiate(); } }
(6)、调用createSystemContext()来获取Context,相当于创建了一个framework-res.apk的上下文环境。
(7)、创建SystemServiceManager对象mSystemServiceManager。这个对象负责系统Service的启动。
(8)、startBootstrapServices()、startCoreServices()、startOtherServices()创建并运行所有java服务。
(9)、调用Loop.loop(),进入处理消息的循环。
SystemServer中的Watchdog
Android开发了WatchDog类作为软件看门狗来监控SystemServer进程,一旦发现问题,WatchDog会杀死SystemServer进程。SystemServer的父进程Zygote接收到SystemServer的死亡信号后,会杀死自己。Zygote进程的死亡信号传递到Init进程后,Init进程会杀死Zygote进程所有子进程并重启Zygote。这样整个手机相当于重启一遍。
启动WatchDog
在SystemServer中创建WatchDog对象,如下:
在startOtherService()方法中:
复制代码
1
2
3
4Slog.i(TAG, "Init Watchdog"); final Watchdog watchdog = Watchdog.getInstance(); watchdog.init(context, mActivityManagerService);
WatchDog是单实例的运行模式。
复制代码
WatchDog的构造方法主要工作是创建几个HandlerChecker对象,并把他们保存到数组列表mHandlerCheckers中。每个HandlerChecker对象对应一个被监控的线程。HandlerCHecker类从Handler类派生,在构造时就和被监控的线程关联在一起。
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
35public static Watchdog getInstance() { if (sWatchdog == null) { sWatchdog = new Watchdog(); } return sWatchdog; } private Watchdog() { super("watchdog"); // Initialize handler checkers for each common thread we want to check. Note // that we are not currently checking the background thread, since it can // potentially hold longer running operations with no guarantees about the timeliness // of operations there. // The shared foreground thread is the main checker. It is where we // will also dispatch monitor checks and do other work. mMonitorChecker = new HandlerChecker(FgThread.getHandler(), "foreground thread", DEFAULT_TIMEOUT); mHandlerCheckers.add(mMonitorChecker); // Add checker for main thread. We only do a quick check since there // can be UI running on the thread. mHandlerCheckers.add(new HandlerChecker(new Handler(Looper.getMainLooper()), "main thread", DEFAULT_TIMEOUT)); // Add checker for shared UI thread. mHandlerCheckers.add(new HandlerChecker(UiThread.getHandler(), "ui thread", DEFAULT_TIMEOUT)); // And also check IO thread. mHandlerCheckers.add(new HandlerChecker(IoThread.getHandler(), "i/o thread", DEFAULT_TIMEOUT)); // And the display thread. mHandlerCheckers.add(new HandlerChecker(DisplayThread.getHandler(), "display thread", DEFAULT_TIMEOUT)); }
WatchDog对象创建后,接下来会调用init()方法进行初始化,
复制代码
注册了RebootRequestReceiver,监听重启的intent:ACTION_REBOOT。
1
2
3
4
5
6
7
8public void init(Context context, ActivityManagerService activity) { mResolver = context.getContentResolver(); mActivity = activity; context.registerReceiver(new RebootRequestReceiver(), new IntentFilter(Intent.ACTION_REBOOT), android.Manifest.permission.REBOOT, null); }
WatchDog监控的服务和线程
WatchDog主要监控线程。如果一个线程陷入了死循环或者和其他的线程相互死锁了,WatchDog需要有办法识别出它们。
WatchDog中提供的两个方法addThread和addMonitor()方法分别用来增加需要监控的线程和服务。addThread()实际是创建一个和受监控对象关联的HandlerChecker对象。
复制代码
对服务的监控也是由HandlerChecker对象来完成。一个HandlerChecker对象就可以检查所有服务。因此,WatchDog让mMonitorChecker对象来完成这个任务。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15public void addThread(Handler thread) { addThread(thread, DEFAULT_TIMEOUT); } public void addThread(Handler thread, long timeoutMillis) { synchronized (this) { if (isAlive()) { throw new RuntimeException("Threads can't be added once the Watchdog is running"); } final String name = thread.getLooper().getThread().getName(); mHandlerCheckers.add(new HandlerChecker(thread, name, timeoutMillis)); } }
复制代码
WatchDog的addMonitor()方法只是调用了mMonitorChecker对象的addMonitor方法。
1
2
3
4
5
6
7
8
9public void addMonitor(Monitor monitor) { synchronized (this) { if (isAlive()) { throw new RuntimeException("Monitors can't be added once the Watchdog is running"); } mMonitorChecker.addMonitor(monitor); } }
在WatchDog的构造函数中,把5个公共线程加入到了监控列表中。
- 主线程
- FgThread
- UiThread。
- IoThread。
- DisplayThread。
SystemServer中一些重要的服务拥有专用的线程来处理消息。除了这5个公共线程外,一些重要服务的专用线程也加入到了监控中,包括:
- ActivityManagerService的AThread线程。
- PackageManagerService的mHandlerThread变量表示的线程。
- PowerManagerService的线程。
- WindowManagerService的wmHandlerThread变量表示的线程。
如果一个服务需要通过WatchDog来监控,它必须首先实现WatchDog的接口Moniter:
复制代码
然后还要调用WatchDog类的addMonitor()方法把它自己加入到WatchDog的服务监控列表中。在systemServer中实现了Moniter接口并调用了addMonitor()方法的服务有。
1
2
3
4public interface Monitor { void monitor(); }
- ActivityManagerService
- InputManagerService
- MediaRouterService。
- MountService。
- NativeDaemonConnector。
- NetworkManagementService。
- PowerManagerService
- WindowManagerService。
WatchDog监控的原理
通过给现场发送消息可以判断一个线程是否运行正常,如果发送的消息不能在规定的时间内得到处理,就表明线程被不正常占用了。
WatchDog运行在一个单独的线程中,如下:
复制代码
run()方法中有一个无限循环,每次循环主要做3件事。
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180public void run() { boolean waitedHalf = false; while (true) { final ArrayList<HandlerChecker> blockedCheckers; final String subject; final boolean allowRestart; int debuggerWasConnected = 0; synchronized (this) { long timeout = CHECK_INTERVAL; // Make sure we (re)spin the checkers that have become idle within // this wait-and-check interval给监控的线程发送消息 for (int i=0; i<mHandlerCheckers.size(); i++) { HandlerChecker hc = mHandlerCheckers.get(i); hc.scheduleCheckLocked(); } if (debuggerWasConnected > 0) { debuggerWasConnected--; } // NOTE: We use uptimeMillis() here because we do not want to increment the time we // wait while asleep. If the device is asleep then the thing that we are waiting // to timeout on is asleep as well and won't have a chance to run, causing a false // positive on when to kill things. long start = SystemClock.uptimeMillis(); while (timeout > 0) {//睡眠一段时间 if (Debug.isDebuggerConnected()) { debuggerWasConnected = 2; } try { wait(timeout); } catch (InterruptedException e) { Log.wtf(TAG, e); } if (Debug.isDebuggerConnected()) { debuggerWasConnected = 2; } timeout = CHECK_INTERVAL - (SystemClock.uptimeMillis() - start); } //检查是否有线程或服务出问题 final int waitState = evaluateCheckerCompletionLocked(); if (waitState == COMPLETED) { // The monitors have returned; reset waitedHalf = false; continue; } else if (waitState == WAITING) { // still waiting but within their configured intervals; back off and recheck continue; } else if (waitState == WAITED_HALF) { if (!waitedHalf) { // We've waited half the deadlock-detection interval. Pull a stack // trace and wait another half. ArrayList<Integer> pids = new ArrayList<Integer>(); pids.add(Process.myPid()); ActivityManagerService.dumpStackTraces(true, pids, null, null, NATIVE_STACKS_OF_INTEREST); waitedHalf = true; } continue; } // something is overdue! blockedCheckers = getBlockedCheckersLocked(); subject = describeCheckersLocked(blockedCheckers); allowRestart = mAllowRestart; } // If we got here, that means that the system is most likely hung. // First collect stack traces from all threads of the system process. // Then kill this process so that the system will restart. EventLog.writeEvent(EventLogTags.WATCHDOG, subject); ArrayList<Integer> pids = new ArrayList<Integer>(); pids.add(Process.myPid()); if (mPhonePid > 0) pids.add(mPhonePid); // Pass !waitedHalf so that just in case we somehow wind up here without having // dumped the halfway stacks, we properly re-initialize the trace file. final File stack = ActivityManagerService.dumpStackTraces( !waitedHalf, pids, null, null, NATIVE_STACKS_OF_INTEREST); // Give some extra time to make sure the stack traces get written. // The system's been hanging for a minute, another second or two won't hurt much. SystemClock.sleep(2000); // Pull our own kernel thread stacks as well if we're configured for that if (RECORD_KERNEL_THREADS) { dumpKernelStackTraces(); } // Trigger the kernel to dump all blocked threads, and backtraces on all CPUs to the kernel log doSysRq('w'); doSysRq('l'); String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null); String traceFileNameAmendment = "_SystemServer_WDT" + mTraceDateFormat.format(new Date()); if (tracesPath != null && tracesPath.length() != 0) { File traceRenameFile = new File(tracesPath); String newTracesPath; int lpos = tracesPath.lastIndexOf ("."); if (-1 != lpos) newTracesPath = tracesPath.substring (0, lpos) + traceFileNameAmendment + tracesPath.substring (lpos); else newTracesPath = tracesPath + traceFileNameAmendment; traceRenameFile.renameTo(new File(newTracesPath)); tracesPath = newTracesPath; } final File newFd = new File(tracesPath); // Try to add the error to the dropbox, but assuming that the ActivityManager // itself may be deadlocked. (which has happened, causing this statement to // deadlock and the watchdog as a whole to be ineffective) Thread dropboxThread = new Thread("watchdogWriteToDropbox") { public void run() { mActivity.addErrorToDropBox( "watchdog", null, "system_server", null, null, subject, null, newFd, null); } }; dropboxThread.start(); try { dropboxThread.join(2000); // wait up to 2 seconds for it to return. } catch (InterruptedException ignored) {} // At times, when user space watchdog traces don't give an indication on // which component held a lock, because of which other threads are blocked, // (thereby causing Watchdog), crash the device to analyze RAM dumps boolean crashOnWatchdog = SystemProperties .getBoolean("persist.sys.crashOnWatchdog", false); if (crashOnWatchdog) { // wait until the above blocked threads be dumped into kernel log SystemClock.sleep(3000); // now try to crash the target try { FileWriter sysrq_trigger = new FileWriter("/proc/sysrq-trigger"); sysrq_trigger.write("c"); sysrq_trigger.close(); } catch (IOException e) { Slog.e(TAG, "Failed to write 'c' to /proc/sysrq-trigger"); Slog.e(TAG, e.getMessage()); } } IActivityController controller; synchronized (this) { controller = mController; } if (controller != null) { Slog.i(TAG, "Reporting stuck state to activity controller"); try { Binder.setDumpDisabled("Service dumps disabled due to hung system process."); // 1 = keep waiting, -1 = kill system int res = controller.systemNotResponding(subject); if (res >= 0) { Slog.i(TAG, "Activity controller requested to coninue to wait"); waitedHalf = false; continue; } } catch (RemoteException e) { } } // Only kill the process if the debugger is not attached. if (Debug.isDebuggerConnected()) { debuggerWasConnected = 2; } if (debuggerWasConnected >= 2) { Slog.w(TAG, "Debugger connected: Watchdog is *not* killing the system process"); } else if (debuggerWasConnected > 0) { Slog.w(TAG, "Debugger was connected: Watchdog is *not* killing the system process"); } else if (!allowRestart) { Slog.w(TAG, "Restart not allowed: Watchdog is *not* killing the system process"); } else { Slog.w(TAG, "*** WATCHDOG KILLING SYSTEM PROCESS: " + subject); for (int i=0; i<blockedCheckers.size(); i++) { Slog.w(TAG, blockedCheckers.get(i).getName() + " stack trace:"); StackTraceElement[] stackTrace = blockedCheckers.get(i).getThread().getStackTrace(); for (StackTraceElement element: stackTrace) { Slog.w(TAG, " at " + element); } } Slog.w(TAG, "*** GOODBYE!"); Process.killProcess(Process.myPid()); System.exit(10); } waitedHalf = false; } }
(1)调用scheduleCheckLocked()方法给所有受监控的线程发送消息。
复制代码
HandlerCHecker对象既要监控服务,又要监控某个线程;因此先判断mMonitors的size是否为0,如果为0,说明这个HandlerChecker没有监控服务,这时如果被监控线程的消息队列处于空闲状态(isIding()方法判断),则说明线程运行良好,把mCompleted设为true后就可以返回了。否则先把mCompleted设为false,并记录消息开始发送的时间,最后调用postAtFrontOfQueue()方法给被监控的线程发送一个消息。这个消息的处理方法是HandlerChecker类的run()方法,如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23public void scheduleCheckLocked() { if (mMonitors.size() == 0 && mHandler.getLooper().isIdling()) { // If the target looper is or just recently was idling, then // there is no reason to enqueue our checker on it since that // is as good as it not being deadlocked. This avoid having // to do a context switch to check the thread. Note that we // only do this if mCheckReboot is false and we have no // monitors, since those would need to be executed at this point. mCompleted = true; return; } if (!mCompleted) { // we already have a check in flight, so no need return; } mCompleted = false; mCurrentMonitor = null; mStartTime = SystemClock.uptimeMillis(); mHandler.postAtFrontOfQueue(this); }
复制代码
如果消息处理方法run()能够执行,说明受监控的线程本身没有问题。但是,还要检查被监控服务的状态。检查是通过调用服务中实现的monitor()方法来完成的。通常monitor()方法的实现是获取服务中的锁,如果不能得到,线程就会挂起,这样mCompleted的值就不能被设为true。
1
2
3
4
5
6
7
8
9
10
11
12
13
14public void run() { final int size = mMonitors.size(); for (int i = 0 ; i < size ; i++) { synchronized (Watchdog.this) { mCurrentMonitor = mMonitors.get(i); } mCurrentMonitor.monitor(); } synchronized (Watchdog.this) { mCompleted = true; mCurrentMonitor = null; } }
mCompleted的值为true,表面HandlerChecker对象监控的线程或服务正常。否则就有空有问题。是否真有问题还要通过等待的时间是否超过规定时间来判断。
(2)、给受监控的线程发送完消息后,调用wait()方法让WatchDog线程睡眠一段时间。
(3)、逐个检查是否有线程或服务出问题了,一旦发现,马上杀死进程。
通过evaluateCheckerCompletionLocked()方法来检查,如下:
复制代码
evaluateCheckerCompletionLocked()通过调用每个检查对象的getCompletionStatelocked()方法来得到对象的状态值。状态值有4种。
1
2
3
4
5
6
7
8
9private int evaluateCheckerCompletionLocked() { int state = COMPLETED; for (int i=0; i<mHandlerCheckers.size(); i++) { HandlerChecker hc = mHandlerCheckers.get(i); state = Math.max(state, hc.getCompletionStateLocked()); } return state; }
- COMPLETED:0,表示状态良好。
- WAITING:1,表示正在等待消息处理的结果。
- WAITED_HALF:2,表示正在等待并且等待的时间超过了规定时间的一半。
- OVERDUE:3,表示等待时间已经超过了规定的时间。
evaluateCheckerCompletionLocked()方法希望知道的是最坏的情况,因此上面代码中使用Math.max()方法来计算出所有监控对象的最坏情况。
OVERDUE状态就会杀死SystemServer进程。
最后
以上就是健壮黑猫最近收集整理的关于Android5.1--SystemServer进程SystemServer的创建过程SystemServer中的Watchdog的全部内容,更多相关Android5.1--SystemServer进程SystemServer内容请搜索靠谱客的其他文章。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复