Merge "If the calling process isn't whitelisted for background activity start, check the other processes of calling UID too" into qt-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
df573a6210
@@ -986,31 +986,6 @@ class ActivityStarter {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If we don't have callerApp at this point, no caller was provided to startActivity().
|
|
||||||
// That's the case for PendingIntent-based starts, since the creator's process might not be
|
|
||||||
// up and alive. If that's the case, we retrieve the WindowProcessController for the send()
|
|
||||||
// caller, so that we can make the decision based on its foreground/whitelisted state.
|
|
||||||
if (callerApp == null) {
|
|
||||||
callerApp = mService.getProcessController(realCallingPid, realCallingUid);
|
|
||||||
}
|
|
||||||
if (callerApp != null) {
|
|
||||||
// don't abort if the callerApp is instrumenting with background activity starts privs
|
|
||||||
if (callerApp.isInstrumentingWithBackgroundActivityStartPrivileges()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// don't abort if the caller is currently temporarily whitelisted
|
|
||||||
if (callerApp.areBackgroundActivityStartsAllowed()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// don't abort if the caller has an activity in any foreground task
|
|
||||||
if (callerApp.hasActivityInVisibleTask()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// don't abort if the caller is bound by a UID that's currently foreground
|
|
||||||
if (isBoundByForegroundUid(callerApp)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// don't abort if the callingUid has START_ACTIVITIES_FROM_BACKGROUND permission
|
// don't abort if the callingUid has START_ACTIVITIES_FROM_BACKGROUND permission
|
||||||
if (mService.checkPermission(START_ACTIVITIES_FROM_BACKGROUND, callingPid, callingUid)
|
if (mService.checkPermission(START_ACTIVITIES_FROM_BACKGROUND, callingPid, callingUid)
|
||||||
== PERMISSION_GRANTED) {
|
== PERMISSION_GRANTED) {
|
||||||
@@ -1035,6 +1010,33 @@ class ActivityStarter {
|
|||||||
+ " temporarily whitelisted. This will not be supported in future Q builds.");
|
+ " temporarily whitelisted. This will not be supported in future Q builds.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
// If we don't have callerApp at this point, no caller was provided to startActivity().
|
||||||
|
// That's the case for PendingIntent-based starts, since the creator's process might not be
|
||||||
|
// up and alive. If that's the case, we retrieve the WindowProcessController for the send()
|
||||||
|
// caller, so that we can make the decision based on its foreground/whitelisted state.
|
||||||
|
int callerAppUid = callingUid;
|
||||||
|
if (callerApp == null) {
|
||||||
|
callerApp = mService.getProcessController(realCallingPid, realCallingUid);
|
||||||
|
callerAppUid = realCallingUid;
|
||||||
|
}
|
||||||
|
// don't abort if the callerApp or other processes of that uid are whitelisted in any way
|
||||||
|
if (callerApp != null) {
|
||||||
|
// first check the original calling process
|
||||||
|
if (callerApp.areBackgroundActivityStartsAllowed()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// only if that one wasn't whitelisted, check the other ones
|
||||||
|
final ArraySet<WindowProcessController> uidProcesses =
|
||||||
|
mService.mProcessMap.getProcesses(callerAppUid);
|
||||||
|
if (uidProcesses != null) {
|
||||||
|
for (int i = uidProcesses.size() - 1; i >= 0; i--) {
|
||||||
|
final WindowProcessController proc = uidProcesses.valueAt(i);
|
||||||
|
if (proc != callerApp && proc.areBackgroundActivityStartsAllowed()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
// anything that has fallen through would currently be aborted
|
// anything that has fallen through would currently be aborted
|
||||||
Slog.w(TAG, "Background activity start [callingPackage: " + callingPackage
|
Slog.w(TAG, "Background activity start [callingPackage: " + callingPackage
|
||||||
+ "; callingUid: " + callingUid
|
+ "; callingUid: " + callingUid
|
||||||
@@ -1059,17 +1061,6 @@ class ActivityStarter {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isBoundByForegroundUid(WindowProcessController callerApp) {
|
|
||||||
final ArraySet<Integer> boundClientUids = callerApp.getBoundClientUids();
|
|
||||||
for (int i = boundClientUids.size() - 1; i >= 0; --i) {
|
|
||||||
final int uid = boundClientUids.valueAt(i);
|
|
||||||
if (mService.isUidForeground(uid)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: remove this toast after feature development is done
|
// TODO: remove this toast after feature development is done
|
||||||
void showBackgroundActivityBlockedToast(boolean abort, String callingPackage) {
|
void showBackgroundActivityBlockedToast(boolean abort, String callingPackage) {
|
||||||
final Resources res = mService.mContext.getResources();
|
final Resources res = mService.mContext.getResources();
|
||||||
|
|||||||
@@ -373,8 +373,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
|
|||||||
private final SparseArray<String> mPendingTempWhitelist = new SparseArray<>();
|
private final SparseArray<String> mPendingTempWhitelist = new SparseArray<>();
|
||||||
/** All processes currently running that might have a window organized by name. */
|
/** All processes currently running that might have a window organized by name. */
|
||||||
final ProcessMap<WindowProcessController> mProcessNames = new ProcessMap<>();
|
final ProcessMap<WindowProcessController> mProcessNames = new ProcessMap<>();
|
||||||
/** All processes we currently have running mapped by pid */
|
/** All processes we currently have running mapped by pid and uid */
|
||||||
final SparseArray<WindowProcessController> mPidMap = new SparseArray<>();
|
final WindowProcessControllerMap mProcessMap = new WindowProcessControllerMap();
|
||||||
/** This is the process holding what we currently consider to be the "home" activity. */
|
/** This is the process holding what we currently consider to be the "home" activity. */
|
||||||
WindowProcessController mHomeProcess;
|
WindowProcessController mHomeProcess;
|
||||||
/** The currently running heavy-weight process, if any. */
|
/** The currently running heavy-weight process, if any. */
|
||||||
@@ -913,7 +913,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
|
|||||||
return getGlobalConfiguration();
|
return getGlobalConfiguration();
|
||||||
}
|
}
|
||||||
synchronized (mGlobalLock) {
|
synchronized (mGlobalLock) {
|
||||||
final WindowProcessController app = mPidMap.get(pid);
|
final WindowProcessController app = mProcessMap.getProcess(pid);
|
||||||
return app != null ? app.getConfiguration() : getGlobalConfiguration();
|
return app != null ? app.getConfiguration() : getGlobalConfiguration();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4640,7 +4640,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
|
|||||||
enforceSystemHasVrFeature();
|
enforceSystemHasVrFeature();
|
||||||
synchronized (mGlobalLock) {
|
synchronized (mGlobalLock) {
|
||||||
final int pid = Binder.getCallingPid();
|
final int pid = Binder.getCallingPid();
|
||||||
final WindowProcessController wpc = mPidMap.get(pid);
|
final WindowProcessController wpc = mProcessMap.getProcess(pid);
|
||||||
mVrController.setVrThreadLocked(tid, pid, wpc);
|
mVrController.setVrThreadLocked(tid, pid, wpc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4659,7 +4659,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
|
|||||||
enforceSystemHasVrFeature();
|
enforceSystemHasVrFeature();
|
||||||
synchronized (mGlobalLock) {
|
synchronized (mGlobalLock) {
|
||||||
final int pid = Binder.getCallingPid();
|
final int pid = Binder.getCallingPid();
|
||||||
final WindowProcessController proc = mPidMap.get(pid);
|
final WindowProcessController proc = mProcessMap.getProcess(pid);
|
||||||
mVrController.setPersistentVrThreadLocked(tid, pid, proc);
|
mVrController.setPersistentVrThreadLocked(tid, pid, proc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5204,9 +5204,10 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
|
|||||||
mH.sendMessage(msg);
|
mH.sendMessage(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = mPidMap.size() - 1; i >= 0; i--) {
|
SparseArray<WindowProcessController> pidMap = mProcessMap.getPidMap();
|
||||||
final int pid = mPidMap.keyAt(i);
|
for (int i = pidMap.size() - 1; i >= 0; i--) {
|
||||||
final WindowProcessController app = mPidMap.get(pid);
|
final int pid = pidMap.keyAt(i);
|
||||||
|
final WindowProcessController app = pidMap.get(pid);
|
||||||
if (DEBUG_CONFIGURATION) {
|
if (DEBUG_CONFIGURATION) {
|
||||||
Slog.v(TAG_CONFIGURATION, "Update process config of "
|
Slog.v(TAG_CONFIGURATION, "Update process config of "
|
||||||
+ app.mName + " to new config " + configCopy);
|
+ app.mName + " to new config " + configCopy);
|
||||||
@@ -5859,7 +5860,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
WindowProcessController getProcessController(int pid, int uid) {
|
WindowProcessController getProcessController(int pid, int uid) {
|
||||||
final WindowProcessController proc = mPidMap.get(pid);
|
final WindowProcessController proc = mProcessMap.getProcess(pid);
|
||||||
if (proc == null) return null;
|
if (proc == null) return null;
|
||||||
if (UserHandle.isApp(uid) && proc.mUid == uid) {
|
if (UserHandle.isApp(uid) && proc.mUid == uid) {
|
||||||
return proc;
|
return proc;
|
||||||
@@ -6423,14 +6424,14 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
|
|||||||
@Override
|
@Override
|
||||||
public void onProcessMapped(int pid, WindowProcessController proc) {
|
public void onProcessMapped(int pid, WindowProcessController proc) {
|
||||||
synchronized (mGlobalLock) {
|
synchronized (mGlobalLock) {
|
||||||
mPidMap.put(pid, proc);
|
mProcessMap.put(pid, proc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onProcessUnMapped(int pid) {
|
public void onProcessUnMapped(int pid) {
|
||||||
synchronized (mGlobalLock) {
|
synchronized (mGlobalLock) {
|
||||||
mPidMap.remove(pid);
|
mProcessMap.remove(pid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6503,7 +6504,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final WindowProcessController process = mPidMap.get(pid);
|
final WindowProcessController process = mProcessMap.getProcess(pid);
|
||||||
if (process == null) {
|
if (process == null) {
|
||||||
if (DEBUG_CONFIGURATION) {
|
if (DEBUG_CONFIGURATION) {
|
||||||
Slog.w(TAG, "Trying to update display configuration for invalid "
|
Slog.w(TAG, "Trying to update display configuration for invalid "
|
||||||
@@ -6696,7 +6697,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
|
|||||||
// Only allow this from foreground processes, so that background
|
// Only allow this from foreground processes, so that background
|
||||||
// applications can't abuse it to prevent system UI from being shown.
|
// applications can't abuse it to prevent system UI from being shown.
|
||||||
if (uid >= FIRST_APPLICATION_UID) {
|
if (uid >= FIRST_APPLICATION_UID) {
|
||||||
final WindowProcessController proc = mPidMap.get(pid);
|
final WindowProcessController proc = mProcessMap.getProcess(pid);
|
||||||
if (!proc.isPerceptible()) {
|
if (!proc.isPerceptible()) {
|
||||||
Slog.w(TAG, "Ignoring closeSystemDialogs " + reason
|
Slog.w(TAG, "Ignoring closeSystemDialogs " + reason
|
||||||
+ " from background process " + proc);
|
+ " from background process " + proc);
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ import android.os.Message;
|
|||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.util.AtomicFile;
|
import android.util.AtomicFile;
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
|
import android.util.SparseArray;
|
||||||
import android.util.Xml;
|
import android.util.Xml;
|
||||||
|
|
||||||
public final class CompatModePackages {
|
public final class CompatModePackages {
|
||||||
@@ -324,8 +325,9 @@ public final class CompatModePackages {
|
|||||||
ActivityRecord starting = stack.restartPackage(packageName);
|
ActivityRecord starting = stack.restartPackage(packageName);
|
||||||
|
|
||||||
// Tell all processes that loaded this package about the change.
|
// Tell all processes that loaded this package about the change.
|
||||||
for (int i = mService.mPidMap.size() - 1; i >= 0; i--) {
|
SparseArray<WindowProcessController> pidMap = mService.mProcessMap.getPidMap();
|
||||||
final WindowProcessController app = mService.mPidMap.valueAt(i);
|
for (int i = pidMap.size() - 1; i >= 0; i--) {
|
||||||
|
final WindowProcessController app = pidMap.valueAt(i);
|
||||||
if (!app.mPkgList.contains(packageName)) {
|
if (!app.mPkgList.contains(packageName)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -372,18 +372,39 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
|
|||||||
mAllowBackgroundActivityStarts = allowBackgroundActivityStarts;
|
mAllowBackgroundActivityStarts = allowBackgroundActivityStarts;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean areBackgroundActivityStartsAllowed() {
|
boolean areBackgroundActivityStartsAllowed() {
|
||||||
return mAllowBackgroundActivityStarts;
|
// allow if the whitelisting flag was explicitly set
|
||||||
|
if (mAllowBackgroundActivityStarts) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// allow if the proc is instrumenting with background activity starts privs
|
||||||
|
if (mInstrumentingWithBackgroundActivityStartPrivileges) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// allow if the caller has an activity in any foreground task
|
||||||
|
if (hasActivityInVisibleTask()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// allow if the caller is bound by a UID that's currently foreground
|
||||||
|
if (isBoundByForegroundUid()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isBoundByForegroundUid() {
|
||||||
|
for (int i = mBoundClientUids.size() - 1; i >= 0; --i) {
|
||||||
|
if (mAtm.isUidForeground(mBoundClientUids.valueAt(i))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setBoundClientUids(ArraySet<Integer> boundClientUids) {
|
public void setBoundClientUids(ArraySet<Integer> boundClientUids) {
|
||||||
mBoundClientUids = boundClientUids;
|
mBoundClientUids = boundClientUids;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArraySet<Integer> getBoundClientUids() {
|
|
||||||
return mBoundClientUids;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setInstrumenting(boolean instrumenting,
|
public void setInstrumenting(boolean instrumenting,
|
||||||
boolean hasBackgroundActivityStartPrivileges) {
|
boolean hasBackgroundActivityStartPrivileges) {
|
||||||
mInstrumenting = instrumenting;
|
mInstrumenting = instrumenting;
|
||||||
@@ -394,14 +415,6 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
|
|||||||
return mInstrumenting;
|
return mInstrumenting;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return true if the instrumentation was started by a holder of
|
|
||||||
* START_ACTIVITIES_FROM_BACKGROUND permission
|
|
||||||
*/
|
|
||||||
boolean isInstrumentingWithBackgroundActivityStartPrivileges() {
|
|
||||||
return mInstrumentingWithBackgroundActivityStartPrivileges;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPerceptible(boolean perceptible) {
|
public void setPerceptible(boolean perceptible) {
|
||||||
mPerceptible = perceptible;
|
mPerceptible = perceptible;
|
||||||
}
|
}
|
||||||
@@ -487,7 +500,7 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean hasActivityInVisibleTask() {
|
private boolean hasActivityInVisibleTask() {
|
||||||
for (int i = mActivities.size() - 1; i >= 0; --i) {
|
for (int i = mActivities.size() - 1; i >= 0; --i) {
|
||||||
TaskRecord task = mActivities.get(i).getTaskRecord();
|
TaskRecord task = mActivities.get(i).getTaskRecord();
|
||||||
if (task == null) {
|
if (task == null) {
|
||||||
|
|||||||
@@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2019 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.server.wm;
|
||||||
|
|
||||||
|
import android.util.ArraySet;
|
||||||
|
import android.util.SparseArray;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
final class WindowProcessControllerMap {
|
||||||
|
|
||||||
|
/** All processes we currently have running mapped by pid */
|
||||||
|
private final SparseArray<WindowProcessController> mPidMap = new SparseArray<>();
|
||||||
|
/** All processes we currently have running mapped by uid */
|
||||||
|
private final Map<Integer, ArraySet<WindowProcessController>> mUidMap = new HashMap<>();
|
||||||
|
|
||||||
|
/** Retrieves a currently running process for pid. */
|
||||||
|
WindowProcessController getProcess(int pid) {
|
||||||
|
return mPidMap.get(pid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Retrieves all currently running processes for uid. */
|
||||||
|
ArraySet<WindowProcessController> getProcesses(int uid) {
|
||||||
|
return mUidMap.get(uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
SparseArray<WindowProcessController> getPidMap() {
|
||||||
|
return mPidMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
void put(int pid, WindowProcessController proc) {
|
||||||
|
// if there is a process for this pid already in mPidMap it'll get replaced automagically,
|
||||||
|
// but we actually need to remove it from mUidMap too before adding the new one
|
||||||
|
final WindowProcessController prevProc = mPidMap.get(pid);
|
||||||
|
if (prevProc != null) {
|
||||||
|
removeProcessFromUidMap(prevProc);
|
||||||
|
}
|
||||||
|
// put process into mPidMap
|
||||||
|
mPidMap.put(pid, proc);
|
||||||
|
// put process into mUidMap
|
||||||
|
final int uid = proc.mUid;
|
||||||
|
ArraySet<WindowProcessController> procSet = mUidMap.getOrDefault(uid,
|
||||||
|
new ArraySet<WindowProcessController>());
|
||||||
|
procSet.add(proc);
|
||||||
|
mUidMap.put(uid, procSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
void remove(int pid) {
|
||||||
|
final WindowProcessController proc = mPidMap.get(pid);
|
||||||
|
if (proc != null) {
|
||||||
|
// remove process from mPidMap
|
||||||
|
mPidMap.remove(pid);
|
||||||
|
// remove process from mUidMap
|
||||||
|
removeProcessFromUidMap(proc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void removeProcessFromUidMap(WindowProcessController proc) {
|
||||||
|
if (proc == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final int uid = proc.mUid;
|
||||||
|
ArraySet<WindowProcessController> procSet = mUidMap.get(uid);
|
||||||
|
if (procSet != null) {
|
||||||
|
procSet.remove(proc);
|
||||||
|
if (procSet.isEmpty()) {
|
||||||
|
mUidMap.remove(uid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,130 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2019 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.server.wm;
|
||||||
|
|
||||||
|
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
import android.os.UserHandle;
|
||||||
|
import android.platform.test.annotations.Presubmit;
|
||||||
|
import android.util.ArraySet;
|
||||||
|
|
||||||
|
import androidx.test.filters.SmallTest;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for the {@link WindowProcessControllerMap} class.
|
||||||
|
*
|
||||||
|
* Build/Install/Run:
|
||||||
|
* atest WmTests:WindowProcessControllerMapTests
|
||||||
|
*/
|
||||||
|
@SmallTest
|
||||||
|
@Presubmit
|
||||||
|
public class WindowProcessControllerMapTests extends ActivityTestsBase {
|
||||||
|
|
||||||
|
private static final int FAKE_UID1 = 666;
|
||||||
|
private static final int FAKE_UID2 = 667;
|
||||||
|
private static final int FAKE_PID1 = 668;
|
||||||
|
private static final int FAKE_PID2 = 669;
|
||||||
|
private static final int FAKE_PID3 = 670;
|
||||||
|
private static final int FAKE_PID4 = 671;
|
||||||
|
|
||||||
|
private WindowProcessControllerMap mProcessMap;
|
||||||
|
private WindowProcessController pid1uid1;
|
||||||
|
private WindowProcessController pid1uid2;
|
||||||
|
private WindowProcessController pid2uid1;
|
||||||
|
private WindowProcessController pid3uid1;
|
||||||
|
private WindowProcessController pid4uid2;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
mProcessMap = new WindowProcessControllerMap();
|
||||||
|
pid1uid1 = new WindowProcessController(
|
||||||
|
mService, mService.mContext.getApplicationInfo(), "fakepid1fakeuid1", FAKE_UID1,
|
||||||
|
UserHandle.getUserId(12345), mock(Object.class), mock(WindowProcessListener.class));
|
||||||
|
pid1uid1.setPid(FAKE_PID1);
|
||||||
|
pid1uid2 = new WindowProcessController(
|
||||||
|
mService, mService.mContext.getApplicationInfo(), "fakepid1fakeuid2", FAKE_UID2,
|
||||||
|
UserHandle.getUserId(12345), mock(Object.class), mock(WindowProcessListener.class));
|
||||||
|
pid1uid2.setPid(FAKE_PID1);
|
||||||
|
pid2uid1 = new WindowProcessController(
|
||||||
|
mService, mService.mContext.getApplicationInfo(), "fakepid2fakeuid1", FAKE_UID1,
|
||||||
|
UserHandle.getUserId(12345), mock(Object.class), mock(WindowProcessListener.class));
|
||||||
|
pid2uid1.setPid(FAKE_PID2);
|
||||||
|
pid3uid1 = new WindowProcessController(
|
||||||
|
mService, mService.mContext.getApplicationInfo(), "fakepid3fakeuid1", FAKE_UID1,
|
||||||
|
UserHandle.getUserId(12345), mock(Object.class), mock(WindowProcessListener.class));
|
||||||
|
pid3uid1.setPid(FAKE_PID3);
|
||||||
|
pid4uid2 = new WindowProcessController(
|
||||||
|
mService, mService.mContext.getApplicationInfo(), "fakepid4fakeuid2", FAKE_UID2,
|
||||||
|
UserHandle.getUserId(12345), mock(Object.class), mock(WindowProcessListener.class));
|
||||||
|
pid4uid2.setPid(FAKE_PID4);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAdditionsAndRemovals() {
|
||||||
|
// test various additions and removals
|
||||||
|
mProcessMap.put(FAKE_PID1, pid1uid1);
|
||||||
|
mProcessMap.put(FAKE_PID2, pid2uid1);
|
||||||
|
assertEquals(pid1uid1, mProcessMap.getProcess(FAKE_PID1));
|
||||||
|
assertEquals(pid2uid1, mProcessMap.getProcess(FAKE_PID2));
|
||||||
|
ArraySet<WindowProcessController> uid1processes = mProcessMap.getProcesses(FAKE_UID1);
|
||||||
|
assertTrue(uid1processes.contains(pid1uid1));
|
||||||
|
assertTrue(uid1processes.contains(pid2uid1));
|
||||||
|
assertEquals(uid1processes.size(), 2);
|
||||||
|
|
||||||
|
mProcessMap.remove(FAKE_PID2);
|
||||||
|
mProcessMap.put(FAKE_PID3, pid3uid1);
|
||||||
|
uid1processes = mProcessMap.getProcesses(FAKE_UID1);
|
||||||
|
assertTrue(uid1processes.contains(pid1uid1));
|
||||||
|
assertFalse(uid1processes.contains(pid2uid1));
|
||||||
|
assertTrue(uid1processes.contains(pid3uid1));
|
||||||
|
assertEquals(uid1processes.size(), 2);
|
||||||
|
|
||||||
|
mProcessMap.put(FAKE_PID4, pid4uid2);
|
||||||
|
ArraySet<WindowProcessController> uid2processes = mProcessMap.getProcesses(FAKE_UID2);
|
||||||
|
assertTrue(uid2processes.contains(pid4uid2));
|
||||||
|
assertEquals(uid2processes.size(), 1);
|
||||||
|
|
||||||
|
mProcessMap.remove(FAKE_PID1);
|
||||||
|
mProcessMap.remove(FAKE_PID3);
|
||||||
|
assertNull(mProcessMap.getProcesses(FAKE_UID1));
|
||||||
|
assertEquals(mProcessMap.getProcess(FAKE_PID4), pid4uid2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testReplacement() {
|
||||||
|
// test that replacing a process is handled correctly
|
||||||
|
mProcessMap.put(FAKE_PID1, pid1uid1);
|
||||||
|
ArraySet<WindowProcessController> uid1processes = mProcessMap.getProcesses(FAKE_UID1);
|
||||||
|
assertTrue(uid1processes.contains(pid1uid1));
|
||||||
|
assertEquals(uid1processes.size(), 1);
|
||||||
|
|
||||||
|
mProcessMap.put(FAKE_PID1, pid1uid2);
|
||||||
|
assertNull(mProcessMap.getProcesses(FAKE_UID1));
|
||||||
|
ArraySet<WindowProcessController> uid2processes = mProcessMap.getProcesses(FAKE_UID2);
|
||||||
|
assertTrue(uid2processes.contains(pid1uid2));
|
||||||
|
assertEquals(uid2processes.size(), 1);
|
||||||
|
assertEquals(mProcessMap.getProcess(FAKE_PID1), pid1uid2);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user