diff options
7 files changed, 104 insertions, 16 deletions
diff --git a/core/java/com/android/internal/inputmethod/InputMethodUtils.java b/core/java/com/android/internal/inputmethod/InputMethodUtils.java index bc051ce..03a053c 100644 --- a/core/java/com/android/internal/inputmethod/InputMethodUtils.java +++ b/core/java/com/android/internal/inputmethod/InputMethodUtils.java @@ -504,6 +504,7 @@ public class InputMethodUtils { private String mEnabledInputMethodsStrCache; private int mCurrentUserId; + private int[] mRelatedUserIds = new int[0]; private static void buildEnabledInputMethodsSettingString( StringBuilder builder, Pair<String, ArrayList<String>> pair) { @@ -536,6 +537,22 @@ public class InputMethodUtils { mCurrentUserId = userId; } + public void setRelatedUserIds(int[] relatedUserIds) { + synchronized (this) { + mRelatedUserIds = relatedUserIds; + } + } + + public boolean isRelatedToOrCurrentUser(int userId) { + synchronized (this) { + if (userId == mCurrentUserId) return true; + for (int i = 0; i < mRelatedUserIds.length; i++) { + if (userId == mRelatedUserIds[i]) return true; + } + return false; + } + } + public List<InputMethodInfo> getEnabledInputMethodListLocked() { return createEnabledInputMethodListLocked( getEnabledInputMethodsAndSubtypeListLocked()); diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java index 0b3eb12..6827b3f 100644 --- a/services/core/java/com/android/server/InputMethodManagerService.java +++ b/services/core/java/com/android/server/InputMethodManagerService.java @@ -59,6 +59,7 @@ import android.content.pm.IPackageManager; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; +import android.content.pm.UserInfo; import android.content.res.Configuration; import android.content.res.Resources; import android.content.res.TypedArray; @@ -78,6 +79,7 @@ import android.os.ResultReceiver; import android.os.ServiceManager; import android.os.SystemClock; import android.os.UserHandle; +import android.os.UserManager; import android.provider.Settings; import android.text.TextUtils; import android.text.style.SuggestionSpan; @@ -441,6 +443,10 @@ public class InputMethodManagerService extends IInputMethodManager.Stub hideInputMethodMenu(); // No need to updateActive return; + } else if (Intent.ACTION_USER_ADDED.equals(action) + || Intent.ACTION_USER_REMOVED.equals(action)) { + updateRelatedUserIds(); + return; } else { Slog.w(TAG, "Unexpected intent " + intent); } @@ -642,6 +648,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub broadcastFilter.addAction(Intent.ACTION_SCREEN_ON); broadcastFilter.addAction(Intent.ACTION_SCREEN_OFF); broadcastFilter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); + broadcastFilter.addAction(Intent.ACTION_USER_ADDED); + broadcastFilter.addAction(Intent.ACTION_USER_REMOVED); mContext.registerReceiver(new ImmsBroadcastReceiver(), broadcastFilter); mNotificationShown = false; @@ -675,6 +683,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub // mSettings should be created before buildInputMethodListLocked mSettings = new InputMethodSettings( mRes, context.getContentResolver(), mMethodMap, mMethodList, userId); + updateRelatedUserIds(); mFileManager = new InputMethodFileManager(mMethodMap, userId); mSwitchingController = new InputMethodSubtypeSwitchingController(mSettings); mSwitchingController.resetCircularListLocked(context); @@ -790,6 +799,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub private void switchUserLocked(int newUserId) { mSettings.setCurrentUserId(newUserId); + updateRelatedUserIds(); // InputMethodFileManager should be reset when the user is changed mFileManager = new InputMethodFileManager(mMethodMap, newUserId); final String defaultImiId = mSettings.getSelectedInputMethod(); @@ -810,6 +820,16 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } } + void updateRelatedUserIds() { + List<UserInfo> relatedUsers = + UserManager.get(mContext).getRelatedUsers(mSettings.getCurrentUserId()); + int[] relatedUserIds = new int[relatedUsers.size()]; // relatedUsers will not be null + for (int i = 0; i < relatedUserIds.length; i++) { + relatedUserIds[i] = relatedUsers.get(i).id; + } + mSettings.setRelatedUserIds(relatedUserIds); + } + @Override public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { @@ -905,7 +925,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub + mSettings.getCurrentUserId() + ", calling pid = " + Binder.getCallingPid() + InputMethodUtils.getApiCallStack()); } - if (uid == Process.SYSTEM_UID || userId == mSettings.getCurrentUserId()) { + if (uid == Process.SYSTEM_UID || mSettings.isRelatedToOrCurrentUser(userId)) { return true; } diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 782868e..f39e634 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -1015,6 +1015,7 @@ public final class ActivityManagerService extends ActivityManagerNative final ActivityThread mSystemThread; int mCurrentUserId = 0; + int[] mRelatedUserIds = new int[0]; // Accessed by ActivityStack private UserManagerService mUserManager; private final class AppDeathRecipient implements IBinder.DeathRecipient { @@ -16097,6 +16098,20 @@ public final class ActivityManagerService extends ActivityManagerNative return startUser(userId, /* foreground */ false); } + /** + * Refreshes the list of users related to the current user when either a + * user switch happens or when a new related user is started in the + * background. + */ + private void updateRelatedUserIdsLocked() { + final List<UserInfo> relatedUsers = getUserManagerLocked().getRelatedUsers(mCurrentUserId); + int[] relatedUserIds = new int[relatedUsers.size()]; // relatedUsers will not be null + for (int i = 0; i < relatedUserIds.length; i++) { + relatedUserIds[i] = relatedUsers.get(i).id; + } + mRelatedUserIds = relatedUserIds; + } + @Override public boolean switchUser(final int userId) { return startUser(userId, /* foregound */ true); @@ -16150,12 +16165,15 @@ public final class ActivityManagerService extends ActivityManagerNative if (foreground) { mCurrentUserId = userId; - mWindowManager.setCurrentUser(userId); + updateRelatedUserIdsLocked(); + mWindowManager.setCurrentUser(userId, mRelatedUserIds); // Once the internal notion of the active user has switched, we lock the device // with the option to show the user switcher on the keyguard. mWindowManager.lockNow(null); } else { final Integer currentUserIdInt = Integer.valueOf(mCurrentUserId); + updateRelatedUserIdsLocked(); + mWindowManager.updateRelatedUserIds(mRelatedUserIds); mUserLru.remove(currentUserIdInt); mUserLru.add(currentUserIdInt); } diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index 922cef4..f3ccdd6 100755 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -341,8 +341,19 @@ final class ActivityStack { mCurrentUser = mService.mCurrentUserId; } - boolean okToShow(ActivityRecord r) { - return r.userId == mCurrentUser + /** + * Checks whether the userid is either the current user or a related user. + */ + private boolean isRelatedToOrCurrentUserLocked(int userId) { + if (mCurrentUser == userId) return true; + for (int i = 0; i < mService.mRelatedUserIds.length; i++) { + if (mService.mRelatedUserIds[i] == userId) return true; + } + return false; + } + + boolean okToShowLocked(ActivityRecord r) { + return isRelatedToOrCurrentUserLocked(r.userId) || (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0; } @@ -362,7 +373,7 @@ final class ActivityStack { final ArrayList<ActivityRecord> activities = task.mActivities; for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { ActivityRecord r = activities.get(activityNdx); - if (!r.finishing && !r.delayedResume && r != notTop && okToShow(r)) { + if (!r.finishing && !r.delayedResume && r != notTop && okToShowLocked(r)) { return r; } } @@ -389,7 +400,7 @@ final class ActivityStack { for (int i = activities.size() - 1; i >= 0; --i) { final ActivityRecord r = activities.get(i); // Note: the taskId check depends on real taskId fields being non-zero - if (!r.finishing && (token != r.appToken) && okToShow(r)) { + if (!r.finishing && (token != r.appToken) && okToShowLocked(r)) { return r; } } @@ -542,7 +553,7 @@ final class ActivityStack { for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { TaskRecord task = mTaskHistory.get(taskNdx); - if (task.userId != mCurrentUser) { + if (!isRelatedToOrCurrentUserLocked(task.userId)) { return null; } final ArrayList<ActivityRecord> activities = task.mActivities; @@ -573,7 +584,7 @@ final class ActivityStack { int index = mTaskHistory.size(); for (int i = 0; i < index; ) { TaskRecord task = mTaskHistory.get(i); - if (task.userId == userId) { + if (isRelatedToOrCurrentUserLocked(task.userId)) { if (DEBUG_TASKS) Slog.d(TAG, "switchUserLocked: stack=" + getStackId() + " moving " + task + " to top"); mTaskHistory.remove(i); @@ -1728,10 +1739,10 @@ final class ActivityStack { mTaskHistory.remove(task); // Now put task at top. int stackNdx = mTaskHistory.size(); - if (task.userId != mCurrentUser) { + if (!isRelatedToOrCurrentUserLocked(task.userId)) { // Put non-current user tasks below current user tasks. while (--stackNdx >= 0) { - if (mTaskHistory.get(stackNdx).userId != mCurrentUser) { + if (!isRelatedToOrCurrentUserLocked(mTaskHistory.get(stackNdx).userId)) { break; } } diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java index 9740812..3a43521 100644 --- a/services/core/java/com/android/server/am/TaskRecord.java +++ b/services/core/java/com/android/server/am/TaskRecord.java @@ -153,7 +153,7 @@ final class TaskRecord extends ThumbnailHolder { ActivityRecord topRunningActivityLocked(ActivityRecord notTop) { for (int activityNdx = mActivities.size() - 1; activityNdx >= 0; --activityNdx) { ActivityRecord r = mActivities.get(activityNdx); - if (!r.finishing && r != notTop && stack.okToShow(r)) { + if (!r.finishing && r != notTop && stack.okToShowLocked(r)) { return r; } } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index c006613..be94ca7 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -19,7 +19,6 @@ package com.android.server.wm; import static android.view.WindowManager.LayoutParams.*; import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; - import android.app.AppOpsManager; import android.util.ArraySet; import android.util.TimeUtils; @@ -302,8 +301,16 @@ public class WindowManagerService extends IWindowManager.Stub } }; - // Current user when multi-user is enabled. Don't show windows of non-current user. + /** + * Current user when multi-user is enabled. Don't show windows of + * non-current user. Also see mRelatedUserIds. + */ int mCurrentUserId; + /** + * Users related to the current user. These are also allowed to show windows + * on the current user. + */ + int[] mRelatedUserIds = new int[0]; final Context mContext; @@ -5284,10 +5291,16 @@ public class WindowManagerService extends IWindowManager.Stub mPolicy.setTouchExplorationEnabled(enabled); } - public void setCurrentUser(final int newUserId) { + public void updateRelatedUserIds(final int[] relatedUserIds) { + synchronized (mWindowMap) { + mRelatedUserIds = relatedUserIds; + } + } + + public void setCurrentUser(final int newUserId, final int[] relatedUserIds) { synchronized (mWindowMap) { - int oldUserId = mCurrentUserId; mCurrentUserId = newUserId; + mRelatedUserIds = relatedUserIds; mAppTransition.setCurrentUser(newUserId); mPolicy.setCurrentUserLw(newUserId); @@ -5302,6 +5315,15 @@ public class WindowManagerService extends IWindowManager.Stub } } + /* Called by WindowState */ + boolean isRelatedToOrCurrentUserLocked(int userId) { + if (userId == mCurrentUserId) return true; + for (int i = 0; i < mRelatedUserIds.length; i++) { + if (mRelatedUserIds[i] == userId) return true; + } + return false; + } + public void enableScreenAfterBoot() { synchronized(mWindowMap) { if (DEBUG_BOOT) { diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index a8e45c4..2c0e99e 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -1249,7 +1249,7 @@ final class WindowState implements WindowManagerPolicy.WindowState { } return win.mShowToOwnerOnly - && UserHandle.getUserId(win.mOwnerUid) != mService.mCurrentUserId; + && !mService.isRelatedToOrCurrentUserLocked(UserHandle.getUserId(win.mOwnerUid)); } private static void applyInsets(Region outRegion, Rect frame, Rect inset) { |