当前位置:   article > 正文

android8.1启动过程(九) SystemServer启动FallbackHome_android fallbackhome 启动方式

android fallbackhome 启动方式

SystemServer进程在启动的过程中会启动PackageManagerService,PackageManagerService启动后会将系统中的应用程序安装完成。在此前已经启动的AMS会将Launcher启动起来。

Launcher的入口为AMSsystemReady方法


1

ActivityManagerDebugConfig    frameworks/base/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java

这里首先分享一个技巧  可以把这个类里面的这个属性设置为true这样就可以把ActivityManager相关的log打开了

  1. // Enable all debug log categories.
  2. // static final boolean DEBUG_ALL = false;
  3. static final boolean DEBUG_ALL = true;

2

startOtherServices()    frameworks/base/services/java/com/android/server/SystemServer.java

  此处是一个Lambda表达式省略的部分是一个回调方法

  1. mActivityManagerService.systemReady(
  2. ...
  3. )

3

systemReady()    frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

  这里关于EventLog分享一个查看log的链接https://www.jianshu.com/p/1c9106dd8284

  android日志主要分为  kernel、radio、event、main

  adb logcat -b  xxx

  1. 130|generic_x86_64:/ # logcat -b events | grep "3040"
  2. 06-02 00:18:02.017 1541 1556 I am_pss : [2069,10015,com.android.launcher,31063040,17305600,0]
  3. 06-02 00:22:02.033 1541 1556 I am_pss : [2069,10015,com.android.launcher,31063040,17305600,0]
  4. 06-02 04:48:12.311 1541 1556 I am_pss : [2069,10015,com.android.launcher,32285696,18903040,0]
  5. 06-02 09:19:17.510 1541 1556 I am_pss : [2069,10015,com.android.launcher,33040384,19652608,0]
  6. 06-02 17:51:00.018 1541 1556 I am_pss : [1710,1001,com.android.phone,31703040,20111360,0]
  7. 06-02 19:26:00.039 1541 1556 I am_pss : [2069,10015,com.android.launcher,34850816,21463040,0]
  1. public void systemReady(final Runnable goingCallback, TimingsTraceLog traceLog) {
  2. traceLog.traceBegin("PhaseActivityManagerReady");
  3. ...
  4. Slog.i(TAG, "System now ready");
  5. EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
  6. SystemClock.uptimeMillis());
  7. ...
  8. }

关于工厂模式FactoryTest可参考这篇文章  https://blog.csdn.net/thl789/article/details/8053574 这里是正常模式

  1. ...
  2. //判断工厂模式
  3. synchronized(this) {
  4. // Make sure we have no pre-ready processes sitting around.
  5. if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL)
  6. ...

 startPersistentApps    只启动加密感知的持久应用程序;一旦用户被解锁,我们将返回并启动不知情的应用程序可参考这篇文章    

https://blog.csdn.net/yaobao888/article/details/77824950

https://www.jianshu.com/p/c9e43905e6b6

https://www.jianshu.com/p/3db7809f231e

  1. ...
  2. synchronized (this) {
  3. // Only start up encryption-aware persistent apps; once user is
  4. // unlocked we'll come back around and start unaware apps
  5. startPersistentApps(PackageManager.MATCH_DIRECT_BOOT_AWARE);
  6. ...

启动Launcher 

startHomeActivityLocked(currentUserId, "systemReady");

4

startHomeActivityLocked()    frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

这里介绍来自这篇  https://blog.csdn.net/learnframework?spm=1001.2014.3001.5509

    这里看到了startHomeActivityLocked(currentUserId, “systemReady”);被调用,从名字既可以看得出他是要启动Home类型的Activtiy,常见的Launcher就是一种Home类型的Activity,但这里其实并不是Launcher,而是设置中的FallbackHome类型的,它也是一个Home类型的Activity,这里FallbackHome是google新加入的,主要就是因为涉及整个android系统的加密等原因,系统在还没有完全解锁前,不可以启动Launcher,因为Launcher中明显和各个第三方应用耦合较多(比如桌面可能显示着一堆的各个应用的Widget),如果直接Launcher作为FallbackHome启动,相对就会要求Launcher依赖的应用也是支持直接解密类型,那就肯定不现实。所以就先启动了FallbackHome一个什么也不显示的界面来作为启动真正Launcher的一个过度

  1. boolean startHomeActivityLocked(int userId, String reason) {
  2. if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL
  3. && mTopAction == null) {
  4. // We are running in factory test mode, but unable to find
  5. // the factory test app, so just sit around displaying the
  6. // error message and don't try to start anything.
  7. return false;
  8. }
  9. Intent intent = getHomeIntent();
  10. ...
  11. }

5

getHomeIntent()  frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

在这个方法中创建了Intent  并将mTopActionmTopData传入,

String mTopAction = Intent.ACTION_MAIN;

和若是系统运行模式不是低级工厂模式则将Intent的Category设置为Intent.CATEGORY_HOME后返回。

  1. Intent getHomeIntent() {
  2. Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);
  3. intent.setComponent(mTopComponent);
  4. intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
  5. if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
  6. intent.addCategory(Intent.CATEGORY_HOME);
  7. }
  8. return intent;
  9. }

6

startHomeActivityLocked()    frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

  继续来分析startHomeActivityLocked方法

  resolveActivityInfo  此前已经说过,系统在还没有完全解锁前,不可以启动Launcher。所以这里其实并不是Launcher,而是设置中的FallbackHome类型的,它也是一个Home类型的Activity

  ProcessRecord  Android系统中用于描述进程的数据结构是ProcessRecord对象,AMS便是管理进程的核心模块  可以参考https://www.cnblogs.com/mingfeng002/p/10573298.html

  此处的ProcessRecord app  应该是设置的包名  此时调用getProcessRecordLocked获取的就是设置的进程因为目前android程序还没有启动所以这是获取不到的  app就返回为null再调用后面的启动

  1. boolean startHomeActivityLocked(int userId, String reason) {
  2. ...
  3. Intent intent = getHomeIntent();
  4. ActivityInfo aInfo = resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);
  5. if (aInfo != null) {
  6. ...
  7. ProcessRecord app = getProcessRecordLocked(aInfo.processName,
  8. aInfo.applicationInfo.uid, true);
  9. if (app == null || app.instr == null) {
  10. intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
  11. final int resolvedUserId = UserHandle.getUserId(aInfo.applicationInfo.uid);
  12. // For ANR debugging to verify if the user activity is the one that actually
  13. // launched.
  14. final String myReason = reason + ":" + userId + ":" + resolvedUserId;
  15. mActivityStarter.startHomeActivityLocked(intent, aInfo, myReason);
  16. }
  17. } else {
  18. Slog.wtf(TAG, "No home screen found for " + intent, new Throwable());
  19. }
  20. return true;
  21. }

7

mActivityStarter.startHomeActivityLocked()       frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java

  这里目前就调用了startActivityLocked()

  1. void startHomeActivityLocked(Intent intent, ActivityInfo aInfo, String reason) {
  2. mSupervisor.moveHomeStackTaskToTop(reason);
  3. mLastHomeActivityStartResult = startActivityLocked(null /*caller*/, intent,
  4. null /*ephemeralIntent*/, null /*resolvedType*/, aInfo, null /*rInfo*/,
  5. null /*voiceSession*/, null /*voiceInteractor*/, null /*resultTo*/,
  6. null /*resultWho*/, 0 /*requestCode*/, 0 /*callingPid*/, 0 /*callingUid*/,
  7. null /*callingPackage*/, 0 /*realCallingPid*/, 0 /*realCallingUid*/,
  8. 0 /*startFlags*/, null /*options*/, false /*ignoreTargetSecurity*/,
  9. false /*componentSpecified*/, mLastHomeActivityStartRecord /*outActivity*/,
  10. null /*inTask*/, "startHomeActivity: " + reason);
  11. ...
  12. }
  13. }

8

startActivityLocked()   frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java

  1. int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
  2. String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
  3. IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
  4. IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
  5. String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
  6. ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
  7. ActivityRecord[] outActivity, TaskRecord inTask, String reason) {
  8. ...
  9. mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType,
  10. aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode,
  11. callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
  12. options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord,
  13. inTask);
  14. ...
  15. }

9

startActivity()  frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java

   这里更新一个知识点,frameworks/base/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java

  // Enable all debug log categories.

  static final boolean DEBUG_ALL = false;     打开debuglog

ActivityRecord  Activity的信息记录在ActivityRecord对象, 并通过通过成员变量task指向TaskRecord    可以参考https://blog.csdn.net/b1480521874/article/details/84637592

注意这块最后调用startActivity的第六个参数为 true

  1. /** DO NOT call this method directly. Use {@link #startActivityLocked} instead. */
  2. private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
  3. String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
  4. IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
  5. IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
  6. String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
  7. ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
  8. ActivityRecord[] outActivity, TaskRecord inTask) {
  9. ...
  10. ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
  11. callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
  12. resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
  13. mSupervisor, options, sourceRecord);
  14. if (outActivity != null) {
  15. outActivity[0] = r;
  16. }
  17. ...
  18. return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true,
  19. options, inTask, outActivity);
  20. }

10

startActivity()  frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java

  显然这个doResume参数为true  继续调用startActivityUnchecked

  1. private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
  2. IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
  3. int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
  4. ActivityRecord[] outActivity) {
  5. ...
  6. result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
  7. startFlags, doResume, options, inTask, outActivity);
  8. ...
  9. }

11

startActivityUnchecked()  frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java

  这里面调用的setInitialState会将mDoResume这个字段置为 true

  接下来调用了mSupervisor.resumeFocusedStackTopActivityLocked

  1. // Note: This method should only be called from {@link startActivity}.
  2. private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
  3. IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
  4. int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
  5. ActivityRecord[] outActivity) {
  6. ...
  7. setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
  8. voiceInteractor);
  9. ...
  10. if (mDoResume) {
  11. final ActivityRecord topTaskActivity =
  12. mStartActivity.getTask().topRunningActivityLocked();
  13. if (!mTargetStack.isFocusable()
  14. || (topTaskActivity != null && topTaskActivity.mTaskOverlay
  15. && mStartActivity != topTaskActivity)) {
  16. ...
  17. } else {
  18. // If the target stack was not previously focusable (previous top running activity
  19. // on that stack was not visible) then any prior calls to move the stack to the
  20. // will not update the focused stack. If starting the new activity now allows the
  21. // task stack to be focusable, then ensure that we now update the focused stack
  22. // accordingly.
  23. if (mTargetStack.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) {
  24. mTargetStack.moveToFront("startActivityUnchecked");
  25. }
  26. mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
  27. mOptions);
  28. }
  29. } else {
  30. ...
  31. }
  32. }

12

resumeFocusedStackTopActivityLocked()    frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java

  这块调用到了targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);

  1. boolean resumeFocusedStackTopActivityLocked(
  2. ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
  3. ...
  4. if (targetStack != null && isFocusedStack(targetStack)) {
  5. return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
  6. }
  7. ...
  8. return false;
  9. }

13

resumeTopActivityUncheckedLocked()    frameworks/base/services/core/java/com/android/server/am/ActivityStack.java

  这块调用到了result = resumeTopActivityInnerLocked(prev, options);

  1. boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
  2. ...
  3. try {
  4. // Protect against recursion.
  5. mStackSupervisor.inResumeTopActivity = true;
  6. result = resumeTopActivityInnerLocked(prev, options);
  7. } finally {
  8. mStackSupervisor.inResumeTopActivity = false;
  9. }
  10. ...
  11. return result;
  12. }

14

resumeTopActivityInnerLocked()      frameworks/base/services/core/java/com/android/server/am/ActivityStack.java

  由于这块代码实在是太多太复杂了  这里只给出结论,无论这中间代码是如何调用的在这个方法的最后打出了一个log

  “resumeTopActivityLocked: Restarting”    显然这里面最后调用了  mStackSupervisor.startSpecificActivityLocked(next, true, true);

  1. private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
  2. ...
  3. } else {
  4. // Whoops, need to restart this activity!
  5. if (!next.hasBeenLaunched) {
  6. next.hasBeenLaunched = true;
  7. } else {
  8. if (SHOW_APP_STARTING_PREVIEW) {
  9. next.showStartingWindow(null /* prev */, false /* newTask */,
  10. false /* taskSwich */);
  11. }
  12. if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Restarting: " + next);
  13. }
  14. if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Restarting " + next);
  15. mStackSupervisor.startSpecificActivityLocked(next, true, true);
  16. }
  17. }

15

startSpecificActivityLocked()    frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java

  此部分代码进程为空  接下来调用 mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,"activity", r.intent.getComponent(), false, false, true);

  注意这个地方倒数第二个参数  isolated 传递的为  false

  1. void startSpecificActivityLocked(ActivityRecord r,
  2. boolean andResume, boolean checkConfig) {
  3. // Is this activity's application already running?
  4. ProcessRecord app = mService.getProcessRecordLocked(r.processName,
  5. r.info.applicationInfo.uid, true);
  6. r.getStack().setLaunchTime(r);
  7. if (app != null && app.thread != null) {
  8. ...
  9. }
  10. mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
  11. "activity", r.intent.getComponent(), false, false, true);
  12. }

16

startProcessLocked()    frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

  调用自己的重载方法 

  此时  isolated 为  false 

           entryPoint 为 null

startProcessLocked(processName, info, knownToBeDead, intentFlags, hostingType, hostingName, allowWhileBooting, isolated, 0 /* isolatedUid */, keepIfLarge, null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */, null /* crashHandler */);

  1. final ProcessRecord startProcessLocked(String processName,
  2. ApplicationInfo info, boolean knownToBeDead, int intentFlags,
  3. String hostingType, ComponentName hostingName, boolean allowWhileBooting,
  4. boolean isolated, boolean keepIfLarge) {
  5. return startProcessLocked(processName, info, knownToBeDead, intentFlags, hostingType,
  6. hostingName, allowWhileBooting, isolated, 0 /* isolatedUid */, keepIfLarge,
  7. null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */,
  8. null /* crashHandler */);
  9. }

17

startProcessLocked()    frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

  这个方法主要接下来创建进程

  isolated 为  false 

  entryPoint 为 null

  最后调用了startProcessLocked(app, hostingType, hostingNameStr, abiOverride, entryPoint, entryPointArgs);

  1. final ProcessRecord startProcessLocked(String processName, ApplicationInfo info,
  2. boolean knownToBeDead, int intentFlags, String hostingType, ComponentName hostingName,
  3. boolean allowWhileBooting, boolean isolated, int isolatedUid, boolean keepIfLarge,
  4. String abiOverride, String entryPoint, String[] entryPointArgs, Runnable crashHandler) {
  5. if (!isolated) {
  6. app = getProcessRecordLocked(processName, info.uid, keepIfLarge);
  7. //这里app还是为null
  8. checkTime(startTime, "startProcess: after getProcessRecord");
  9. if ((intentFlags & Intent.FLAG_FROM_BACKGROUND) != 0) {
  10. ...//不走
  11. } else {
  12. // When the user is explicitly starting a process, then clear its
  13. // crash count so that we won't make it bad until they see at
  14. // least one crash dialog again, and make the process good again
  15. // if it had been bad.
  16. if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid
  17. + "/" + info.processName);
  18. mAppErrors.resetProcessCrashTimeLocked(info);
  19. if (mAppErrors.isBadProcessLocked(info)) {
  20. EventLog.writeEvent(EventLogTags.AM_PROC_GOOD,
  21. UserHandle.getUserId(info.uid), info.uid,
  22. info.processName);
  23. mAppErrors.clearBadProcessLocked(info);
  24. if (app != null) {
  25. app.bad = false;
  26. }
  27. }
  28. }
  29. } else {
  30. ...
  31. }
  32. ...
  33. if (app == null) {
  34. checkTime(startTime, "startProcess: creating new process record");
  35. app = newProcessRecordLocked(info, processName, isolated, isolatedUid);
  36. if (app == null) {
  37. ...//不走
  38. }
  39. app.crashHandler = crashHandler;
  40. checkTime(startTime, "startProcess: done creating new process record");
  41. } else {
  42. ...//不走
  43. }
  44. ...
  45. startProcessLocked(
  46. app, hostingType, hostingNameStr, abiOverride, entryPoint, entryPointArgs);
  47. checkTime(startTime, "startProcess: done starting proc!");
  48. return (app.pid != 0) ? app : null;
  49. }

18

startProcessLocked()    frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

  entryPoint 为 null

  if (entryPoint == null) entryPoint = "android.app.ActivityThread";   构建启动参数 这个参数是最后剩下的在Zygote中用来反射调用main函数的

  最后调用了这个  Process.start(entryPoint, app.processName, uid, uid, gids, debugFlags, mountExternal, app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet, app.info.dataDir, invokeWith, entryPointArgs);

  注意这个时候把新new出来的ProcessRecord放到mPidsSelfLocked  this.mPidsSelfLocked.put(startResult.pid, app);

  1. private final void startProcessLocked(ProcessRecord app, String hostingType,
  2. String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
  3. ...
  4. if (entryPoint == null) entryPoint = "android.app.ActivityThread";
  5. Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +
  6. app.processName);
  7. checkTime(startTime, "startProcess: asking zygote to start proc");
  8. ProcessStartResult startResult;
  9. if (hostingType.equals("webview_service")) {
  10. ...//不走
  11. } else {
  12. startResult = Process.start(entryPoint,
  13. app.processName, uid, uid, gids, debugFlags, mountExternal,
  14. app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
  15. app.info.dataDir, invokeWith, entryPointArgs);
  16. }
  17. ...
  18. synchronized (mPidsSelfLocked) {
  19. this.mPidsSelfLocked.put(startResult.pid, app);
  20. if (isActivityProcess) {
  21. Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
  22. msg.obj = app;
  23. mHandler.sendMessageDelayed(msg, startResult.usingWrapper
  24. ? PROC_START_TIMEOUT_WITH_WRAPPER : PROC_START_TIMEOUT);
  25. }
  26. }
  27. }

19

Process.start()    frameworks/base/core/java/android/os/Process.java

  一眼望去  zygoteProcess.start(processClass, niceName, uid, gid, gids, debugFlags, mountExternal, targetSdkVersion, seInfo, abi, instructionSet, appDataDir, invokeWith, zygoteArgs);

  1. public static final ProcessStartResult start(final String processClass,
  2. final String niceName,
  3. int uid, int gid, int[] gids,
  4. int debugFlags, int mountExternal,
  5. int targetSdkVersion,
  6. String seInfo,
  7. String abi,
  8. String instructionSet,
  9. String appDataDir,
  10. String invokeWith,
  11. String[] zygoteArgs) {
  12. return zygoteProcess.start(processClass, niceName, uid, gid, gids,
  13. debugFlags, mountExternal, targetSdkVersion, seInfo,
  14. abi, instructionSet, appDataDir, invokeWith, zygoteArgs);
  15. }

20 

start()    frameworks/base/core/java/android/os/ZygoteProcess.java

  1. public final Process.ProcessStartResult start(final String processClass,
  2. final String niceName,
  3. int uid, int gid, int[] gids,
  4. int debugFlags, int mountExternal,
  5. int targetSdkVersion,
  6. String seInfo,
  7. String abi,
  8. String instructionSet,
  9. String appDataDir,
  10. String invokeWith,
  11. String[] zygoteArgs) {
  12. try {
  13. return startViaZygote(processClass, niceName, uid, gid, gids,
  14. debugFlags, mountExternal, targetSdkVersion, seInfo,
  15. abi, instructionSet, appDataDir, invokeWith, zygoteArgs);
  16. } catch (ZygoteStartFailedEx ex) {
  17. Log.e(LOG_TAG,
  18. "Starting VM process through Zygote failed");
  19. throw new RuntimeException(
  20. "Starting VM process through Zygote failed", ex);
  21. }
  22. }

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/273538
推荐阅读
相关标签
  

闽ICP备14008679号