Loading services/core/java/com/android/server/am/BroadcastProcessQueue.java +27 −14 Original line number Diff line number Diff line Loading @@ -265,13 +265,6 @@ class BroadcastProcessQueue { @Nullable public BroadcastRecord enqueueOrReplaceBroadcast(@NonNull BroadcastRecord record, int recordIndex, @NonNull BroadcastConsumer deferredStatesApplyConsumer) { // When updateDeferredStates() has already applied a deferred state to // all pending items, apply to this new broadcast too if (mLastDeferredStates && record.deferUntilActive && (record.getDeliveryState(recordIndex) == BroadcastRecord.DELIVERY_PENDING)) { deferredStatesApplyConsumer.accept(record, recordIndex); } // Ignore FLAG_RECEIVER_REPLACE_PENDING if the sender specified the policy using the // BroadcastOptions delivery group APIs. if (record.isReplacePending() Loading @@ -294,6 +287,13 @@ class BroadcastProcessQueue { // with implicit responsiveness expectations. getQueueForBroadcast(record).addLast(newBroadcastArgs); onBroadcastEnqueued(record, recordIndex); // When updateDeferredStates() has already applied a deferred state to // all pending items, apply to this new broadcast too if (mLastDeferredStates && shouldBeDeferred() && (record.getDeliveryState(recordIndex) == BroadcastRecord.DELIVERY_PENDING)) { deferredStatesApplyConsumer.accept(record, recordIndex); } return null; } Loading Loading @@ -1235,30 +1235,43 @@ class BroadcastProcessQueue { } /** * Update {@link BroadcastRecord.DELIVERY_DEFERRED} states of all our * Update {@link BroadcastRecord#DELIVERY_DEFERRED} states of all our * pending broadcasts, when needed. */ void updateDeferredStates(@NonNull BroadcastConsumer applyConsumer, @NonNull BroadcastConsumer clearConsumer) { // When all we have pending is deferred broadcasts, and we're cached, // then we want everything to be marked deferred final boolean wantDeferredStates = (mCountDeferred > 0) && (mCountDeferred == mCountEnqueued) && mProcessFreezable; final boolean wantDeferredStates = shouldBeDeferred(); if (mLastDeferredStates != wantDeferredStates) { mLastDeferredStates = wantDeferredStates; if (wantDeferredStates) { forEachMatchingBroadcast((r, i) -> { return r.deferUntilActive && (r.getDeliveryState(i) == BroadcastRecord.DELIVERY_PENDING); return (r.getDeliveryState(i) == BroadcastRecord.DELIVERY_PENDING); }, applyConsumer, false); } else { forEachMatchingBroadcast((r, i) -> { return r.deferUntilActive && (r.getDeliveryState(i) == BroadcastRecord.DELIVERY_DEFERRED); return (r.getDeliveryState(i) == BroadcastRecord.DELIVERY_DEFERRED); }, clearConsumer, false); } } } void clearDeferredStates(@NonNull BroadcastConsumer clearConsumer) { if (mLastDeferredStates) { mLastDeferredStates = false; forEachMatchingBroadcast((r, i) -> { return (r.getDeliveryState(i) == BroadcastRecord.DELIVERY_DEFERRED); }, clearConsumer, false); } } @VisibleForTesting boolean shouldBeDeferred() { if (mRunnableAtInvalidated) updateRunnableAt(); return mRunnableAtReason == REASON_CACHED || mRunnableAtReason == REASON_CACHED_INFINITE_DEFER; } /** Loading services/core/java/com/android/server/am/BroadcastQueueModernImpl.java +8 −2 Original line number Diff line number Diff line Loading @@ -479,6 +479,10 @@ class BroadcastQueueModernImpl extends BroadcastQueue { break; } // Clear the deferred state of broadcasts in this queue as we are just about to // deliver broadcasts to this process. queue.clearDeferredStates(mBroadcastConsumerDeferClear); // We might not have heard about a newly running process yet, so // consider refreshing if we think we're cold updateWarmProcess(queue); Loading Loading @@ -1567,12 +1571,14 @@ class BroadcastQueueModernImpl extends BroadcastQueue { r.resultExtras = null; }; private final BroadcastConsumer mBroadcastConsumerDeferApply = (r, i) -> { @VisibleForTesting final BroadcastConsumer mBroadcastConsumerDeferApply = (r, i) -> { setDeliveryState(null, null, r, i, r.receivers.get(i), BroadcastRecord.DELIVERY_DEFERRED, "mBroadcastConsumerDeferApply"); }; private final BroadcastConsumer mBroadcastConsumerDeferClear = (r, i) -> { @VisibleForTesting final BroadcastConsumer mBroadcastConsumerDeferClear = (r, i) -> { setDeliveryState(null, null, r, i, r.receivers.get(i), BroadcastRecord.DELIVERY_PENDING, "mBroadcastConsumerDeferClear"); }; Loading services/tests/mockingservicestests/src/com/android/server/am/BaseBroadcastQueueTest.java 0 → 100644 +259 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 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 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.ArgumentMatchers.eq; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; import android.annotation.NonNull; import android.app.usage.UsageStatsManagerInternal; import android.content.ComponentName; import android.content.Context; import android.content.IntentFilter; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManagerInternal; import android.content.pm.ResolveInfo; import android.os.Handler; import android.os.HandlerThread; import android.os.TestLooperManager; import android.os.UserHandle; import android.provider.Settings; import android.util.SparseArray; import androidx.test.platform.app.InstrumentationRegistry; import com.android.server.AlarmManagerInternal; import com.android.server.DropBoxManagerInternal; import com.android.server.LocalServices; import com.android.server.appop.AppOpsService; import com.android.server.wm.ActivityTaskManagerService; import org.junit.Rule; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.io.File; import java.util.Objects; import java.util.concurrent.atomic.AtomicInteger; public abstract class BaseBroadcastQueueTest { static final int USER_GUEST = 11; static final String PACKAGE_ANDROID = "android"; static final String PACKAGE_PHONE = "com.android.phone"; static final String PACKAGE_RED = "com.example.red"; static final String PACKAGE_GREEN = "com.example.green"; static final String PACKAGE_BLUE = "com.example.blue"; static final String PACKAGE_YELLOW = "com.example.yellow"; static final String PACKAGE_ORANGE = "com.example.orange"; static final String PROCESS_SYSTEM = "system"; static final String CLASS_RED = "com.example.red.Red"; static final String CLASS_GREEN = "com.example.green.Green"; static final String CLASS_BLUE = "com.example.blue.Blue"; static final String CLASS_YELLOW = "com.example.yellow.Yellow"; static final String CLASS_ORANGE = "com.example.orange.Orange"; static final BroadcastProcessQueue.BroadcastPredicate BROADCAST_PREDICATE_ANY = (r, i) -> true; @Rule public final ApplicationExitInfoTest.ServiceThreadRule mServiceThreadRule = new ApplicationExitInfoTest.ServiceThreadRule(); @Mock AppOpsService mAppOpsService; @Mock PackageManagerInternal mPackageManagerInt; @Mock UsageStatsManagerInternal mUsageStatsManagerInt; @Mock DropBoxManagerInternal mDropBoxManagerInt; @Mock AlarmManagerInternal mAlarmManagerInt; @Mock ProcessList mProcessList; Context mContext; ActivityManagerService mAms; BroadcastConstants mConstants; BroadcastSkipPolicy mSkipPolicy; HandlerThread mHandlerThread; TestLooperManager mLooper; AtomicInteger mNextPid; /** * Map from PID to registered registered runtime receivers. */ SparseArray<ReceiverList> mRegisteredReceivers = new SparseArray<>(); public void setUp() throws Exception { MockitoAnnotations.initMocks(this); mContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); mHandlerThread = new HandlerThread(getTag()); mHandlerThread.start(); // Pause all event processing until a test chooses to resume mLooper = Objects.requireNonNull(InstrumentationRegistry.getInstrumentation() .acquireLooperManager(mHandlerThread.getLooper())); mNextPid = new AtomicInteger(100); LocalServices.removeServiceForTest(DropBoxManagerInternal.class); LocalServices.addService(DropBoxManagerInternal.class, mDropBoxManagerInt); LocalServices.removeServiceForTest(PackageManagerInternal.class); LocalServices.addService(PackageManagerInternal.class, mPackageManagerInt); LocalServices.removeServiceForTest(AlarmManagerInternal.class); LocalServices.addService(AlarmManagerInternal.class, mAlarmManagerInt); doReturn(new ComponentName("", "")).when(mPackageManagerInt).getSystemUiServiceComponent(); doNothing().when(mPackageManagerInt).notifyComponentUsed(any(), anyInt(), any(), any()); doAnswer((invocation) -> { return getUidForPackage(invocation.getArgument(0)); }).when(mPackageManagerInt).getPackageUid(any(), anyLong(), eq(UserHandle.USER_SYSTEM)); final ActivityManagerService realAms = new ActivityManagerService( new TestInjector(mContext), mServiceThreadRule.getThread()); realAms.mActivityTaskManager = new ActivityTaskManagerService(mContext); realAms.mActivityTaskManager.initialize(null, null, mContext.getMainLooper()); realAms.mAtmInternal = spy(realAms.mActivityTaskManager.getAtmInternal()); realAms.mOomAdjuster = spy(realAms.mOomAdjuster); realAms.mPackageManagerInt = mPackageManagerInt; realAms.mUsageStatsService = mUsageStatsManagerInt; realAms.mProcessesReady = true; mAms = spy(realAms); mSkipPolicy = spy(new BroadcastSkipPolicy(mAms)); doReturn(null).when(mSkipPolicy).shouldSkipMessage(any(), any()); doReturn(false).when(mSkipPolicy).disallowBackgroundStart(any()); mConstants = new BroadcastConstants(Settings.Global.BROADCAST_FG_CONSTANTS); } public void tearDown() throws Exception { mHandlerThread.quit(); } static int getUidForPackage(@NonNull String packageName) { switch (packageName) { case PACKAGE_ANDROID: return android.os.Process.SYSTEM_UID; case PACKAGE_PHONE: return android.os.Process.PHONE_UID; case PACKAGE_RED: return android.os.Process.FIRST_APPLICATION_UID + 1; case PACKAGE_GREEN: return android.os.Process.FIRST_APPLICATION_UID + 2; case PACKAGE_BLUE: return android.os.Process.FIRST_APPLICATION_UID + 3; case PACKAGE_YELLOW: return android.os.Process.FIRST_APPLICATION_UID + 4; case PACKAGE_ORANGE: return android.os.Process.FIRST_APPLICATION_UID + 5; default: throw new IllegalArgumentException(); } } static int getUidForPackage(@NonNull String packageName, int userId) { return UserHandle.getUid(userId, getUidForPackage(packageName)); } private class TestInjector extends ActivityManagerService.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 mProcessList; } } abstract String getTag(); static ApplicationInfo makeApplicationInfo(String packageName) { return makeApplicationInfo(packageName, packageName, UserHandle.USER_SYSTEM); } static ApplicationInfo makeApplicationInfo(String packageName, String processName, int userId) { final ApplicationInfo ai = new ApplicationInfo(); ai.packageName = packageName; ai.processName = processName; ai.uid = getUidForPackage(packageName, userId); return ai; } static ResolveInfo withPriority(ResolveInfo info, int priority) { info.priority = priority; return info; } static BroadcastFilter withPriority(BroadcastFilter filter, int priority) { filter.setPriority(priority); return filter; } static ResolveInfo makeManifestReceiver(String packageName, String name) { return makeManifestReceiver(packageName, name, UserHandle.USER_SYSTEM); } static ResolveInfo makeManifestReceiver(String packageName, String name, int userId) { return makeManifestReceiver(packageName, packageName, name, userId); } static ResolveInfo makeManifestReceiver(String packageName, String processName, String name, int userId) { final ResolveInfo ri = new ResolveInfo(); ri.activityInfo = new ActivityInfo(); ri.activityInfo.packageName = packageName; ri.activityInfo.processName = processName; ri.activityInfo.name = name; ri.activityInfo.applicationInfo = makeApplicationInfo(packageName, processName, userId); return ri; } BroadcastFilter makeRegisteredReceiver(ProcessRecord app) { return makeRegisteredReceiver(app, 0); } BroadcastFilter makeRegisteredReceiver(ProcessRecord app, int priority) { final ReceiverList receiverList = mRegisteredReceivers.get(app.getPid()); return makeRegisteredReceiver(receiverList, priority); } static BroadcastFilter makeRegisteredReceiver(ReceiverList receiverList, int priority) { final IntentFilter filter = new IntentFilter(); filter.setPriority(priority); final BroadcastFilter res = new BroadcastFilter(filter, receiverList, receiverList.app.info.packageName, null, null, null, receiverList.uid, receiverList.userId, false, false, true); receiverList.add(res); return res; } } Loading
services/core/java/com/android/server/am/BroadcastProcessQueue.java +27 −14 Original line number Diff line number Diff line Loading @@ -265,13 +265,6 @@ class BroadcastProcessQueue { @Nullable public BroadcastRecord enqueueOrReplaceBroadcast(@NonNull BroadcastRecord record, int recordIndex, @NonNull BroadcastConsumer deferredStatesApplyConsumer) { // When updateDeferredStates() has already applied a deferred state to // all pending items, apply to this new broadcast too if (mLastDeferredStates && record.deferUntilActive && (record.getDeliveryState(recordIndex) == BroadcastRecord.DELIVERY_PENDING)) { deferredStatesApplyConsumer.accept(record, recordIndex); } // Ignore FLAG_RECEIVER_REPLACE_PENDING if the sender specified the policy using the // BroadcastOptions delivery group APIs. if (record.isReplacePending() Loading @@ -294,6 +287,13 @@ class BroadcastProcessQueue { // with implicit responsiveness expectations. getQueueForBroadcast(record).addLast(newBroadcastArgs); onBroadcastEnqueued(record, recordIndex); // When updateDeferredStates() has already applied a deferred state to // all pending items, apply to this new broadcast too if (mLastDeferredStates && shouldBeDeferred() && (record.getDeliveryState(recordIndex) == BroadcastRecord.DELIVERY_PENDING)) { deferredStatesApplyConsumer.accept(record, recordIndex); } return null; } Loading Loading @@ -1235,30 +1235,43 @@ class BroadcastProcessQueue { } /** * Update {@link BroadcastRecord.DELIVERY_DEFERRED} states of all our * Update {@link BroadcastRecord#DELIVERY_DEFERRED} states of all our * pending broadcasts, when needed. */ void updateDeferredStates(@NonNull BroadcastConsumer applyConsumer, @NonNull BroadcastConsumer clearConsumer) { // When all we have pending is deferred broadcasts, and we're cached, // then we want everything to be marked deferred final boolean wantDeferredStates = (mCountDeferred > 0) && (mCountDeferred == mCountEnqueued) && mProcessFreezable; final boolean wantDeferredStates = shouldBeDeferred(); if (mLastDeferredStates != wantDeferredStates) { mLastDeferredStates = wantDeferredStates; if (wantDeferredStates) { forEachMatchingBroadcast((r, i) -> { return r.deferUntilActive && (r.getDeliveryState(i) == BroadcastRecord.DELIVERY_PENDING); return (r.getDeliveryState(i) == BroadcastRecord.DELIVERY_PENDING); }, applyConsumer, false); } else { forEachMatchingBroadcast((r, i) -> { return r.deferUntilActive && (r.getDeliveryState(i) == BroadcastRecord.DELIVERY_DEFERRED); return (r.getDeliveryState(i) == BroadcastRecord.DELIVERY_DEFERRED); }, clearConsumer, false); } } } void clearDeferredStates(@NonNull BroadcastConsumer clearConsumer) { if (mLastDeferredStates) { mLastDeferredStates = false; forEachMatchingBroadcast((r, i) -> { return (r.getDeliveryState(i) == BroadcastRecord.DELIVERY_DEFERRED); }, clearConsumer, false); } } @VisibleForTesting boolean shouldBeDeferred() { if (mRunnableAtInvalidated) updateRunnableAt(); return mRunnableAtReason == REASON_CACHED || mRunnableAtReason == REASON_CACHED_INFINITE_DEFER; } /** Loading
services/core/java/com/android/server/am/BroadcastQueueModernImpl.java +8 −2 Original line number Diff line number Diff line Loading @@ -479,6 +479,10 @@ class BroadcastQueueModernImpl extends BroadcastQueue { break; } // Clear the deferred state of broadcasts in this queue as we are just about to // deliver broadcasts to this process. queue.clearDeferredStates(mBroadcastConsumerDeferClear); // We might not have heard about a newly running process yet, so // consider refreshing if we think we're cold updateWarmProcess(queue); Loading Loading @@ -1567,12 +1571,14 @@ class BroadcastQueueModernImpl extends BroadcastQueue { r.resultExtras = null; }; private final BroadcastConsumer mBroadcastConsumerDeferApply = (r, i) -> { @VisibleForTesting final BroadcastConsumer mBroadcastConsumerDeferApply = (r, i) -> { setDeliveryState(null, null, r, i, r.receivers.get(i), BroadcastRecord.DELIVERY_DEFERRED, "mBroadcastConsumerDeferApply"); }; private final BroadcastConsumer mBroadcastConsumerDeferClear = (r, i) -> { @VisibleForTesting final BroadcastConsumer mBroadcastConsumerDeferClear = (r, i) -> { setDeliveryState(null, null, r, i, r.receivers.get(i), BroadcastRecord.DELIVERY_PENDING, "mBroadcastConsumerDeferClear"); }; Loading
services/tests/mockingservicestests/src/com/android/server/am/BaseBroadcastQueueTest.java 0 → 100644 +259 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 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 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.ArgumentMatchers.eq; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; import android.annotation.NonNull; import android.app.usage.UsageStatsManagerInternal; import android.content.ComponentName; import android.content.Context; import android.content.IntentFilter; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManagerInternal; import android.content.pm.ResolveInfo; import android.os.Handler; import android.os.HandlerThread; import android.os.TestLooperManager; import android.os.UserHandle; import android.provider.Settings; import android.util.SparseArray; import androidx.test.platform.app.InstrumentationRegistry; import com.android.server.AlarmManagerInternal; import com.android.server.DropBoxManagerInternal; import com.android.server.LocalServices; import com.android.server.appop.AppOpsService; import com.android.server.wm.ActivityTaskManagerService; import org.junit.Rule; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.io.File; import java.util.Objects; import java.util.concurrent.atomic.AtomicInteger; public abstract class BaseBroadcastQueueTest { static final int USER_GUEST = 11; static final String PACKAGE_ANDROID = "android"; static final String PACKAGE_PHONE = "com.android.phone"; static final String PACKAGE_RED = "com.example.red"; static final String PACKAGE_GREEN = "com.example.green"; static final String PACKAGE_BLUE = "com.example.blue"; static final String PACKAGE_YELLOW = "com.example.yellow"; static final String PACKAGE_ORANGE = "com.example.orange"; static final String PROCESS_SYSTEM = "system"; static final String CLASS_RED = "com.example.red.Red"; static final String CLASS_GREEN = "com.example.green.Green"; static final String CLASS_BLUE = "com.example.blue.Blue"; static final String CLASS_YELLOW = "com.example.yellow.Yellow"; static final String CLASS_ORANGE = "com.example.orange.Orange"; static final BroadcastProcessQueue.BroadcastPredicate BROADCAST_PREDICATE_ANY = (r, i) -> true; @Rule public final ApplicationExitInfoTest.ServiceThreadRule mServiceThreadRule = new ApplicationExitInfoTest.ServiceThreadRule(); @Mock AppOpsService mAppOpsService; @Mock PackageManagerInternal mPackageManagerInt; @Mock UsageStatsManagerInternal mUsageStatsManagerInt; @Mock DropBoxManagerInternal mDropBoxManagerInt; @Mock AlarmManagerInternal mAlarmManagerInt; @Mock ProcessList mProcessList; Context mContext; ActivityManagerService mAms; BroadcastConstants mConstants; BroadcastSkipPolicy mSkipPolicy; HandlerThread mHandlerThread; TestLooperManager mLooper; AtomicInteger mNextPid; /** * Map from PID to registered registered runtime receivers. */ SparseArray<ReceiverList> mRegisteredReceivers = new SparseArray<>(); public void setUp() throws Exception { MockitoAnnotations.initMocks(this); mContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); mHandlerThread = new HandlerThread(getTag()); mHandlerThread.start(); // Pause all event processing until a test chooses to resume mLooper = Objects.requireNonNull(InstrumentationRegistry.getInstrumentation() .acquireLooperManager(mHandlerThread.getLooper())); mNextPid = new AtomicInteger(100); LocalServices.removeServiceForTest(DropBoxManagerInternal.class); LocalServices.addService(DropBoxManagerInternal.class, mDropBoxManagerInt); LocalServices.removeServiceForTest(PackageManagerInternal.class); LocalServices.addService(PackageManagerInternal.class, mPackageManagerInt); LocalServices.removeServiceForTest(AlarmManagerInternal.class); LocalServices.addService(AlarmManagerInternal.class, mAlarmManagerInt); doReturn(new ComponentName("", "")).when(mPackageManagerInt).getSystemUiServiceComponent(); doNothing().when(mPackageManagerInt).notifyComponentUsed(any(), anyInt(), any(), any()); doAnswer((invocation) -> { return getUidForPackage(invocation.getArgument(0)); }).when(mPackageManagerInt).getPackageUid(any(), anyLong(), eq(UserHandle.USER_SYSTEM)); final ActivityManagerService realAms = new ActivityManagerService( new TestInjector(mContext), mServiceThreadRule.getThread()); realAms.mActivityTaskManager = new ActivityTaskManagerService(mContext); realAms.mActivityTaskManager.initialize(null, null, mContext.getMainLooper()); realAms.mAtmInternal = spy(realAms.mActivityTaskManager.getAtmInternal()); realAms.mOomAdjuster = spy(realAms.mOomAdjuster); realAms.mPackageManagerInt = mPackageManagerInt; realAms.mUsageStatsService = mUsageStatsManagerInt; realAms.mProcessesReady = true; mAms = spy(realAms); mSkipPolicy = spy(new BroadcastSkipPolicy(mAms)); doReturn(null).when(mSkipPolicy).shouldSkipMessage(any(), any()); doReturn(false).when(mSkipPolicy).disallowBackgroundStart(any()); mConstants = new BroadcastConstants(Settings.Global.BROADCAST_FG_CONSTANTS); } public void tearDown() throws Exception { mHandlerThread.quit(); } static int getUidForPackage(@NonNull String packageName) { switch (packageName) { case PACKAGE_ANDROID: return android.os.Process.SYSTEM_UID; case PACKAGE_PHONE: return android.os.Process.PHONE_UID; case PACKAGE_RED: return android.os.Process.FIRST_APPLICATION_UID + 1; case PACKAGE_GREEN: return android.os.Process.FIRST_APPLICATION_UID + 2; case PACKAGE_BLUE: return android.os.Process.FIRST_APPLICATION_UID + 3; case PACKAGE_YELLOW: return android.os.Process.FIRST_APPLICATION_UID + 4; case PACKAGE_ORANGE: return android.os.Process.FIRST_APPLICATION_UID + 5; default: throw new IllegalArgumentException(); } } static int getUidForPackage(@NonNull String packageName, int userId) { return UserHandle.getUid(userId, getUidForPackage(packageName)); } private class TestInjector extends ActivityManagerService.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 mProcessList; } } abstract String getTag(); static ApplicationInfo makeApplicationInfo(String packageName) { return makeApplicationInfo(packageName, packageName, UserHandle.USER_SYSTEM); } static ApplicationInfo makeApplicationInfo(String packageName, String processName, int userId) { final ApplicationInfo ai = new ApplicationInfo(); ai.packageName = packageName; ai.processName = processName; ai.uid = getUidForPackage(packageName, userId); return ai; } static ResolveInfo withPriority(ResolveInfo info, int priority) { info.priority = priority; return info; } static BroadcastFilter withPriority(BroadcastFilter filter, int priority) { filter.setPriority(priority); return filter; } static ResolveInfo makeManifestReceiver(String packageName, String name) { return makeManifestReceiver(packageName, name, UserHandle.USER_SYSTEM); } static ResolveInfo makeManifestReceiver(String packageName, String name, int userId) { return makeManifestReceiver(packageName, packageName, name, userId); } static ResolveInfo makeManifestReceiver(String packageName, String processName, String name, int userId) { final ResolveInfo ri = new ResolveInfo(); ri.activityInfo = new ActivityInfo(); ri.activityInfo.packageName = packageName; ri.activityInfo.processName = processName; ri.activityInfo.name = name; ri.activityInfo.applicationInfo = makeApplicationInfo(packageName, processName, userId); return ri; } BroadcastFilter makeRegisteredReceiver(ProcessRecord app) { return makeRegisteredReceiver(app, 0); } BroadcastFilter makeRegisteredReceiver(ProcessRecord app, int priority) { final ReceiverList receiverList = mRegisteredReceivers.get(app.getPid()); return makeRegisteredReceiver(receiverList, priority); } static BroadcastFilter makeRegisteredReceiver(ReceiverList receiverList, int priority) { final IntentFilter filter = new IntentFilter(); filter.setPriority(priority); final BroadcastFilter res = new BroadcastFilter(filter, receiverList, receiverList.app.info.packageName, null, null, null, receiverList.uid, receiverList.userId, false, false, true); receiverList.add(res); return res; } }