summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/app/HomeVisibilityListener.java5
-rw-r--r--core/java/android/app/IProcessObserver.aidl11
-rw-r--r--libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/tv/TvPipTestBase.kt8
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerShellCommand.java5
-rw-r--r--services/core/java/com/android/server/am/AppFGSTracker.java5
-rw-r--r--services/core/java/com/android/server/am/ProcessList.java17
-rw-r--r--services/core/java/com/android/server/app/GameServiceProviderInstanceImpl.java5
-rw-r--r--services/core/java/com/android/server/devicestate/DeviceStateManagerService.java4
-rw-r--r--services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java5
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/am/ProcessObserverTest.java275
10 files changed, 340 insertions, 0 deletions
diff --git a/core/java/android/app/HomeVisibilityListener.java b/core/java/android/app/HomeVisibilityListener.java
index 1f5f2e4c8237..5dd7ab0f99fa 100644
--- a/core/java/android/app/HomeVisibilityListener.java
+++ b/core/java/android/app/HomeVisibilityListener.java
@@ -69,6 +69,11 @@ public abstract class HomeVisibilityListener {
public HomeVisibilityListener() {
mObserver = new android.app.IProcessObserver.Stub() {
@Override
+ public void onProcessStarted(int pid, int processUid, int packageUid,
+ String packageName, String processName) {
+ }
+
+ @Override
public void onForegroundActivitiesChanged(int pid, int uid, boolean fg) {
refreshHomeVisibility();
}
diff --git a/core/java/android/app/IProcessObserver.aidl b/core/java/android/app/IProcessObserver.aidl
index 7be3620f317b..5c5e72cf9d6f 100644
--- a/core/java/android/app/IProcessObserver.aidl
+++ b/core/java/android/app/IProcessObserver.aidl
@@ -18,6 +18,17 @@ package android.app;
/** {@hide} */
oneway interface IProcessObserver {
+ /**
+ * Invoked when an app process starts up.
+ *
+ * @param pid The pid of the process.
+ * @param processUid The UID associated with the process.
+ * @param packageUid The UID associated with the package.
+ * @param packageName The name of the package.
+ * @param processName The name of the process.
+ */
+ void onProcessStarted(int pid, int processUid, int packageUid,
+ @utf8InCpp String packageName, @utf8InCpp String processName);
void onForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities);
void onForegroundServicesChanged(int pid, int uid, int serviceTypes);
void onProcessDied(int pid, int uid);
diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/tv/TvPipTestBase.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/tv/TvPipTestBase.kt
index 47bff8de377e..0d1853534927 100644
--- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/tv/TvPipTestBase.kt
+++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/tv/TvPipTestBase.kt
@@ -78,6 +78,14 @@ abstract class TvPipTestBase : PipTestBase(rotationToString(ROTATION_0), ROTATIO
uiAutomation.dropShellPermissionIdentity()
}
+ override fun onProcessStarted(
+ pid: Int,
+ processUid: Int,
+ packageUid: Int,
+ packageName: String,
+ processName: String
+ ) {}
+
override fun onForegroundActivitiesChanged(pid: Int, uid: Int, foreground: Boolean) {}
override fun onForegroundServicesChanged(pid: Int, uid: Int, serviceTypes: Int) {}
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 57c52c2cf408..45f657d713ad 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -3754,6 +3754,11 @@ final class ActivityManagerShellCommand extends ShellCommand {
}
@Override
+ public void onProcessStarted(int pid, int processUid, int packageUid, String packageName,
+ String processName) {
+ }
+
+ @Override
public void onForegroundServicesChanged(int pid, int uid, int serviceTypes) {
}
diff --git a/services/core/java/com/android/server/am/AppFGSTracker.java b/services/core/java/com/android/server/am/AppFGSTracker.java
index 1f98aba5bbd7..fb89b8e4f3b4 100644
--- a/services/core/java/com/android/server/am/AppFGSTracker.java
+++ b/services/core/java/com/android/server/am/AppFGSTracker.java
@@ -102,6 +102,11 @@ final class AppFGSTracker extends BaseAppStateDurationsTracker<AppFGSPolicy, Pac
}
@Override
+ public void onProcessStarted(int pid, int processUid, int packageUid, String packageName,
+ String processName) {
+ }
+
+ @Override
public void onProcessDied(int pid, int uid) {
}
};
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index fa5dbd2543d3..f5c34a5da1c1 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -2852,6 +2852,7 @@ public final class ProcessList {
? PROC_START_TIMEOUT_WITH_WRAPPER : PROC_START_TIMEOUT);
}
}
+ dispatchProcessStarted(app, pid);
checkSlow(app.getStartTime(), "startProcess: done updating pids map");
return true;
}
@@ -4977,6 +4978,22 @@ public final class ProcessList {
}
}
+ void dispatchProcessStarted(ProcessRecord app, int pid) {
+ int i = mProcessObservers.beginBroadcast();
+ while (i > 0) {
+ i--;
+ final IProcessObserver observer = mProcessObservers.getBroadcastItem(i);
+ if (observer != null) {
+ try {
+ observer.onProcessStarted(pid, app.uid, app.info.uid,
+ app.info.packageName, app.processName);
+ } catch (RemoteException e) {
+ }
+ }
+ }
+ mProcessObservers.finishBroadcast();
+ }
+
void dispatchProcessDied(int pid, int uid) {
int i = mProcessObservers.beginBroadcast();
while (i > 0) {
diff --git a/services/core/java/com/android/server/app/GameServiceProviderInstanceImpl.java b/services/core/java/com/android/server/app/GameServiceProviderInstanceImpl.java
index 684d6a0fc596..cdd147a0ec37 100644
--- a/services/core/java/com/android/server/app/GameServiceProviderInstanceImpl.java
+++ b/services/core/java/com/android/server/app/GameServiceProviderInstanceImpl.java
@@ -177,6 +177,11 @@ final class GameServiceProviderInstanceImpl implements GameServiceProviderInstan
}
@Override
+ public void onProcessStarted(int pid, int processUid, int packageUid, String packageName,
+ String processName) {
+ }
+
+ @Override
public void onForegroundServicesChanged(int pid, int uid, int serviceTypes) {
}
};
diff --git a/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java b/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
index 6ec6a123a4e7..77cb08bc02bd 100644
--- a/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
+++ b/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
@@ -204,6 +204,10 @@ public final class DeviceStateManagerService extends SystemService {
}
@Override
+ public void onProcessStarted(int pid, int processUid, int packageUid, String packageName,
+ String processName) {}
+
+ @Override
public void onProcessDied(int pid, int uid) {}
@Override
diff --git a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
index 550aed51c8e2..978f46808e3b 100644
--- a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
+++ b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
@@ -214,6 +214,11 @@ public final class MediaProjectionManagerService extends SystemService
}
@Override
+ public void onProcessStarted(int pid, int processUid, int packageUid,
+ String packageName, String processName) {
+ }
+
+ @Override
public void onForegroundServicesChanged(int pid, int uid, int serviceTypes) {
MediaProjectionManagerService.this.handleForegroundServicesChanged(pid, uid,
serviceTypes);
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/ProcessObserverTest.java b/services/tests/mockingservicestests/src/com/android/server/am/ProcessObserverTest.java
new file mode 100644
index 000000000000..fcf761fb6607
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/am/ProcessObserverTest.java
@@ -0,0 +1,275 @@
+/*
+ * Copyright (C) 2022 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.am;
+
+import static android.os.Process.myPid;
+import static android.os.Process.myUid;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import android.app.ActivityManagerInternal;
+import android.app.IApplicationThread;
+import android.app.IProcessObserver;
+import android.app.usage.UsageStatsManagerInternal;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManagerInternal;
+import android.os.Binder;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.IBinder;
+import android.util.Log;
+
+import androidx.test.filters.MediumTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.server.DropBoxManagerInternal;
+import com.android.server.LocalServices;
+import com.android.server.am.ActivityManagerService.Injector;
+import com.android.server.appop.AppOpsService;
+import com.android.server.wm.ActivityTaskManagerInternal;
+import com.android.server.wm.ActivityTaskManagerService;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.io.File;
+import java.util.Arrays;
+
+
+/**
+ * Tests to verify that process events are dispatched to process observers.
+ */
+@MediumTest
+@SuppressWarnings("GuardedBy")
+public class ProcessObserverTest {
+ private static final String TAG = "ProcessObserverTest";
+
+ private static final String PACKAGE = "com.foo";
+
+ @Rule
+ public final ApplicationExitInfoTest.ServiceThreadRule
+ mServiceThreadRule = new ApplicationExitInfoTest.ServiceThreadRule();
+
+ private Context mContext;
+ private HandlerThread mHandlerThread;
+
+ @Mock
+ private AppOpsService mAppOpsService;
+ @Mock
+ private DropBoxManagerInternal mDropBoxManagerInt;
+ @Mock
+ private PackageManagerInternal mPackageManagerInt;
+ @Mock
+ private UsageStatsManagerInternal mUsageStatsManagerInt;
+ @Mock
+ private ActivityManagerInternal mActivityManagerInt;
+ @Mock
+ private ActivityTaskManagerInternal mActivityTaskManagerInt;
+ @Mock
+ private BatteryStatsService mBatteryStatsService;
+
+ private ActivityManagerService mRealAms;
+ private ActivityManagerService mAms;
+
+ private ProcessList mRealProcessList = new ProcessList();
+ private ProcessList mProcessList;
+
+ final IProcessObserver mProcessObserver = mock(IProcessObserver.Stub.class);
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+
+ mContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+
+ mHandlerThread = new HandlerThread(TAG);
+ mHandlerThread.start();
+
+ LocalServices.removeServiceForTest(DropBoxManagerInternal.class);
+ LocalServices.addService(DropBoxManagerInternal.class, mDropBoxManagerInt);
+
+ LocalServices.removeServiceForTest(PackageManagerInternal.class);
+ LocalServices.addService(PackageManagerInternal.class, mPackageManagerInt);
+
+ LocalServices.removeServiceForTest(ActivityManagerInternal.class);
+ LocalServices.addService(ActivityManagerInternal.class, mActivityManagerInt);
+
+ LocalServices.removeServiceForTest(ActivityTaskManagerInternal.class);
+ LocalServices.addService(ActivityTaskManagerInternal.class, mActivityTaskManagerInt);
+
+ doReturn(new ComponentName("", "")).when(mPackageManagerInt).getSystemUiServiceComponent();
+ doReturn(true).when(mActivityTaskManagerInt).attachApplication(any());
+ doNothing().when(mActivityTaskManagerInt).onProcessMapped(anyInt(), any());
+
+ mRealAms = new ActivityManagerService(
+ new TestInjector(mContext), mServiceThreadRule.getThread());
+ mRealAms.mConstants.loadDeviceConfigConstants();
+ mRealAms.mActivityTaskManager = new ActivityTaskManagerService(mContext);
+ mRealAms.mActivityTaskManager.initialize(null, null, mContext.getMainLooper());
+ mRealAms.mAtmInternal = mActivityTaskManagerInt;
+ mRealAms.mPackageManagerInt = mPackageManagerInt;
+ mRealAms.mUsageStatsService = mUsageStatsManagerInt;
+ mRealAms.mProcessesReady = true;
+ mAms = spy(mRealAms);
+ mRealProcessList.mService = mAms;
+ mProcessList = spy(mRealProcessList);
+
+ doReturn(mProcessObserver).when(mProcessObserver).asBinder();
+ mProcessList.registerProcessObserver(mProcessObserver);
+
+ doAnswer((invocation) -> {
+ Log.v(TAG, "Intercepting isProcStartValidLocked() for "
+ + Arrays.toString(invocation.getArguments()));
+ return null;
+ }).when(mProcessList).isProcStartValidLocked(any(), anyLong());
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ mHandlerThread.quit();
+ }
+
+ private class TestInjector extends Injector {
+ TestInjector(Context context) {
+ super(context);
+ }
+
+ @Override
+ public AppOpsService getAppOpsService(File recentAccessesFile, File storageFile,
+ Handler handler) {
+ return mAppOpsService;
+ }
+
+ @Override
+ public Handler getUiHandler(ActivityManagerService service) {
+ return mHandlerThread.getThreadHandler();
+ }
+
+ @Override
+ public ProcessList getProcessList(ActivityManagerService service) {
+ return mRealProcessList;
+ }
+
+ @Override
+ public BatteryStatsService getBatteryStatsService() {
+ return mBatteryStatsService;
+ }
+ }
+
+ private ProcessRecord makeActiveProcessRecord(String packageName)
+ throws Exception {
+ final ApplicationInfo ai = makeApplicationInfo(packageName);
+ return makeActiveProcessRecord(ai);
+ }
+
+ private ProcessRecord makeActiveProcessRecord(ApplicationInfo ai)
+ throws Exception {
+ final IApplicationThread thread = mock(IApplicationThread.class);
+ final IBinder threadBinder = new Binder();
+ doReturn(threadBinder).when(thread).asBinder();
+ doAnswer((invocation) -> {
+ Log.v(TAG, "Intercepting bindApplication() for "
+ + Arrays.toString(invocation.getArguments()));
+ if (mRealAms.mConstants.mEnableWaitForFinishAttachApplication) {
+ mRealAms.finishAttachApplication(0);
+ }
+ return null;
+ }).when(thread).bindApplication(
+ any(), any(),
+ any(), any(), anyBoolean(),
+ any(), any(),
+ any(), any(),
+ any(),
+ any(), anyInt(),
+ anyBoolean(), anyBoolean(),
+ anyBoolean(), anyBoolean(), any(),
+ any(), any(), any(),
+ any(), any(),
+ any(), any(),
+ any(),
+ anyLong(), anyLong());
+ final ProcessRecord r = spy(new ProcessRecord(mAms, ai, ai.processName, ai.uid));
+ r.setPid(myPid());
+ r.setStartUid(myUid());
+ r.setHostingRecord(new HostingRecord(HostingRecord.HOSTING_TYPE_BROADCAST));
+ r.makeActive(thread, mAms.mProcessStats);
+ doNothing().when(r).killLocked(any(), any(), anyInt(), anyInt(), anyBoolean(),
+ anyBoolean());
+ return r;
+ }
+
+ static ApplicationInfo makeApplicationInfo(String packageName) {
+ final ApplicationInfo ai = new ApplicationInfo();
+ ai.packageName = packageName;
+ ai.processName = packageName;
+ ai.uid = myUid();
+ return ai;
+ }
+
+ /**
+ * Verify that a process start event is dispatched to process observers.
+ */
+ @Test
+ public void testNormal() throws Exception {
+ ProcessRecord app = startProcess();
+ verify(mProcessObserver).onProcessStarted(
+ app.getPid(), app.uid, app.info.uid, PACKAGE, PACKAGE);
+ }
+
+ private ProcessRecord startProcess() throws Exception {
+ final ProcessRecord app = makeActiveProcessRecord(PACKAGE);
+ final ApplicationInfo appInfo = makeApplicationInfo(PACKAGE);
+ mProcessList.handleProcessStartedLocked(app, app.getPid(), /* usingWrapper */ false,
+ /* expectedStartSeq */ 0, /* procAttached */ false);
+ app.getThread().bindApplication(PACKAGE, appInfo,
+ null, null, false,
+ null,
+ null,
+ null, null,
+ null,
+ null, 0,
+ false, false,
+ true, false,
+ null,
+ null, null,
+ null,
+ null, null, null,
+ null, null,
+ 0, 0);
+ return app;
+ }
+
+ // TODO: [b/302724778] Remove manual JNI load
+ static {
+ System.loadLibrary("mockingservicestestjni");
+ }
+}