Merge "Fix for crash due to user unlock and start race condition" into sc-dev
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index caf2510..ec2020f 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -122,7 +122,6 @@
import java.util.Objects;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.atomic.AtomicInteger;
-import java.util.function.Consumer;
/**
* Helper class for {@link ActivityManagerService} responsible for multi-user functionality.
@@ -518,18 +517,12 @@
if (!mInjector.getUserManager().isPreCreated(userId)) {
mHandler.sendMessage(mHandler.obtainMessage(REPORT_LOCKED_BOOT_COMPLETE_MSG,
userId, 0));
- Intent intent = new Intent(Intent.ACTION_LOCKED_BOOT_COMPLETED, null);
- intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
- intent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT
- | Intent.FLAG_RECEIVER_OFFLOAD
- | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
- mInjector.broadcastIntent(intent, null, resultTo, 0, null, null,
- new String[]{android.Manifest.permission.RECEIVE_BOOT_COMPLETED},
- AppOpsManager.OP_NONE,
- getTemporaryAppAllowlistBroadcastOptions(REASON_LOCKED_BOOT_COMPLETED)
- .toBundle(), true,
- false, MY_PID, SYSTEM_UID,
- Binder.getCallingUid(), Binder.getCallingPid(), userId);
+ // In case of headless system user mode, do not send boot complete broadcast for
+ // system user as it is sent by sendBootCompleted call.
+ if (!(UserManager.isHeadlessSystemUserMode() && uss.mHandle.isSystem())) {
+ // ACTION_LOCKED_BOOT_COMPLETED
+ sendLockedBootCompletedBroadcast(resultTo, userId);
+ }
}
}
@@ -552,6 +545,21 @@
}
}
+ private void sendLockedBootCompletedBroadcast(IIntentReceiver receiver, @UserIdInt int userId) {
+ final Intent intent = new Intent(Intent.ACTION_LOCKED_BOOT_COMPLETED, null);
+ intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
+ intent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT
+ | Intent.FLAG_RECEIVER_OFFLOAD
+ | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
+ mInjector.broadcastIntent(intent, null, receiver, 0, null, null,
+ new String[]{android.Manifest.permission.RECEIVE_BOOT_COMPLETED},
+ AppOpsManager.OP_NONE,
+ getTemporaryAppAllowlistBroadcastOptions(REASON_LOCKED_BOOT_COMPLETED)
+ .toBundle(), true,
+ false, MY_PID, SYSTEM_UID,
+ Binder.getCallingUid(), Binder.getCallingPid(), userId);
+ }
+
/**
* Step from {@link UserState#STATE_RUNNING_LOCKED} to
* {@link UserState#STATE_RUNNING_UNLOCKING}.
@@ -2167,26 +2175,22 @@
}
void sendBootCompleted(IIntentReceiver resultTo) {
- final boolean systemUserFinishedBooting;
-
// Get a copy of mStartedUsers to use outside of lock
SparseArray<UserState> startedUsers;
synchronized (mLock) {
- systemUserFinishedBooting = mCurrentUserId != UserHandle.USER_SYSTEM;
startedUsers = mStartedUsers.clone();
}
for (int i = 0; i < startedUsers.size(); i++) {
UserState uss = startedUsers.valueAt(i);
- if (systemUserFinishedBooting && uss.mHandle.isSystem()) {
- // On Automotive, at this point the system user has already been started and
- // unlocked, and some of the tasks we do here have already been done. So skip those
- // in that case.
- // TODO(b/132262830): this workdound shouldn't be necessary once we move the
- // headless-user start logic to UserManager-land
- Slog.d(TAG, "sendBootCompleted(): skipping on non-current system user");
- continue;
+ if (!UserManager.isHeadlessSystemUserMode()) {
+ finishUserBoot(uss, resultTo);
+ } else if (uss.mHandle.isSystem()) {
+ // In case of headless system user mode, send only locked boot complete broadcast
+ // for system user since finishUserBoot call will be made using other code path;
+ // for non-system user, do nothing since finishUserBoot will be called elsewhere.
+ sendLockedBootCompletedBroadcast(resultTo, uss.mHandle.getIdentifier());
+ return;
}
- finishUserBoot(uss, resultTo);
}
}