diff options
author | Amith Yamasani <yamasani@google.com> | 2014-03-04 16:48:05 -0800 |
---|---|---|
committer | Amith Yamasani <yamasani@google.com> | 2014-03-07 17:41:24 -0800 |
commit | 734983fff35d9ed2b7a9848bdfbca401887d0dd8 (patch) | |
tree | 0f7514529fe469f5e1b1586cd9306b785fb3fcc6 /services/core/java | |
parent | 16340670aff0ec980fff4354d785a38b11c33d3b (diff) | |
download | frameworks_base-734983fff35d9ed2b7a9848bdfbca401887d0dd8.zip frameworks_base-734983fff35d9ed2b7a9848bdfbca401887d0dd8.tar.gz frameworks_base-734983fff35d9ed2b7a9848bdfbca401887d0dd8.tar.bz2 |
Allow related users to show activities on primary user
Make ActivityManager and WindowManager understand related users.
Task stack will now contain interleaved tasks for related users,
but still group regular users separately from groups of related users.
InputMethodManagerService permits related users to invoke IME and receive
key events.
Change-Id: I3bd87b32aec69c3f8d470c8b29b144f4e849c808
Diffstat (limited to 'services/core/java')
6 files changed, 87 insertions, 16 deletions
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) { |