Loading core/java/android/hardware/display/DisplayManagerInternal.java +17 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,8 @@ package android.hardware.display; import android.hardware.SensorManager; import android.os.Handler; import android.os.PowerManager; import android.util.IntArray; import android.util.SparseArray; import android.view.Display; import android.view.DisplayInfo; Loading Loading @@ -146,6 +148,21 @@ public abstract class DisplayManagerInternal { */ public abstract void setDisplayOffsets(int displayId, int x, int y); /** * Provide a list of UIDs that are present on the display and are allowed to access it. * * @param displayAccessUIDs Mapping displayId -> int array of UIDs. */ public abstract void setDisplayAccessUIDs(SparseArray<IntArray> displayAccessUIDs); /** * Check if specified UID's content is present on display and should be granted access to it. * * @param uid UID to be checked. * @param displayId id of the display where presence of the content is checked. * */ public abstract boolean isUidPresentOnDisplay(int uid, int displayId); /** * Describes the requested power state of the display. * Loading core/java/android/view/WindowManagerPolicy.java +2 −1 Original line number Diff line number Diff line Loading @@ -750,13 +750,14 @@ public interface WindowManagerPolicy { * @param windowFlags Window layout flags. * @param overrideConfig override configuration to consider when generating * context to for resources. * @param displayId Id of the display to show the splash screen at. * * @return The starting surface. * */ public StartingSurface addSplashScreen(IBinder appToken, String packageName, int theme, CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, int windowFlags, Configuration overrideConfig); int logo, int windowFlags, Configuration overrideConfig, int displayId); /** * Prepare for a window being added to the window manager. You can throw an Loading services/core/java/com/android/server/am/ActivityRecord.java +8 −4 Original line number Diff line number Diff line Loading @@ -149,6 +149,7 @@ final class ActivityRecord implements AppWindowContainerListener { AppWindowContainerController mWindowContainerController; final ActivityInfo info; // all about me final ApplicationInfo appInfo; // information about activity's app final int launchedFromPid; // always the pid who started the activity. final int launchedFromUid; // always the uid who started the activity. final String launchedFromPackage; // always the package who started the activity. final int userId; // Which user is this running for? Loading Loading @@ -588,7 +589,7 @@ final class ActivityRecord implements AppWindowContainerListener { return ResolverActivity.class.getName().equals(realActivity.getClassName()); } ActivityRecord(ActivityManagerService _service, ProcessRecord _caller, ActivityRecord(ActivityManagerService _service, ProcessRecord _caller, int _launchedFromPid, int _launchedFromUid, String _launchedFromPackage, Intent _intent, String _resolvedType, ActivityInfo aInfo, Configuration _configuration, ActivityRecord _resultTo, String _resultWho, int _reqCode, Loading @@ -598,6 +599,7 @@ final class ActivityRecord implements AppWindowContainerListener { service = _service; appToken = new Token(this); info = aInfo; launchedFromPid = _launchedFromPid; launchedFromUid = _launchedFromUid; launchedFromPackage = _launchedFromPackage; userId = UserHandle.getUserId(aInfo.applicationInfo.uid); Loading Loading @@ -2192,9 +2194,11 @@ final class ActivityRecord implements AppWindowContainerListener { throw new XmlPullParserException("restoreActivity resolver error. Intent=" + intent + " resolvedType=" + resolvedType); } final ActivityRecord r = new ActivityRecord(service, /*caller*/null, launchedFromUid, launchedFromPackage, intent, resolvedType, aInfo, service.getConfiguration(), null, null, 0, componentSpecified, false, stackSupervisor, null, null, null); final ActivityRecord r = new ActivityRecord(service, null /* caller */, 0 /* launchedFromPid */, launchedFromUid, launchedFromPackage, intent, resolvedType, aInfo, service.getConfiguration(), null /* resultTo */, null /* resultWho */, 0 /* reqCode */, componentSpecified, false /* rootVoiceInteraction */, stackSupervisor, null /* container */, null /* options */, null /* sourceRecord */); r.persistentState = persistentState; r.taskDescription = taskDescription; Loading services/core/java/com/android/server/am/ActivityStack.java +30 −2 Original line number Diff line number Diff line Loading @@ -105,6 +105,7 @@ import android.os.UserHandle; import android.service.voice.IVoiceInteractionSession; import android.util.ArraySet; import android.util.EventLog; import android.util.IntArray; import android.util.Log; import android.util.Slog; import android.util.SparseArray; Loading Loading @@ -195,6 +196,12 @@ final class ActivityStack extends ConfigurationContainer { return mActivityContainer.mActivityDisplay; } @Override void onParentChanged() { super.onParentChanged(); mStackSupervisor.updateUIDsPresentOnDisplay(); } enum ActivityState { INITIALIZING, RESUMED, Loading Loading @@ -680,6 +687,27 @@ final class ActivityStack extends ConfigurationContainer { return null; } boolean isInStackLocked(TaskRecord task) { return mTaskHistory.contains(task); } /** Checks if there are tasks with specific UID in the stack. */ boolean isUidPresent(int uid) { for (TaskRecord task : mTaskHistory) { if (task.effectiveUid == uid) { return true; } } return false; } /** Get all UIDs that are present in the stack. */ void getPresentUIDs(IntArray presentUIDs) { for (TaskRecord task : mTaskHistory) { presentUIDs.add(task.effectiveUid); } } final boolean updateLRUListLocked(ActivityRecord r) { final boolean hadit = mLRUActivities.remove(r); mLRUActivities.add(r); Loading Loading @@ -4878,13 +4906,13 @@ final class ActivityStack extends ConfigurationContainer { final boolean toTop = position >= mTaskHistory.size(); final ActivityStack prevStack = preAddTask(task, reason, toTop); mTaskHistory.add(position, task); task.setStack(this); if (toTop) { updateTaskReturnToForTopInsertion(task); } mTaskHistory.add(position, task); updateTaskMovement(task, toTop); postAddTask(task, prevStack); Loading @@ -4901,8 +4929,8 @@ final class ActivityStack extends ConfigurationContainer { final ActivityRecord topRunningActivity = task.topRunningActivityLocked(); final boolean wasResumed = topRunningActivity == task.getStack().mResumedActivity; task.setStack(this); insertTaskAtPosition(task, index); task.setStack(this); postAddTask(task, null /* prevStack */); if (wasResumed) { Loading services/core/java/com/android/server/am/ActivityStackSupervisor.java +97 −15 Original line number Diff line number Diff line Loading @@ -125,6 +125,7 @@ import android.graphics.Rect; import android.hardware.display.DisplayManager; import android.hardware.display.DisplayManager.DisplayListener; import android.hardware.display.DisplayManagerGlobal; import android.hardware.display.DisplayManagerInternal; import android.hardware.display.VirtualDisplay; import android.hardware.input.InputManager; import android.hardware.input.InputManagerInternal; Loading Loading @@ -154,6 +155,7 @@ import android.util.ArrayMap; import android.util.ArraySet; import android.util.DisplayMetrics; import android.util.EventLog; import android.util.IntArray; import android.util.Slog; import android.util.SparseArray; import android.util.SparseIntArray; Loading Loading @@ -380,7 +382,10 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D /** Mapping from displayId to display current state */ private final SparseArray<ActivityDisplay> mActivityDisplays = new SparseArray<>(); InputManagerInternal mInputManagerInternal; private final SparseArray<IntArray> mDisplayAccessUIDs = new SparseArray<>(); private DisplayManagerInternal mDisplayManagerInternal; private InputManagerInternal mInputManagerInternal; /** The chain of tasks in lockTask mode. The current frontmost task is at the top, and tasks * may be finished until there is only one entry left. If this is empty the system is not Loading Loading @@ -580,6 +585,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D mDisplayManager = (DisplayManager)mService.mContext.getSystemService(Context.DISPLAY_SERVICE); mDisplayManager.registerDisplayListener(this, null); mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class); Display[] displays = mDisplayManager.getDisplays(); for (int displayNdx = displays.length - 1; displayNdx >= 0; --displayNdx) { Loading Loading @@ -1519,11 +1525,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D // Check if someone tries to launch an activity on a private display with a different // owner. final int launchDisplayId = options.getLaunchDisplayId(); if (launchDisplayId != INVALID_DISPLAY) { final ActivityDisplay activityDisplay = mActivityDisplays.get(launchDisplayId); if (activityDisplay != null && (activityDisplay.mDisplay.getFlags() & FLAG_PRIVATE) != 0) { if (activityDisplay.mDisplay.getOwnerUid() != callingUid) { if (launchDisplayId != INVALID_DISPLAY && !isCallerAllowedToLaunchOnDisplay(callingPid, callingUid, launchDisplayId)) { final String msg = "Permission Denial: starting " + intent.toString() + " from " + callerApp + " (pid=" + callingPid + ", uid=" + callingUid + ") with launchDisplayId=" Loading @@ -1532,12 +1535,66 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D throw new SecurityException(msg); } } return true; } /** Check if caller is allowed to launch activities on specified display. */ boolean isCallerAllowedToLaunchOnDisplay(int callingPid, int callingUid, int launchDisplayId) { if (DEBUG_TASKS) Slog.d(TAG, "Launch on display check: displayId=" + launchDisplayId + " callingPid=" + callingPid + " callingUid=" + callingUid); final ActivityDisplay activityDisplay = mActivityDisplays.get(launchDisplayId); if (activityDisplay == null) { Slog.w(TAG, "Launch on display check: display not found"); return false; } if (!activityDisplay.isPrivate()) { // Anyone can launch on a public display. if (DEBUG_TASKS) Slog.d(TAG, "Launch on display check:" + " allow launch on public display"); return true; } // Check if the caller is the owner of the display. if (activityDisplay.mDisplay.getOwnerUid() == callingUid) { if (DEBUG_TASKS) Slog.d(TAG, "Launch on display check:" + " allow launch for owner of the display"); return true; } // Check if caller is present on display if (activityDisplay.isUidPresent(callingUid)) { if (DEBUG_TASKS) Slog.d(TAG, "Launch on display check:" + " allow launch for caller present on the display"); return true; } // Check if the caller can launch anything. final int startAnyPerm = mService.checkPermission(START_ANY_ACTIVITY, callingPid, callingUid); if (startAnyPerm == PERMISSION_GRANTED) { if (DEBUG_TASKS) Slog.d(TAG, "Launch on display check:" + " allow launch any on display"); return true; } Slog.w(TAG, "Launch on display check: denied"); return false; } /** Update lists of UIDs that are present on displays and have access to them. */ void updateUIDsPresentOnDisplay() { mDisplayAccessUIDs.clear(); for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { final ActivityDisplay activityDisplay = mActivityDisplays.valueAt(displayNdx); mDisplayAccessUIDs.append(activityDisplay.mDisplayId, activityDisplay.getPresentUIDs()); } // Store updated lists in DisplayManager. Callers from outside of AM should get them there. mDisplayManagerInternal.setDisplayAccessUIDs(mDisplayAccessUIDs); } UserInfo getUserInfo(int userId) { final long identity = Binder.clearCallingIdentity(); try { Loading Loading @@ -4586,6 +4643,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D ActivityRecord mVisibleBehindActivity; /** Array of all UIDs that are present on the display. */ private IntArray mDisplayAccessUIDs = new IntArray(); ActivityDisplay() { } Loading Loading @@ -4648,6 +4708,28 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D protected ConfigurationContainer getParent() { return ActivityStackSupervisor.this; } boolean isPrivate() { return (mDisplay.getFlags() & FLAG_PRIVATE) != 0; } boolean isUidPresent(int uid) { for (ActivityStack stack : mStacks) { if (stack.isUidPresent(uid)) { return true; } } return false; } /** Update and get all UIDs that are present on the display and have access to it. */ private IntArray getPresentUIDs() { mDisplayAccessUIDs.clear(); for (ActivityStack stack : mStacks) { stack.getPresentUIDs(mDisplayAccessUIDs); } return mDisplayAccessUIDs; } } class VirtualActivityDisplay extends ActivityDisplay { Loading Loading
core/java/android/hardware/display/DisplayManagerInternal.java +17 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,8 @@ package android.hardware.display; import android.hardware.SensorManager; import android.os.Handler; import android.os.PowerManager; import android.util.IntArray; import android.util.SparseArray; import android.view.Display; import android.view.DisplayInfo; Loading Loading @@ -146,6 +148,21 @@ public abstract class DisplayManagerInternal { */ public abstract void setDisplayOffsets(int displayId, int x, int y); /** * Provide a list of UIDs that are present on the display and are allowed to access it. * * @param displayAccessUIDs Mapping displayId -> int array of UIDs. */ public abstract void setDisplayAccessUIDs(SparseArray<IntArray> displayAccessUIDs); /** * Check if specified UID's content is present on display and should be granted access to it. * * @param uid UID to be checked. * @param displayId id of the display where presence of the content is checked. * */ public abstract boolean isUidPresentOnDisplay(int uid, int displayId); /** * Describes the requested power state of the display. * Loading
core/java/android/view/WindowManagerPolicy.java +2 −1 Original line number Diff line number Diff line Loading @@ -750,13 +750,14 @@ public interface WindowManagerPolicy { * @param windowFlags Window layout flags. * @param overrideConfig override configuration to consider when generating * context to for resources. * @param displayId Id of the display to show the splash screen at. * * @return The starting surface. * */ public StartingSurface addSplashScreen(IBinder appToken, String packageName, int theme, CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, int windowFlags, Configuration overrideConfig); int logo, int windowFlags, Configuration overrideConfig, int displayId); /** * Prepare for a window being added to the window manager. You can throw an Loading
services/core/java/com/android/server/am/ActivityRecord.java +8 −4 Original line number Diff line number Diff line Loading @@ -149,6 +149,7 @@ final class ActivityRecord implements AppWindowContainerListener { AppWindowContainerController mWindowContainerController; final ActivityInfo info; // all about me final ApplicationInfo appInfo; // information about activity's app final int launchedFromPid; // always the pid who started the activity. final int launchedFromUid; // always the uid who started the activity. final String launchedFromPackage; // always the package who started the activity. final int userId; // Which user is this running for? Loading Loading @@ -588,7 +589,7 @@ final class ActivityRecord implements AppWindowContainerListener { return ResolverActivity.class.getName().equals(realActivity.getClassName()); } ActivityRecord(ActivityManagerService _service, ProcessRecord _caller, ActivityRecord(ActivityManagerService _service, ProcessRecord _caller, int _launchedFromPid, int _launchedFromUid, String _launchedFromPackage, Intent _intent, String _resolvedType, ActivityInfo aInfo, Configuration _configuration, ActivityRecord _resultTo, String _resultWho, int _reqCode, Loading @@ -598,6 +599,7 @@ final class ActivityRecord implements AppWindowContainerListener { service = _service; appToken = new Token(this); info = aInfo; launchedFromPid = _launchedFromPid; launchedFromUid = _launchedFromUid; launchedFromPackage = _launchedFromPackage; userId = UserHandle.getUserId(aInfo.applicationInfo.uid); Loading Loading @@ -2192,9 +2194,11 @@ final class ActivityRecord implements AppWindowContainerListener { throw new XmlPullParserException("restoreActivity resolver error. Intent=" + intent + " resolvedType=" + resolvedType); } final ActivityRecord r = new ActivityRecord(service, /*caller*/null, launchedFromUid, launchedFromPackage, intent, resolvedType, aInfo, service.getConfiguration(), null, null, 0, componentSpecified, false, stackSupervisor, null, null, null); final ActivityRecord r = new ActivityRecord(service, null /* caller */, 0 /* launchedFromPid */, launchedFromUid, launchedFromPackage, intent, resolvedType, aInfo, service.getConfiguration(), null /* resultTo */, null /* resultWho */, 0 /* reqCode */, componentSpecified, false /* rootVoiceInteraction */, stackSupervisor, null /* container */, null /* options */, null /* sourceRecord */); r.persistentState = persistentState; r.taskDescription = taskDescription; Loading
services/core/java/com/android/server/am/ActivityStack.java +30 −2 Original line number Diff line number Diff line Loading @@ -105,6 +105,7 @@ import android.os.UserHandle; import android.service.voice.IVoiceInteractionSession; import android.util.ArraySet; import android.util.EventLog; import android.util.IntArray; import android.util.Log; import android.util.Slog; import android.util.SparseArray; Loading Loading @@ -195,6 +196,12 @@ final class ActivityStack extends ConfigurationContainer { return mActivityContainer.mActivityDisplay; } @Override void onParentChanged() { super.onParentChanged(); mStackSupervisor.updateUIDsPresentOnDisplay(); } enum ActivityState { INITIALIZING, RESUMED, Loading Loading @@ -680,6 +687,27 @@ final class ActivityStack extends ConfigurationContainer { return null; } boolean isInStackLocked(TaskRecord task) { return mTaskHistory.contains(task); } /** Checks if there are tasks with specific UID in the stack. */ boolean isUidPresent(int uid) { for (TaskRecord task : mTaskHistory) { if (task.effectiveUid == uid) { return true; } } return false; } /** Get all UIDs that are present in the stack. */ void getPresentUIDs(IntArray presentUIDs) { for (TaskRecord task : mTaskHistory) { presentUIDs.add(task.effectiveUid); } } final boolean updateLRUListLocked(ActivityRecord r) { final boolean hadit = mLRUActivities.remove(r); mLRUActivities.add(r); Loading Loading @@ -4878,13 +4906,13 @@ final class ActivityStack extends ConfigurationContainer { final boolean toTop = position >= mTaskHistory.size(); final ActivityStack prevStack = preAddTask(task, reason, toTop); mTaskHistory.add(position, task); task.setStack(this); if (toTop) { updateTaskReturnToForTopInsertion(task); } mTaskHistory.add(position, task); updateTaskMovement(task, toTop); postAddTask(task, prevStack); Loading @@ -4901,8 +4929,8 @@ final class ActivityStack extends ConfigurationContainer { final ActivityRecord topRunningActivity = task.topRunningActivityLocked(); final boolean wasResumed = topRunningActivity == task.getStack().mResumedActivity; task.setStack(this); insertTaskAtPosition(task, index); task.setStack(this); postAddTask(task, null /* prevStack */); if (wasResumed) { Loading
services/core/java/com/android/server/am/ActivityStackSupervisor.java +97 −15 Original line number Diff line number Diff line Loading @@ -125,6 +125,7 @@ import android.graphics.Rect; import android.hardware.display.DisplayManager; import android.hardware.display.DisplayManager.DisplayListener; import android.hardware.display.DisplayManagerGlobal; import android.hardware.display.DisplayManagerInternal; import android.hardware.display.VirtualDisplay; import android.hardware.input.InputManager; import android.hardware.input.InputManagerInternal; Loading Loading @@ -154,6 +155,7 @@ import android.util.ArrayMap; import android.util.ArraySet; import android.util.DisplayMetrics; import android.util.EventLog; import android.util.IntArray; import android.util.Slog; import android.util.SparseArray; import android.util.SparseIntArray; Loading Loading @@ -380,7 +382,10 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D /** Mapping from displayId to display current state */ private final SparseArray<ActivityDisplay> mActivityDisplays = new SparseArray<>(); InputManagerInternal mInputManagerInternal; private final SparseArray<IntArray> mDisplayAccessUIDs = new SparseArray<>(); private DisplayManagerInternal mDisplayManagerInternal; private InputManagerInternal mInputManagerInternal; /** The chain of tasks in lockTask mode. The current frontmost task is at the top, and tasks * may be finished until there is only one entry left. If this is empty the system is not Loading Loading @@ -580,6 +585,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D mDisplayManager = (DisplayManager)mService.mContext.getSystemService(Context.DISPLAY_SERVICE); mDisplayManager.registerDisplayListener(this, null); mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class); Display[] displays = mDisplayManager.getDisplays(); for (int displayNdx = displays.length - 1; displayNdx >= 0; --displayNdx) { Loading Loading @@ -1519,11 +1525,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D // Check if someone tries to launch an activity on a private display with a different // owner. final int launchDisplayId = options.getLaunchDisplayId(); if (launchDisplayId != INVALID_DISPLAY) { final ActivityDisplay activityDisplay = mActivityDisplays.get(launchDisplayId); if (activityDisplay != null && (activityDisplay.mDisplay.getFlags() & FLAG_PRIVATE) != 0) { if (activityDisplay.mDisplay.getOwnerUid() != callingUid) { if (launchDisplayId != INVALID_DISPLAY && !isCallerAllowedToLaunchOnDisplay(callingPid, callingUid, launchDisplayId)) { final String msg = "Permission Denial: starting " + intent.toString() + " from " + callerApp + " (pid=" + callingPid + ", uid=" + callingUid + ") with launchDisplayId=" Loading @@ -1532,12 +1535,66 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D throw new SecurityException(msg); } } return true; } /** Check if caller is allowed to launch activities on specified display. */ boolean isCallerAllowedToLaunchOnDisplay(int callingPid, int callingUid, int launchDisplayId) { if (DEBUG_TASKS) Slog.d(TAG, "Launch on display check: displayId=" + launchDisplayId + " callingPid=" + callingPid + " callingUid=" + callingUid); final ActivityDisplay activityDisplay = mActivityDisplays.get(launchDisplayId); if (activityDisplay == null) { Slog.w(TAG, "Launch on display check: display not found"); return false; } if (!activityDisplay.isPrivate()) { // Anyone can launch on a public display. if (DEBUG_TASKS) Slog.d(TAG, "Launch on display check:" + " allow launch on public display"); return true; } // Check if the caller is the owner of the display. if (activityDisplay.mDisplay.getOwnerUid() == callingUid) { if (DEBUG_TASKS) Slog.d(TAG, "Launch on display check:" + " allow launch for owner of the display"); return true; } // Check if caller is present on display if (activityDisplay.isUidPresent(callingUid)) { if (DEBUG_TASKS) Slog.d(TAG, "Launch on display check:" + " allow launch for caller present on the display"); return true; } // Check if the caller can launch anything. final int startAnyPerm = mService.checkPermission(START_ANY_ACTIVITY, callingPid, callingUid); if (startAnyPerm == PERMISSION_GRANTED) { if (DEBUG_TASKS) Slog.d(TAG, "Launch on display check:" + " allow launch any on display"); return true; } Slog.w(TAG, "Launch on display check: denied"); return false; } /** Update lists of UIDs that are present on displays and have access to them. */ void updateUIDsPresentOnDisplay() { mDisplayAccessUIDs.clear(); for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { final ActivityDisplay activityDisplay = mActivityDisplays.valueAt(displayNdx); mDisplayAccessUIDs.append(activityDisplay.mDisplayId, activityDisplay.getPresentUIDs()); } // Store updated lists in DisplayManager. Callers from outside of AM should get them there. mDisplayManagerInternal.setDisplayAccessUIDs(mDisplayAccessUIDs); } UserInfo getUserInfo(int userId) { final long identity = Binder.clearCallingIdentity(); try { Loading Loading @@ -4586,6 +4643,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D ActivityRecord mVisibleBehindActivity; /** Array of all UIDs that are present on the display. */ private IntArray mDisplayAccessUIDs = new IntArray(); ActivityDisplay() { } Loading Loading @@ -4648,6 +4708,28 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D protected ConfigurationContainer getParent() { return ActivityStackSupervisor.this; } boolean isPrivate() { return (mDisplay.getFlags() & FLAG_PRIVATE) != 0; } boolean isUidPresent(int uid) { for (ActivityStack stack : mStacks) { if (stack.isUidPresent(uid)) { return true; } } return false; } /** Update and get all UIDs that are present on the display and have access to it. */ private IntArray getPresentUIDs() { mDisplayAccessUIDs.clear(); for (ActivityStack stack : mStacks) { stack.getPresentUIDs(mDisplayAccessUIDs); } return mDisplayAccessUIDs; } } class VirtualActivityDisplay extends ActivityDisplay { Loading