Android 启动以及 USER_UNLOCKED的广播的发送

1. 开机各阶段

makefile 复制代码
```shell
boot_progress|bootAnimation:|wm_boot_animation_done
 
boot_progress_start: 6914   标志着kernel启动完成。Zygote开始启动  此时界面还是现实开机静态图片
 BootAnimation: BootAnimationStartTiming start time: 15202ms    界面开始开机动画
boot_progress_preload_start: 9509  Zygote开始加载资源
boot_progress_preload_end: 12251 Zygote加载资源结束
boot_progress_system_run: 12619 SystemServer开始启动
boot_progress_pms_start: 13424 PMS开始启动
boot_progress_pms_system_scan_start: 13482 PMS扫描/system目录下的安装包
boot_progress_pms_data_scan_start: 15598 PMS扫描/data目录下的安装包
boot_progress_pms_scan_end: 15633 PMS扫描结束
boot_progress_pms_ready: 16225 PMS初始化完毕
boot_progress_ams_ready: 22036 AMS就绪
android.intent.category.HOME: 先启动"Android正在启动" FallbackHome。
boot_progress_enable_screen: 24814 AMS启动完成后开始激活屏幕,从此以后
屏幕才能响应用户的触摸
wm_boot_animation_done: 27995 开机动画结束,这一步用户能直观感受到开
机结束
ACTION_LOCKED_BOOT_COMPLETED: Android7.0之后才有,在解锁前就会发出。
 
ActivityTaskManager: START u0 {act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10000100 cmp=com.android.launcher3/.Launcher} from uid 0, pid 0     启动launcher

```

wm_boot_animation_done : 开机动画结束,一般统计到这个时间点。

可以过滤 SystemServerTiming 看子服务启动时间。

Zygote32Timing 查看 zygote 加载各资源消耗的时间, 主要是 preloaded-classes 耗时。

2. Android 启动过程

  1. bootloader 启动 kernel

  2. kernel 启动后,首先启动 init 进程

  3. system\core\init\Init.cpp 在里面搭建系统运行环境,并解析启动init.rc。在init.zygote*.rc中启动 app_process(即zygote进程)。app_progress 入口在app_main.cpp。 里面启动ZygoteInit 和RuntimeInit。

  4. ZygoteInit 里面启动 SystemServer,并用ZygoteServer注册一个socket,死循环等待AMS的信息来创建应用进程。

3. SystemServer 启动过程

  1. 设置时间、时区、语言等

  2. startBootstrapServices:读配置,启动开机必备的服务:AMS、PMS等等

startCoreServices:其他重要服务,DropBox、电池、应用使用情况服务等

startOtherServices:通知、蓝牙、wifi等设备相关服务。

  1. 在AMS的systemReady 中调用startHomeActivityLocked 启动launcher。

  2. Launcher启动后,会在ActivityThread.handleResumeActivity中通过Idler 最终通过 finishBooting(里面设置sys.boot_completed 属性为1) 调用UserController.sendBootCompleted。这里涉及各种开机相关广播,在对credential-encrypted storage解锁后,BOOT_COMPLETED在UserController.finishUserUnlockedCompleted 中发出。

4. 几种开机广播

ACTION_LOCKED_BOOT_COMPLETED 表示解锁之前的 Direct Boot Mode 启动完成

ACTION_BOOT_COMPLETED 我们平时监听的开机广播

开机广播发送时机

Pasted image 20230412163530.png
go 复制代码
```shell
在Launcher启动时的handleResumeActivity,
ActivityTaskManagerService.activityIdle:
ActivityStackSupervisor.activityIdleInternalLocked:
    checkFinishBootingLocked: 检查是否初始化完成,需要所有启动应用的主线程是空闲的
        ActivityManagerService.finishBooting: 
            UserController.sendBootCompleted
                finishUserBoot
                    ACTION_LOCKED_BOOT_COMPLETED 发送;
                    maybeUnlockUser
                        unlockUserCleared
                        finishUserUnlocking:发送 SYSTEM_USER_UNLOCK_MSG 信息,finishUserUnlocked
                        finishUserUnlockedCompleted:ACTION_BOOT_COMPLETED 这里发送开机广播
                    
        ActivityTaskManagerService.postFinishBooting: 

```

launcher 启动后, 调用到 ActivityThread.handleResumeActivity()

yaml 复制代码
```java
    @Override
    public void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward,
            String reason) {
        ... ...
        // 往 loop 中添加了一条空闲消息
        Looper.myQueue().addIdleHandler(new Idler());
    }

private class Idler implements MessageQueue.IdleHandler {
2470          @Override
2471          public final boolean queueIdle() {
2472              ActivityClientRecord a = mNewActivities;
2473              boolean stopProfiling = false;
2474              if (mBoundApplication != null && mProfiler.profileFd != null
2475                      && mProfiler.autoStopProfiler) {
2476                  stopProfiling = true;
2477              }
2478              if (a != null) {
2479                  mNewActivities = null;
// 这里交给了 ActivityClient 
2480                  final ActivityClient ac = ActivityClient.getInstance();
2481                  ActivityClientRecord prev;
2482                  do {
2483                      if (localLOGV) Slog.v(
2484                          TAG, "Reporting idle of " + a +
2485                          " finished=" +
2486                          (a.activity != null && a.activity.mFinished));
2487                      if (a.activity != null && !a.activity.mFinished) {
2488                          ac.activityIdle(a.token, a.createdConfig, stopProfiling);
2489                          a.createdConfig = null;
2490                      }
2491                      prev = a;
2492                      a = a.nextIdle;
2493                      prev.nextIdle = null;
2494                  } while (a != null);
2495              }
2496              if (stopProfiling) {
2497                  mProfiler.stopProfiling();
2498              }
2499              return false;
2500          }
2501      }

```

Looper.myQueue().addIdleHandler(new Idler()); 往 loop 中添加了一条空闲消息,这个消息主要通知 ActivityTaskManagerService 当前 Activity 空闲了,这个时候可以去做一些其他的事情,比如执行上一个 Activity 的 onStop( ), onDestroy( ) ......

还有开机广播, 接着就来看看ActivityTaskManagerService.activityIdle():

arduino 复制代码
```java
      /** Reports the main thread is idle after the activity is resumed. */
50      public void activityIdle(IBinder token, Configuration config, boolean stopProfiling) {
51          try {
52              getActivityClientController().activityIdle(token, config, stopProfiling);
53          } catch (RemoteException e) {
54              e.rethrowFromSystemServer();
55          }
56      }

```

这里交给了 ActivityClientController 中的 activityIdle 来处理

java 复制代码
```java

 public void activityIdle(IBinder token, Configuration config, boolean stopProfiling) {
141          final long origId = Binder.clearCallingIdentity();
142          try {
143              synchronized (mGlobalLock) {
144                  Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "activityIdle");
145                  final ActivityRecord r = ActivityRecord.forTokenLocked(token);
146                  if (r == null) {
147                      return;
148                  }
// 这里其实还是回到了 ActivityTaskSupervisor 
149                  mTaskSupervisor.activityIdleInternal(r, false /* fromTimeout */,
150                          false /* processPausingActivities */, config);
151                  if (stopProfiling && r.hasProcess()) {
152                      r.app.clearProfilerIfNeeded();
153                  }
154              }
155          } finally {
156              Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
157              Binder.restoreCallingIdentity(origId);
158          }
159      }
```
yaml 复制代码
``java
 void activityIdleInternal(ActivityRecord r, boolean fromTimeout,
1578              boolean processPausingActivities, Configuration config) {
1579          if (DEBUG_ALL) Slog.v(TAG, "Activity idle: " + r);
1580  
1581          if (r != null) {
1582              if (DEBUG_IDLE) Slog.d(TAG_IDLE, "activityIdleInternal: Callers="
1583                      + Debug.getCallers(4));
1584              mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
1585              r.finishLaunchTickingLocked();
1586              if (fromTimeout) {
1587                  reportActivityLaunched(fromTimeout, r, INVALID_DELAY, -1 /* launchState */);
1588              }
1589  
1590              // This is a hack to semi-deal with a race condition
1591              // in the client where it can be constructed with a
1592              // newer configuration from when we asked it to launch.
1593              // We'll update with whatever configuration it now says
1594              // it used to launch.
1595              if (config != null) {
1596                  r.setLastReportedGlobalConfiguration(config);
1597              }
1598  
1599              // We are now idle.  If someone is waiting for a thumbnail from
1600              // us, we can now deliver.
1601              r.idle = true;
1602  
1603              // Check if able to finish booting when device is booting and all resumed activities
1604              // are idle.
               // 1.检查是否初始化完成,需要所有启动应用的主线程是空闲的
1605              if ((mService.isBooting() && mRootWindowContainer.allResumedActivitiesIdle())
1606                      || fromTimeout) {
1607                  checkFinishBootingLocked();
1608              }
1609  
1610              // When activity is idle, we consider the relaunch must be successful, so let's clear
1611              // the flag.
1612              r.mRelaunchReason = RELAUNCH_REASON_NONE;
1613          }
1614  
1615          if (mRootWindowContainer.allResumedActivitiesIdle()) {
1616              if (r != null) {
1617                  mService.scheduleAppGcsLocked();
1618                  mRecentTasks.onActivityIdle(r);
1619              }
1620  
1621              if (mLaunchingActivityWakeLock.isHeld()) {
1622                  mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
1623                  if (VALIDATE_WAKE_LOCK_CALLER &&
1624                          Binder.getCallingUid() != Process.myUid()) {
1625                      throw new IllegalStateException("Calling must be system uid");
1626                  }
1627                  mLaunchingActivityWakeLock.release();
1628              }
1629              mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
1630          }
1631  
1632          // Atomically retrieve all of the other things to do.
             // 2. 处理 stop 和 destory 的 activity 
1633          processStoppingAndFinishingActivities(r, processPausingActivities, "idle");
1634  
1635          if (DEBUG_IDLE) {
1636              Slogf.i(TAG, "activityIdleInternal(): r=%s, mStartingUsers=%s", r, mStartingUsers);
1637          }
1638  
1639          if (!mStartingUsers.isEmpty()) {
1640              final ArrayList<UserState> startingUsers = new ArrayList<>(mStartingUsers);
1641              mStartingUsers.clear();
1642              // Complete user switch.
1643              for (int i = 0; i < startingUsers.size(); i++) {
1644                  UserState userState = startingUsers.get(i);
1645                  Slogf.i(TAG, "finishing switch of user %d", userState.mHandle.getIdentifier());
1646                  mService.mAmInternal.finishUserSwitch(userState);
1647              }
1648          }
1649  
1650          mService.mH.post(() -> mService.mAmInternal.trimApplications());
1651      }
1652  

```

上面的逻辑主要分为 3块, 其中 2 中是处理 Activity 的生命周期。

1 中就会去发送开机广播

``

mService.isBooting() 这里返回 true, 在ActivityManagerService.systemReady()里赋的值

mRootWindowContainer.allResumedActivitiesIdle() 这里就是判断启动过的 Activity 主线程是否全是空闲的,如果不是空闲,就会一直等,直到所有都是空闲的才会在这里往下执行。(这也就是为什么有时候系统开机广播会在开机之后几分钟才发送)

再往下看看 checkFinishBootingLocked()

yaml 复制代码
```java
1560      /**
1561       * Called when all resumed tasks/root-tasks are idle.
1562       */
1563      @GuardedBy("mService")
1564      private void checkFinishBootingLocked() {
1565          final boolean booting = mService.isBooting();
1566          boolean enableScreen = false;
              // 置为 false
1567          mService.setBooting(false);
1568          if (!mService.isBooted()) {
1569              mService.setBooted(true);
1570              enableScreen = true;
1571          }
1572          if (booting || enableScreen) {
                  // 
1573              mService.postFinishBooting(booting, enableScreen);
1574          }
1575      }
1576  

```

注意这里的 booting 和 booted, 通过 booting 来判断,执行一次就会被设置为 false.

也就是方法只会执行一次。

yaml 复制代码
```java
frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java

5181      void postFinishBooting(boolean finishBooting, boolean enableScreen) {
5182          mH.post(() -> {
5183              if (finishBooting) {
                      // 这里会执行 ActivityManagerService 的finishBooting
5184                  mAmInternal.finishBooting();
5185              }
5186              if (enableScreen) {
                     // 这里中间通过转发下,会执行到 WindowManagerService的enableScreenAfterBoot()
5187                  mInternal.enableScreenAfterBoot(isBooted());
5188              }
5189          });
5190      }
5191  
```
ini 复制代码
```java

    final void finishBooting() {
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "FinishBooting");
 
        synchronized (this) {
            if (!mBootAnimationComplete) {
                mCallFinishBooting = true;
                return;
            }
            mCallFinishBooting = false;
        }
        ... ...
    }
 
    @Override
    public void bootAnimationComplete() {
        final boolean callFinishBooting;
        synchronized (this) {
            callFinishBooting = mCallFinishBooting;
            mBootAnimationComplete = true;
        }
        if (callFinishBooting) {
            finishBooting();
        }
    }
```

这里的mBootAnimationComplete默认是false,直接就给返回了,如果不返回就会去执行发送开机广播了

开机动画: bootAnimationComplete(), 这里将 mBootAnimationComplete 置为 true

还是会去执行 finishBooting()

bootAnimationComplete() 什么时候执行呢?

WindowManagerService.enableScreenAfterBoot()

yaml 复制代码
```java
public void enableScreenAfterBoot() {
3834          synchronized (mGlobalLock) {
3835              ProtoLog.i(WM_DEBUG_BOOT, "enableScreenAfterBoot: mDisplayEnabled=%b "
3836                              + "mForceDisplayEnabled=%b mShowingBootMessages=%b mSystemBooted=%b. "
3837                              + "%s",
3838                      mDisplayEnabled, mForceDisplayEnabled, mShowingBootMessages, mSystemBooted,
3839                      new RuntimeException("here").fillInStackTrace());
3840              if (mSystemBooted) {
3841                  return;
3842              }
3843              mSystemBooted = true;
3844              hideBootMessagesLocked();
3845              // If the screen still doesn't come up after 30 seconds, give
3846              // up and turn it on.
3847              mH.sendEmptyMessageDelayed(H.BOOT_TIMEOUT, 30 * 1000);
3848          }
3849  
3850          mPolicy.systemBooted();
3851  
3852          performEnableScreen();
3853      }

 private void performEnableScreen() {
        ... ...
        try {
            mActivityManager.bootAnimationComplete();
        } catch (RemoteException e) {
        }
        ... ...

```

enableScreenAfterBoot() 只会执行一次,但是 performEnableScreen() 可能会执行多次,内部会每隔 200ms 去查询动画是否完成,如果完成了,就会执行ActivityManagerService.bootAnimationComplete()

又执行回去,也就是再回去`ActivityManagerService.finishBooting():

arduino 复制代码
```java
    final void finishBooting() {
        ... ...
        mUserController.sendBootCompleted(... ...);
        ... ...
    }

```

又转到UserController类中去了,这是ActivityManagerService的一个帮助类,先来看下它的调用链:

rust 复制代码
```shell

UserController:

sendBootCompleted() -> finishUserBoot() -> maybeUnlockUser() -> unlockUserCleared() -> finishUserUnlocking -> handler 发送 SYSTEM_USER_UNLOCK_MSG 消息 -> finishUserUnlocked() -> finishUserUnlockedCompleted()

```
java 复制代码
```java

    private void finishUserUnlockedCompleted(UserState uss) {
        ... ...
        final Intent bootIntent = new Intent(Intent.ACTION_BOOT_COMPLETED, null);
        bootIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
        bootIntent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT
                | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND
                | Intent.FLAG_RECEIVER_OFFLOAD);
        // Widget broadcasts are outbound via FgThread, so to guarantee sequencing
        // we also send the boot_completed broadcast from that thread.
        final int callingUid = Binder.getCallingUid();
        final int callingPid = Binder.getCallingPid();
        FgThread.getHandler().post(() -> {
            mInjector.broadcastIntent(bootIntent, null,
                    new IIntentReceiver.Stub() {
                        @Override
                        public void performReceive(Intent intent, int resultCode, String data,
                                Bundle extras, boolean ordered, boolean sticky, int sendingUser)
                                        throws RemoteException {
                            Slog.i(UserController.TAG, "Finished processing BOOT_COMPLETED for u"
                                    + userId);
                            mBootCompleted = true;
                        }
                    }, 0, null, null,
                    new String[]{android.Manifest.permission.RECEIVE_BOOT_COMPLETED},
                    AppOpsManager.OP_NONE, null, true, false, MY_PID, SYSTEM_UID,
                    callingUid, callingPid, userId);
        });
    }

```

这里先是封装了Intent.ACTION_BOOT_COMPLETED这个广播意图,同时还传了一个android.Manifest.permission.RECEIVE_BOOT_COMPLETED权限,然后转交给UserController.Injector.broadcastIntent():

arduino 复制代码
```java
        protected int broadcastIntent(Intent intent, String resolvedType,
                IIntentReceiver resultTo, int resultCode, String resultData,
                Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle bOptions,
                boolean ordered, boolean sticky, int callingPid, int callingUid, int realCallingUid,
                int realCallingPid, int userId) {
            // TODO b/64165549 Verify that mLock is not held before calling AMS methods
            synchronized (mService) {
                return mService.broadcastIntentLocked(null, null, intent, resolvedType, resultTo,
                        resultCode, resultData, resultExtras, requiredPermissions, appOp, bOptions,
                        ordered, sticky, callingPid, callingUid, realCallingUid, realCallingPid,
                        userId);
            }
        }
```

这里又调用到ActivityManagerService.broadcastIntentLocked(),到这里就不在往下看了,后面就是去执行发送广播的逻辑。

对于有些广播接收不到,比如报如下错误:

W BroadcastQueue: Background execution not allowed:******************

类似这类错误,就可以在BroadcastQueue这个类里面找到抛这个异常的地方,然后基于抛这个异常的判断看看怎么去处理

相关推荐
安卓理事人7 小时前
安卓LinkedBlockingQueue消息队列
android
万能的小裴同学8 小时前
Android M3U8视频播放器
android·音视频
q***57748 小时前
MySql的慢查询(慢日志)
android·mysql·adb
JavaNoober9 小时前
Android 前台服务 "Bad Notification" 崩溃机制分析文档
android
城东米粉儿9 小时前
关于ObjectAnimator
android
zhangphil10 小时前
Android渲染线程Render Thread的RenderNode与DisplayList,引用Bitmap及Open GL纹理上传GPU
android
火柴就是我11 小时前
从头写一个自己的app
android·前端·flutter
lichong95112 小时前
XLog debug 开启打印日志,release 关闭打印日志
android·java·前端
用户693717500138413 小时前
14.Kotlin 类:类的形态(一):抽象类 (Abstract Class)
android·后端·kotlin
火柴就是我13 小时前
NekoBoxForAndroid 编译libcore.aar
android