Loading core/java/android/content/pm/UserInfo.java +8 −0 Original line number Diff line number Diff line Loading @@ -327,6 +327,14 @@ public class UserInfo implements Parcelable { return "UserInfo{" + id + ":" + name + ":" + Integer.toHexString(flags) + "}"; } /** @hide */ public String toFullString() { return "UserInfo[id=" + id + ", name=" + name + ", flags=" + flagsToString(flags) + "]"; } /** @hide */ public static String flagsToString(int flags) { return DebugUtils.flagsToString(UserInfo.class, "FLAG_", flags); Loading services/core/java/com/android/server/SystemService.java +43 −10 Original line number Diff line number Diff line Loading @@ -54,6 +54,10 @@ import com.android.server.pm.UserManagerService; * {@hide} */ public abstract class SystemService { // TODO(b/133242016) STOPSHIP: change to false before R ships protected static final boolean DEBUG_USER = true; /* * Boot Phases */ Loading Loading @@ -150,7 +154,17 @@ public abstract class SystemService { public void onBootPhase(int phase) {} /** * @deprecated subclasses should extend {@link #onStartUser(int, int)} instead (which by default * Checks if the service should be available for the given user. * * <p>By default returns {@code true}, but subclasses should extend for optimization, if they * don't support some types (like headless system user). */ public boolean isSupported(@NonNull UserInfo userInfo) { return true; } /** * @deprecated subclasses should extend {@link #onStartUser(UserInfo)} instead (which by default * calls this method). */ @Deprecated Loading @@ -160,6 +174,9 @@ public abstract class SystemService { * Called when a new user is starting, for system services to initialize any per-user * state they maintain for running users. * * <p>This method is only called when the service {@link #isSupported(UserInfo) supports} this * user. * * @param userInfo The information about the user. <b>NOTE: </b> this is a "live" object * referenced by {@link UserManagerService} and hence should not be modified. */ Loading @@ -168,7 +185,7 @@ public abstract class SystemService { } /** * @deprecated subclasses should extend {@link #onUnlockUser(int, int)} instead (which by * @deprecated subclasses should extend {@link #onUnlockUser(UserInfo)} instead (which by * default calls this method). */ @Deprecated Loading @@ -185,6 +202,9 @@ public abstract class SystemService { * Code written inside system services should use * {@link UserManager#isUserUnlockingOrUnlocked(int)} to handle both of * these states. * <p> * This method is only called when the service {@link #isSupported(UserInfo) supports} this * user. * * @param userInfo The information about the user. <b>NOTE: </b> this is a "live" object * referenced by {@link UserManagerService} and hence should not be modified. Loading @@ -194,8 +214,8 @@ public abstract class SystemService { } /** * @deprecated subclasses should extend {@link #onSwitchUser(int, int)} instead (which by * default calls this method). * @deprecated subclasses should extend {@link #onSwitchUser(UserInfo, UserInfo)} instead * (which by default calls this method). */ @Deprecated public void onSwitchUser(@UserIdInt int userHandle) {} Loading @@ -205,15 +225,21 @@ public abstract class SystemService { * special behavior for whichever user is currently in the foreground. This is called * before any application processes are aware of the new user. * * @param userInfo The information about the user. <b>NOTE: </b> this is a "live" object * <p>This method is only called when the service {@link #isSupported(UserInfo) supports} either * of the users ({@code from} or {@code to}). * * <b>NOTE: </b> both {@code from} and {@code to} are "live" objects * referenced by {@link UserManagerService} and hence should not be modified. * * @param from The information about the user being switched from. * @param to The information about the user being switched from to. */ public void onSwitchUser(@NonNull UserInfo userInfo) { onSwitchUser(userInfo.id); public void onSwitchUser(@NonNull UserInfo from, @NonNull UserInfo to) { onSwitchUser(to.id); } /** * @deprecated subclasses should extend {@link #onStopUser(int, int)} instead (which by default * @deprecated subclasses should extend {@link #onStopUser(UserInfo)} instead (which by default * calls this method). */ @Deprecated Loading @@ -225,6 +251,9 @@ public abstract class SystemService { * broadcast to the user; it is a good place to stop making use of any resources of that * user (such as binding to a service running in the user). * * <p>This method is only called when the service {@link #isSupported(UserInfo) supports} this * user. * * <p>NOTE: This is the last callback where the callee may access the target user's CE storage. * * @param userInfo The information about the user. <b>NOTE: </b> this is a "live" object Loading @@ -235,7 +264,7 @@ public abstract class SystemService { } /** * @deprecated subclasses should extend {@link #onCleanupUser(int, int)} instead (which by * @deprecated subclasses should extend {@link #onCleanupUser(UserInfo)} instead (which by * default calls this method). */ @Deprecated Loading @@ -246,8 +275,12 @@ public abstract class SystemService { * state they maintain for running users. This is called after all application process * teardown of the user is complete. * * <p>This method is only called when the service {@link #isSupported(UserInfo) supports} this * user. * * <p>NOTE: When this callback is called, the CE storage for the target user may not be * accessible already. Use {@link #onCleanupUser} instead if you need to access the CE storage. * accessible already. Use {@link #onStopUser(UserInfo)} instead if you need to access the CE * storage. * * @param userInfo The information about the user. <b>NOTE: </b> this is a "live" object * referenced by {@link UserManagerService} and hence should not be modified. Loading services/core/java/com/android/server/SystemServiceManager.java +68 −20 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import android.content.pm.UserInfo; import android.os.Environment; import android.os.SystemClock; import android.os.Trace; import android.os.UserHandle; import android.os.UserManagerInternal; import android.util.Slog; Loading @@ -41,8 +42,16 @@ import java.util.ArrayList; */ public class SystemServiceManager { private static final String TAG = "SystemServiceManager"; private static final boolean DEBUG = false; private static final int SERVICE_CALL_WARN_TIME_MS = 50; // Constants used on onUser(...) private static final String START = "Start"; private static final String UNLOCK = "Unlock"; private static final String SWITCH = "Switch"; private static final String STOP = "Stop"; private static final String CLEANUP = "Cleanup"; private static File sSystemDir; private final Context mContext; private boolean mSafeMode; Loading Loading @@ -90,7 +99,6 @@ public class SystemServiceManager { * @return The service instance, never null. * @throws RuntimeException if the service fails to start. */ @SuppressWarnings("unchecked") public <T extends SystemService> T startService(Class<T> serviceClass) { try { final String name = serviceClass.getName(); Loading Loading @@ -212,64 +220,104 @@ public class SystemServiceManager { * Starts the given user. */ public void startUser(final @NonNull TimingsTraceAndSlog t, final @UserIdInt int userHandle) { onUser(t, "Start", userHandle, (s, u) -> s.onStartUser(u)); onUser(t, START, userHandle); } /** * Unlocks the given user. */ public void unlockUser(final @UserIdInt int userHandle) { onUser("Unlock", userHandle, (s, u) -> s.onUnlockUser(u)); onUser(UNLOCK, userHandle); } /** * Switches to the given user. */ public void switchUser(final @UserIdInt int userHandle) { onUser("Switch", userHandle, (s, u) -> s.onSwitchUser(u)); public void switchUser(final @UserIdInt int from, final @UserIdInt int to) { onUser(TimingsTraceAndSlog.newAsyncLog(), SWITCH, to, from); } /** * Stops the given user. */ public void stopUser(final @UserIdInt int userHandle) { onUser("Stop", userHandle, (s, u) -> s.onStopUser(u)); onUser(STOP, userHandle); } /** * Cleans up the given user. */ public void cleanupUser(final @UserIdInt int userHandle) { onUser("Cleanup", userHandle, (s, u) -> s.onCleanupUser(u)); onUser(CLEANUP, userHandle); } private interface ServiceVisitor { void visit(@NonNull SystemService service, @NonNull UserInfo userInfo); private void onUser(@NonNull String onWhat, @UserIdInt int userHandle) { onUser(TimingsTraceAndSlog.newAsyncLog(), onWhat, userHandle); } private void onUser(@NonNull String onWhat, @UserIdInt int userHandle, @NonNull ServiceVisitor visitor) { onUser(TimingsTraceAndSlog.newAsyncLog(), onWhat, userHandle, visitor); private void onUser(@NonNull TimingsTraceAndSlog t, @NonNull String onWhat, @UserIdInt int userHandle) { onUser(t, onWhat, userHandle, UserHandle.USER_NULL); } private void onUser(@NonNull TimingsTraceAndSlog t, @NonNull String onWhat, @UserIdInt int userHandle, @NonNull ServiceVisitor visitor) { t.traceBegin("ssm." + onWhat + "User-" + userHandle); Slog.i(TAG, "Calling on" + onWhat + "User u" + userHandle); final UserInfo userInfo = getUserInfo(userHandle); @UserIdInt int curUserId, @UserIdInt int prevUserId) { t.traceBegin("ssm." + onWhat + "User-" + curUserId); Slog.i(TAG, "Calling on" + onWhat + "User " + curUserId); final UserInfo curUserInfo = getUserInfo(curUserId); final UserInfo prevUserInfo = prevUserId == UserHandle.USER_NULL ? null : getUserInfo(prevUserId); final int serviceLen = mServices.size(); for (int i = 0; i < serviceLen; i++) { final SystemService service = mServices.get(i); final String serviceName = service.getClass().getName(); t.traceBegin("ssm.on" + onWhat + "User-" + userHandle + " " + serviceName); boolean supported = service.isSupported(curUserInfo); // Must check if either curUser or prevUser is supported (for example, if switching from // unsupported to supported, we still need to notify the services) if (!supported && prevUserInfo != null) { supported = service.isSupported(prevUserInfo); } if (!supported) { if (DEBUG) { Slog.d(TAG, "Skipping " + onWhat + "User-" + curUserId + " on service " + serviceName + " because it's not supported (curUser: " + curUserInfo + ", prevUser:" + prevUserInfo + ")"); } else { Slog.i(TAG, "Skipping " + onWhat + "User-" + curUserId + " on " + serviceName); } continue; } t.traceBegin("ssm.on" + onWhat + "User-" + curUserId + " " + serviceName); long time = SystemClock.elapsedRealtime(); try { visitor.visit(service, userInfo); switch (onWhat) { case SWITCH: service.onSwitchUser(prevUserInfo, curUserInfo); break; case START: service.onStartUser(curUserInfo); break; case UNLOCK: service.onUnlockUser(curUserInfo); break; case STOP: service.onStopUser(curUserInfo); break; case CLEANUP: service.onCleanupUser(curUserInfo); break; default: throw new IllegalArgumentException(onWhat + " what?"); } } catch (Exception ex) { Slog.wtf(TAG, "Failure reporting " + onWhat + " of user " + userHandle Slog.wtf(TAG, "Failure reporting " + onWhat + " of user " + curUserInfo + " to service " + serviceName, ex); } warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "on" + onWhat + "User "); warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "on" + onWhat + "User-" + curUserId); t.traceEnd(); // what on service } t.traceEnd(); // main entry Loading services/core/java/com/android/server/am/UserController.java +1 −1 Original line number Diff line number Diff line Loading @@ -2180,7 +2180,7 @@ class UserController implements Handler.Callback { BatteryStats.HistoryItem.EVENT_USER_FOREGROUND_START, Integer.toString(msg.arg1), msg.arg1); mInjector.getSystemServiceManager().switchUser(msg.arg1); mInjector.getSystemServiceManager().switchUser(msg.arg2, msg.arg1); break; case FOREGROUND_PROFILE_CHANGED_MSG: dispatchForegroundProfileChanged(msg.arg1); Loading services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java +48 −32 Original line number Diff line number Diff line Loading @@ -52,8 +52,9 @@ import android.os.Parcel; import android.os.RemoteCallback; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.Trace; import android.os.UserHandle; import android.os.UserManager; import android.os.UserManagerInternal; import android.provider.Settings; import android.service.voice.IVoiceInteractionService; import android.service.voice.IVoiceInteractionSession; Loading Loading @@ -95,14 +96,14 @@ import java.util.concurrent.Executor; */ public class VoiceInteractionManagerService extends SystemService { static final String TAG = "VoiceInteractionManagerService"; static final boolean DEBUG = true; // TODO(b/133242016) STOPSHIP: change to false before R ships static final boolean DEBUG = false; final Context mContext; final ContentResolver mResolver; final DatabaseHelper mDbHelper; final ActivityManagerInternal mAmInternal; final ActivityTaskManagerInternal mAtmInternal; final UserManager mUserManager; final UserManagerInternal mUserManagerInternal; final ArraySet<Integer> mLoadedKeyphraseIds = new ArraySet<>(); ShortcutServiceInternal mShortcutServiceInternal; SoundTriggerInternal mSoundTriggerInternal; Loading @@ -120,8 +121,8 @@ public class VoiceInteractionManagerService extends SystemService { LocalServices.getService(ActivityManagerInternal.class)); mAtmInternal = Preconditions.checkNotNull( LocalServices.getService(ActivityTaskManagerInternal.class)); mUserManager = Preconditions.checkNotNull( context.getSystemService(UserManager.class)); mUserManagerInternal = Preconditions.checkNotNull( LocalServices.getService(UserManagerInternal.class)); PermissionManagerServiceInternal permissionManagerInternal = LocalServices.getService( PermissionManagerServiceInternal.class); Loading Loading @@ -156,38 +157,31 @@ public class VoiceInteractionManagerService extends SystemService { } } @Override public boolean isSupported(UserInfo userInfo) { return userInfo.isFull(); } @Override public void onStartUser(@NonNull UserInfo userInfo) { if (DEBUG) Slog.d(TAG, "onStartUser(" + userInfo + ")"); if (DEBUG_USER) Slog.d(TAG, "onStartUser(" + userInfo + ")"); if (!userInfo.isFull()) { if (DEBUG) Slog.d(TAG, "***** skipping on non-full user " + userInfo); return; } mServiceStub.initForUser(userInfo.id); } @Override public void onUnlockUser(@NonNull UserInfo userInfo) { if (DEBUG) Slog.d(TAG, "onUnlockUser(" + userInfo + ")"); if (DEBUG_USER) Slog.d(TAG, "onUnlockUser(" + userInfo + ")"); if (!userInfo.isFull()) { if (DEBUG) Slog.d(TAG, "***** skipping on non-full user " + userInfo); return; } mServiceStub.initForUser(userInfo.id); mServiceStub.switchImplementationIfNeeded(false); } @Override public void onSwitchUser(@NonNull UserInfo userInfo) { if (DEBUG) Slog.d(TAG, "onSwitchUser(" + userInfo + ")"); public void onSwitchUser(@NonNull UserInfo from, @NonNull UserInfo to) { if (DEBUG_USER) Slog.d(TAG, "onSwitchUser(" + from + " > " + to + ")"); if (!userInfo.isFull()) { if (DEBUG) Slog.d(TAG, "***** skipping on non-full user " + userInfo); return; } mServiceStub.switchUser(userInfo.id); mServiceStub.switchUser(to.id); } class LocalService extends VoiceInteractionManagerInternal { Loading Loading @@ -225,6 +219,7 @@ public class VoiceInteractionManagerService extends SystemService { private boolean mSafeMode; private int mCurUser; private boolean mCurUserUnlocked; private boolean mCurUserSupported; private final boolean mEnableService; VoiceInteractionManagerServiceStub() { Loading Loading @@ -292,9 +287,9 @@ public class VoiceInteractionManagerService extends SystemService { public void initForUser(int userHandle) { final TimingsTraceAndSlog t; if (DEBUG) { t = TimingsTraceAndSlog.newAsyncLog(); t.traceBegin("VoiceInteractionSvc.initForUser(" + userHandle + ")"); if (DEBUG_USER) { t = new TimingsTraceAndSlog(TAG, Trace.TRACE_TAG_SYSTEM_SERVER); t.traceBegin("initForUser(" + userHandle + ")"); } else { t = null; } Loading Loading @@ -439,15 +434,21 @@ public class VoiceInteractionManagerService extends SystemService { new SettingsObserver(UiThread.getHandler()); synchronized (this) { mCurUser = ActivityManager.getCurrentUser(); setCurrentUserLocked(ActivityManager.getCurrentUser()); switchImplementationIfNeededLocked(false); } } public void switchUser(int userHandle) { private void setCurrentUserLocked(@UserIdInt int userHandle) { mCurUser = userHandle; final UserInfo userInfo = mUserManagerInternal.getUserInfo(mCurUser); mCurUserSupported = isSupported(userInfo); } public void switchUser(@UserIdInt int userHandle) { FgThread.getHandler().post(() -> { synchronized (this) { mCurUser = userHandle; setCurrentUserLocked(userHandle); mCurUserUnlocked = false; switchImplementationIfNeededLocked(false); } Loading @@ -461,10 +462,22 @@ public class VoiceInteractionManagerService extends SystemService { } void switchImplementationIfNeededLocked(boolean force) { if (!mCurUserSupported) { if (DEBUG_USER) { Slog.d(TAG, "switchImplementationIfNeeded(): skipping on unsuported user " + mCurUser); } if (mImpl != null) { mImpl.shutdownLocked(); setImplLocked(null); } return; } final TimingsTraceAndSlog t; if (DEBUG) { t = TimingsTraceAndSlog.newAsyncLog(); t.traceBegin("VoiceInteractionSvc.switchImplementation(" + mCurUser + ")"); if (DEBUG_USER) { t = new TimingsTraceAndSlog(TAG, Trace.TRACE_TAG_SYSTEM_SERVER); t.traceBegin("switchImplementation(" + mCurUser + ")"); } else { t = null; } Loading Loading @@ -494,7 +507,7 @@ public class VoiceInteractionManagerService extends SystemService { final boolean hasComponent = serviceComponent != null && serviceInfo != null; if (mUserManager.isUserUnlockingOrUnlocked(mCurUser)) { if (mUserManagerInternal.isUserUnlockingOrUnlocked(mCurUser)) { if (hasComponent) { mShortcutServiceInternal.setShortcutHostPackage(TAG, serviceComponent.getPackageName(), mCurUser); Loading Loading @@ -1275,6 +1288,9 @@ public class VoiceInteractionManagerService extends SystemService { synchronized (this) { pw.println("VOICE INTERACTION MANAGER (dumpsys voiceinteraction)"); pw.println(" mEnableService: " + mEnableService); pw.println(" mCurUser: " + mCurUser); pw.println(" mCurUserUnlocked: " + mCurUserUnlocked); pw.println(" mCurUserSupported: " + mCurUserSupported); if (mImpl == null) { pw.println(" (No active implementation)"); return; Loading Loading
core/java/android/content/pm/UserInfo.java +8 −0 Original line number Diff line number Diff line Loading @@ -327,6 +327,14 @@ public class UserInfo implements Parcelable { return "UserInfo{" + id + ":" + name + ":" + Integer.toHexString(flags) + "}"; } /** @hide */ public String toFullString() { return "UserInfo[id=" + id + ", name=" + name + ", flags=" + flagsToString(flags) + "]"; } /** @hide */ public static String flagsToString(int flags) { return DebugUtils.flagsToString(UserInfo.class, "FLAG_", flags); Loading
services/core/java/com/android/server/SystemService.java +43 −10 Original line number Diff line number Diff line Loading @@ -54,6 +54,10 @@ import com.android.server.pm.UserManagerService; * {@hide} */ public abstract class SystemService { // TODO(b/133242016) STOPSHIP: change to false before R ships protected static final boolean DEBUG_USER = true; /* * Boot Phases */ Loading Loading @@ -150,7 +154,17 @@ public abstract class SystemService { public void onBootPhase(int phase) {} /** * @deprecated subclasses should extend {@link #onStartUser(int, int)} instead (which by default * Checks if the service should be available for the given user. * * <p>By default returns {@code true}, but subclasses should extend for optimization, if they * don't support some types (like headless system user). */ public boolean isSupported(@NonNull UserInfo userInfo) { return true; } /** * @deprecated subclasses should extend {@link #onStartUser(UserInfo)} instead (which by default * calls this method). */ @Deprecated Loading @@ -160,6 +174,9 @@ public abstract class SystemService { * Called when a new user is starting, for system services to initialize any per-user * state they maintain for running users. * * <p>This method is only called when the service {@link #isSupported(UserInfo) supports} this * user. * * @param userInfo The information about the user. <b>NOTE: </b> this is a "live" object * referenced by {@link UserManagerService} and hence should not be modified. */ Loading @@ -168,7 +185,7 @@ public abstract class SystemService { } /** * @deprecated subclasses should extend {@link #onUnlockUser(int, int)} instead (which by * @deprecated subclasses should extend {@link #onUnlockUser(UserInfo)} instead (which by * default calls this method). */ @Deprecated Loading @@ -185,6 +202,9 @@ public abstract class SystemService { * Code written inside system services should use * {@link UserManager#isUserUnlockingOrUnlocked(int)} to handle both of * these states. * <p> * This method is only called when the service {@link #isSupported(UserInfo) supports} this * user. * * @param userInfo The information about the user. <b>NOTE: </b> this is a "live" object * referenced by {@link UserManagerService} and hence should not be modified. Loading @@ -194,8 +214,8 @@ public abstract class SystemService { } /** * @deprecated subclasses should extend {@link #onSwitchUser(int, int)} instead (which by * default calls this method). * @deprecated subclasses should extend {@link #onSwitchUser(UserInfo, UserInfo)} instead * (which by default calls this method). */ @Deprecated public void onSwitchUser(@UserIdInt int userHandle) {} Loading @@ -205,15 +225,21 @@ public abstract class SystemService { * special behavior for whichever user is currently in the foreground. This is called * before any application processes are aware of the new user. * * @param userInfo The information about the user. <b>NOTE: </b> this is a "live" object * <p>This method is only called when the service {@link #isSupported(UserInfo) supports} either * of the users ({@code from} or {@code to}). * * <b>NOTE: </b> both {@code from} and {@code to} are "live" objects * referenced by {@link UserManagerService} and hence should not be modified. * * @param from The information about the user being switched from. * @param to The information about the user being switched from to. */ public void onSwitchUser(@NonNull UserInfo userInfo) { onSwitchUser(userInfo.id); public void onSwitchUser(@NonNull UserInfo from, @NonNull UserInfo to) { onSwitchUser(to.id); } /** * @deprecated subclasses should extend {@link #onStopUser(int, int)} instead (which by default * @deprecated subclasses should extend {@link #onStopUser(UserInfo)} instead (which by default * calls this method). */ @Deprecated Loading @@ -225,6 +251,9 @@ public abstract class SystemService { * broadcast to the user; it is a good place to stop making use of any resources of that * user (such as binding to a service running in the user). * * <p>This method is only called when the service {@link #isSupported(UserInfo) supports} this * user. * * <p>NOTE: This is the last callback where the callee may access the target user's CE storage. * * @param userInfo The information about the user. <b>NOTE: </b> this is a "live" object Loading @@ -235,7 +264,7 @@ public abstract class SystemService { } /** * @deprecated subclasses should extend {@link #onCleanupUser(int, int)} instead (which by * @deprecated subclasses should extend {@link #onCleanupUser(UserInfo)} instead (which by * default calls this method). */ @Deprecated Loading @@ -246,8 +275,12 @@ public abstract class SystemService { * state they maintain for running users. This is called after all application process * teardown of the user is complete. * * <p>This method is only called when the service {@link #isSupported(UserInfo) supports} this * user. * * <p>NOTE: When this callback is called, the CE storage for the target user may not be * accessible already. Use {@link #onCleanupUser} instead if you need to access the CE storage. * accessible already. Use {@link #onStopUser(UserInfo)} instead if you need to access the CE * storage. * * @param userInfo The information about the user. <b>NOTE: </b> this is a "live" object * referenced by {@link UserManagerService} and hence should not be modified. Loading
services/core/java/com/android/server/SystemServiceManager.java +68 −20 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import android.content.pm.UserInfo; import android.os.Environment; import android.os.SystemClock; import android.os.Trace; import android.os.UserHandle; import android.os.UserManagerInternal; import android.util.Slog; Loading @@ -41,8 +42,16 @@ import java.util.ArrayList; */ public class SystemServiceManager { private static final String TAG = "SystemServiceManager"; private static final boolean DEBUG = false; private static final int SERVICE_CALL_WARN_TIME_MS = 50; // Constants used on onUser(...) private static final String START = "Start"; private static final String UNLOCK = "Unlock"; private static final String SWITCH = "Switch"; private static final String STOP = "Stop"; private static final String CLEANUP = "Cleanup"; private static File sSystemDir; private final Context mContext; private boolean mSafeMode; Loading Loading @@ -90,7 +99,6 @@ public class SystemServiceManager { * @return The service instance, never null. * @throws RuntimeException if the service fails to start. */ @SuppressWarnings("unchecked") public <T extends SystemService> T startService(Class<T> serviceClass) { try { final String name = serviceClass.getName(); Loading Loading @@ -212,64 +220,104 @@ public class SystemServiceManager { * Starts the given user. */ public void startUser(final @NonNull TimingsTraceAndSlog t, final @UserIdInt int userHandle) { onUser(t, "Start", userHandle, (s, u) -> s.onStartUser(u)); onUser(t, START, userHandle); } /** * Unlocks the given user. */ public void unlockUser(final @UserIdInt int userHandle) { onUser("Unlock", userHandle, (s, u) -> s.onUnlockUser(u)); onUser(UNLOCK, userHandle); } /** * Switches to the given user. */ public void switchUser(final @UserIdInt int userHandle) { onUser("Switch", userHandle, (s, u) -> s.onSwitchUser(u)); public void switchUser(final @UserIdInt int from, final @UserIdInt int to) { onUser(TimingsTraceAndSlog.newAsyncLog(), SWITCH, to, from); } /** * Stops the given user. */ public void stopUser(final @UserIdInt int userHandle) { onUser("Stop", userHandle, (s, u) -> s.onStopUser(u)); onUser(STOP, userHandle); } /** * Cleans up the given user. */ public void cleanupUser(final @UserIdInt int userHandle) { onUser("Cleanup", userHandle, (s, u) -> s.onCleanupUser(u)); onUser(CLEANUP, userHandle); } private interface ServiceVisitor { void visit(@NonNull SystemService service, @NonNull UserInfo userInfo); private void onUser(@NonNull String onWhat, @UserIdInt int userHandle) { onUser(TimingsTraceAndSlog.newAsyncLog(), onWhat, userHandle); } private void onUser(@NonNull String onWhat, @UserIdInt int userHandle, @NonNull ServiceVisitor visitor) { onUser(TimingsTraceAndSlog.newAsyncLog(), onWhat, userHandle, visitor); private void onUser(@NonNull TimingsTraceAndSlog t, @NonNull String onWhat, @UserIdInt int userHandle) { onUser(t, onWhat, userHandle, UserHandle.USER_NULL); } private void onUser(@NonNull TimingsTraceAndSlog t, @NonNull String onWhat, @UserIdInt int userHandle, @NonNull ServiceVisitor visitor) { t.traceBegin("ssm." + onWhat + "User-" + userHandle); Slog.i(TAG, "Calling on" + onWhat + "User u" + userHandle); final UserInfo userInfo = getUserInfo(userHandle); @UserIdInt int curUserId, @UserIdInt int prevUserId) { t.traceBegin("ssm." + onWhat + "User-" + curUserId); Slog.i(TAG, "Calling on" + onWhat + "User " + curUserId); final UserInfo curUserInfo = getUserInfo(curUserId); final UserInfo prevUserInfo = prevUserId == UserHandle.USER_NULL ? null : getUserInfo(prevUserId); final int serviceLen = mServices.size(); for (int i = 0; i < serviceLen; i++) { final SystemService service = mServices.get(i); final String serviceName = service.getClass().getName(); t.traceBegin("ssm.on" + onWhat + "User-" + userHandle + " " + serviceName); boolean supported = service.isSupported(curUserInfo); // Must check if either curUser or prevUser is supported (for example, if switching from // unsupported to supported, we still need to notify the services) if (!supported && prevUserInfo != null) { supported = service.isSupported(prevUserInfo); } if (!supported) { if (DEBUG) { Slog.d(TAG, "Skipping " + onWhat + "User-" + curUserId + " on service " + serviceName + " because it's not supported (curUser: " + curUserInfo + ", prevUser:" + prevUserInfo + ")"); } else { Slog.i(TAG, "Skipping " + onWhat + "User-" + curUserId + " on " + serviceName); } continue; } t.traceBegin("ssm.on" + onWhat + "User-" + curUserId + " " + serviceName); long time = SystemClock.elapsedRealtime(); try { visitor.visit(service, userInfo); switch (onWhat) { case SWITCH: service.onSwitchUser(prevUserInfo, curUserInfo); break; case START: service.onStartUser(curUserInfo); break; case UNLOCK: service.onUnlockUser(curUserInfo); break; case STOP: service.onStopUser(curUserInfo); break; case CLEANUP: service.onCleanupUser(curUserInfo); break; default: throw new IllegalArgumentException(onWhat + " what?"); } } catch (Exception ex) { Slog.wtf(TAG, "Failure reporting " + onWhat + " of user " + userHandle Slog.wtf(TAG, "Failure reporting " + onWhat + " of user " + curUserInfo + " to service " + serviceName, ex); } warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "on" + onWhat + "User "); warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "on" + onWhat + "User-" + curUserId); t.traceEnd(); // what on service } t.traceEnd(); // main entry Loading
services/core/java/com/android/server/am/UserController.java +1 −1 Original line number Diff line number Diff line Loading @@ -2180,7 +2180,7 @@ class UserController implements Handler.Callback { BatteryStats.HistoryItem.EVENT_USER_FOREGROUND_START, Integer.toString(msg.arg1), msg.arg1); mInjector.getSystemServiceManager().switchUser(msg.arg1); mInjector.getSystemServiceManager().switchUser(msg.arg2, msg.arg1); break; case FOREGROUND_PROFILE_CHANGED_MSG: dispatchForegroundProfileChanged(msg.arg1); Loading
services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java +48 −32 Original line number Diff line number Diff line Loading @@ -52,8 +52,9 @@ import android.os.Parcel; import android.os.RemoteCallback; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.Trace; import android.os.UserHandle; import android.os.UserManager; import android.os.UserManagerInternal; import android.provider.Settings; import android.service.voice.IVoiceInteractionService; import android.service.voice.IVoiceInteractionSession; Loading Loading @@ -95,14 +96,14 @@ import java.util.concurrent.Executor; */ public class VoiceInteractionManagerService extends SystemService { static final String TAG = "VoiceInteractionManagerService"; static final boolean DEBUG = true; // TODO(b/133242016) STOPSHIP: change to false before R ships static final boolean DEBUG = false; final Context mContext; final ContentResolver mResolver; final DatabaseHelper mDbHelper; final ActivityManagerInternal mAmInternal; final ActivityTaskManagerInternal mAtmInternal; final UserManager mUserManager; final UserManagerInternal mUserManagerInternal; final ArraySet<Integer> mLoadedKeyphraseIds = new ArraySet<>(); ShortcutServiceInternal mShortcutServiceInternal; SoundTriggerInternal mSoundTriggerInternal; Loading @@ -120,8 +121,8 @@ public class VoiceInteractionManagerService extends SystemService { LocalServices.getService(ActivityManagerInternal.class)); mAtmInternal = Preconditions.checkNotNull( LocalServices.getService(ActivityTaskManagerInternal.class)); mUserManager = Preconditions.checkNotNull( context.getSystemService(UserManager.class)); mUserManagerInternal = Preconditions.checkNotNull( LocalServices.getService(UserManagerInternal.class)); PermissionManagerServiceInternal permissionManagerInternal = LocalServices.getService( PermissionManagerServiceInternal.class); Loading Loading @@ -156,38 +157,31 @@ public class VoiceInteractionManagerService extends SystemService { } } @Override public boolean isSupported(UserInfo userInfo) { return userInfo.isFull(); } @Override public void onStartUser(@NonNull UserInfo userInfo) { if (DEBUG) Slog.d(TAG, "onStartUser(" + userInfo + ")"); if (DEBUG_USER) Slog.d(TAG, "onStartUser(" + userInfo + ")"); if (!userInfo.isFull()) { if (DEBUG) Slog.d(TAG, "***** skipping on non-full user " + userInfo); return; } mServiceStub.initForUser(userInfo.id); } @Override public void onUnlockUser(@NonNull UserInfo userInfo) { if (DEBUG) Slog.d(TAG, "onUnlockUser(" + userInfo + ")"); if (DEBUG_USER) Slog.d(TAG, "onUnlockUser(" + userInfo + ")"); if (!userInfo.isFull()) { if (DEBUG) Slog.d(TAG, "***** skipping on non-full user " + userInfo); return; } mServiceStub.initForUser(userInfo.id); mServiceStub.switchImplementationIfNeeded(false); } @Override public void onSwitchUser(@NonNull UserInfo userInfo) { if (DEBUG) Slog.d(TAG, "onSwitchUser(" + userInfo + ")"); public void onSwitchUser(@NonNull UserInfo from, @NonNull UserInfo to) { if (DEBUG_USER) Slog.d(TAG, "onSwitchUser(" + from + " > " + to + ")"); if (!userInfo.isFull()) { if (DEBUG) Slog.d(TAG, "***** skipping on non-full user " + userInfo); return; } mServiceStub.switchUser(userInfo.id); mServiceStub.switchUser(to.id); } class LocalService extends VoiceInteractionManagerInternal { Loading Loading @@ -225,6 +219,7 @@ public class VoiceInteractionManagerService extends SystemService { private boolean mSafeMode; private int mCurUser; private boolean mCurUserUnlocked; private boolean mCurUserSupported; private final boolean mEnableService; VoiceInteractionManagerServiceStub() { Loading Loading @@ -292,9 +287,9 @@ public class VoiceInteractionManagerService extends SystemService { public void initForUser(int userHandle) { final TimingsTraceAndSlog t; if (DEBUG) { t = TimingsTraceAndSlog.newAsyncLog(); t.traceBegin("VoiceInteractionSvc.initForUser(" + userHandle + ")"); if (DEBUG_USER) { t = new TimingsTraceAndSlog(TAG, Trace.TRACE_TAG_SYSTEM_SERVER); t.traceBegin("initForUser(" + userHandle + ")"); } else { t = null; } Loading Loading @@ -439,15 +434,21 @@ public class VoiceInteractionManagerService extends SystemService { new SettingsObserver(UiThread.getHandler()); synchronized (this) { mCurUser = ActivityManager.getCurrentUser(); setCurrentUserLocked(ActivityManager.getCurrentUser()); switchImplementationIfNeededLocked(false); } } public void switchUser(int userHandle) { private void setCurrentUserLocked(@UserIdInt int userHandle) { mCurUser = userHandle; final UserInfo userInfo = mUserManagerInternal.getUserInfo(mCurUser); mCurUserSupported = isSupported(userInfo); } public void switchUser(@UserIdInt int userHandle) { FgThread.getHandler().post(() -> { synchronized (this) { mCurUser = userHandle; setCurrentUserLocked(userHandle); mCurUserUnlocked = false; switchImplementationIfNeededLocked(false); } Loading @@ -461,10 +462,22 @@ public class VoiceInteractionManagerService extends SystemService { } void switchImplementationIfNeededLocked(boolean force) { if (!mCurUserSupported) { if (DEBUG_USER) { Slog.d(TAG, "switchImplementationIfNeeded(): skipping on unsuported user " + mCurUser); } if (mImpl != null) { mImpl.shutdownLocked(); setImplLocked(null); } return; } final TimingsTraceAndSlog t; if (DEBUG) { t = TimingsTraceAndSlog.newAsyncLog(); t.traceBegin("VoiceInteractionSvc.switchImplementation(" + mCurUser + ")"); if (DEBUG_USER) { t = new TimingsTraceAndSlog(TAG, Trace.TRACE_TAG_SYSTEM_SERVER); t.traceBegin("switchImplementation(" + mCurUser + ")"); } else { t = null; } Loading Loading @@ -494,7 +507,7 @@ public class VoiceInteractionManagerService extends SystemService { final boolean hasComponent = serviceComponent != null && serviceInfo != null; if (mUserManager.isUserUnlockingOrUnlocked(mCurUser)) { if (mUserManagerInternal.isUserUnlockingOrUnlocked(mCurUser)) { if (hasComponent) { mShortcutServiceInternal.setShortcutHostPackage(TAG, serviceComponent.getPackageName(), mCurUser); Loading Loading @@ -1275,6 +1288,9 @@ public class VoiceInteractionManagerService extends SystemService { synchronized (this) { pw.println("VOICE INTERACTION MANAGER (dumpsys voiceinteraction)"); pw.println(" mEnableService: " + mEnableService); pw.println(" mCurUser: " + mCurUser); pw.println(" mCurUserUnlocked: " + mCurUserUnlocked); pw.println(" mCurUserSupported: " + mCurUserSupported); if (mImpl == null) { pw.println(" (No active implementation)"); return; Loading