1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.am;
18 
19 import static org.mockito.ArgumentMatchers.any;
20 import static org.mockito.ArgumentMatchers.anyInt;
21 import static org.mockito.ArgumentMatchers.anyLong;
22 import static org.mockito.ArgumentMatchers.eq;
23 import static org.mockito.Mockito.doAnswer;
24 import static org.mockito.Mockito.doNothing;
25 import static org.mockito.Mockito.doReturn;
26 import static org.mockito.Mockito.spy;
27 
28 import android.annotation.NonNull;
29 import android.app.usage.UsageStatsManagerInternal;
30 import android.content.ComponentName;
31 import android.content.Context;
32 import android.content.IntentFilter;
33 import android.content.pm.ActivityInfo;
34 import android.content.pm.ApplicationInfo;
35 import android.content.pm.PackageManagerInternal;
36 import android.content.pm.ResolveInfo;
37 import android.os.Handler;
38 import android.os.HandlerThread;
39 import android.os.TestLooperManager;
40 import android.os.UserHandle;
41 import android.platform.test.flag.junit.CheckFlagsRule;
42 import android.platform.test.flag.junit.DeviceFlagsValueProvider;
43 import android.provider.Settings;
44 import android.util.SparseArray;
45 
46 import androidx.test.platform.app.InstrumentationRegistry;
47 
48 import com.android.dx.mockito.inline.extended.ExtendedMockito;
49 import com.android.internal.util.FrameworkStatsLog;
50 import com.android.modules.utils.testing.ExtendedMockitoRule;
51 import com.android.server.AlarmManagerInternal;
52 import com.android.server.DropBoxManagerInternal;
53 import com.android.server.LocalServices;
54 import com.android.server.appop.AppOpsService;
55 import com.android.server.wm.ActivityTaskManagerService;
56 
57 import org.junit.Rule;
58 import org.mockito.Mock;
59 import org.mockito.Mockito;
60 import org.mockito.MockitoAnnotations;
61 
62 import java.io.File;
63 import java.util.Objects;
64 import java.util.concurrent.atomic.AtomicInteger;
65 
66 public abstract class BaseBroadcastQueueTest {
67 
68     static final int USER_GUEST = 11;
69 
70     static final String PACKAGE_ANDROID = "android";
71     static final String PACKAGE_PHONE = "com.android.phone";
72     static final String PACKAGE_RED = "com.example.red";
73     static final String PACKAGE_GREEN = "com.example.green";
74     static final String PACKAGE_BLUE = "com.example.blue";
75     static final String PACKAGE_YELLOW = "com.example.yellow";
76     static final String PACKAGE_ORANGE = "com.example.orange";
77 
78     static final String PROCESS_SYSTEM = "system";
79 
80     static final String CLASS_RED = "com.example.red.Red";
81     static final String CLASS_GREEN = "com.example.green.Green";
82     static final String CLASS_BLUE = "com.example.blue.Blue";
83     static final String CLASS_YELLOW = "com.example.yellow.Yellow";
84     static final String CLASS_ORANGE = "com.example.orange.Orange";
85 
86     static final BroadcastProcessQueue.BroadcastPredicate BROADCAST_PREDICATE_ANY =
87             (r, i) -> true;
88 
89     @Rule
90     public final ApplicationExitInfoTest.ServiceThreadRule
91             mServiceThreadRule = new ApplicationExitInfoTest.ServiceThreadRule();
92 
93     @Rule
94     public final ExtendedMockitoRule mExtendedMockitoRule = new ExtendedMockitoRule.Builder(this)
95             .spyStatic(FrameworkStatsLog.class)
96             .spyStatic(ProcessList.class)
97             .build();
98 
99     @Rule
100     public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
101 
102     @Mock
103     AppOpsService mAppOpsService;
104     @Mock
105     PackageManagerInternal mPackageManagerInt;
106     @Mock
107     UsageStatsManagerInternal mUsageStatsManagerInt;
108     @Mock
109     DropBoxManagerInternal mDropBoxManagerInt;
110     @Mock
111     AlarmManagerInternal mAlarmManagerInt;
112     @Mock
113     ProcessList mProcessList;
114 
115     @Mock
116     AppStartInfoTracker mAppStartInfoTracker;
117 
118     Context mContext;
119     ActivityManagerService mAms;
120     BroadcastConstants mConstants;
121     BroadcastSkipPolicy mSkipPolicy;
122     HandlerThread mHandlerThread;
123     TestLooperManager mLooper;
124     AtomicInteger mNextPid;
125     BroadcastHistory mEmptyHistory;
126 
127     /**
128      * Map from PID to registered registered runtime receivers.
129      */
130     SparseArray<ReceiverList> mRegisteredReceivers = new SparseArray<>();
131 
setUp()132     public void setUp() throws Exception {
133         MockitoAnnotations.initMocks(this);
134 
135         mContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
136         mHandlerThread = new HandlerThread(getTag());
137         mHandlerThread.start();
138         // Pause all event processing until a test chooses to resume
139         mLooper = Objects.requireNonNull(InstrumentationRegistry.getInstrumentation()
140                 .acquireLooperManager(mHandlerThread.getLooper()));
141         mNextPid = new AtomicInteger(100);
142 
143         mConstants = new BroadcastConstants(Settings.Global.BROADCAST_FG_CONSTANTS);
144         mEmptyHistory = new BroadcastHistory(mConstants) {
145             public void addBroadcastToHistoryLocked(BroadcastRecord original) {
146                 // Ignored
147             }
148         };
149 
150         LocalServices.removeServiceForTest(DropBoxManagerInternal.class);
151         LocalServices.addService(DropBoxManagerInternal.class, mDropBoxManagerInt);
152         LocalServices.removeServiceForTest(PackageManagerInternal.class);
153         LocalServices.addService(PackageManagerInternal.class, mPackageManagerInt);
154         LocalServices.removeServiceForTest(AlarmManagerInternal.class);
155         LocalServices.addService(AlarmManagerInternal.class, mAlarmManagerInt);
156         doReturn(new ComponentName("", "")).when(mPackageManagerInt).getSystemUiServiceComponent();
157         doNothing().when(mPackageManagerInt).notifyComponentUsed(any(), anyInt(), any(), any());
158         doAnswer((invocation) -> {
159             return getUidForPackage(invocation.getArgument(0));
160         }).when(mPackageManagerInt).getPackageUid(any(), anyLong(), eq(UserHandle.USER_SYSTEM));
161 
162         final ActivityManagerService realAms = new ActivityManagerService(
163                 new TestInjector(mContext), mServiceThreadRule.getThread());
164         realAms.mActivityTaskManager = new ActivityTaskManagerService(mContext);
165         realAms.mActivityTaskManager.initialize(null, null, mContext.getMainLooper());
166         realAms.mAtmInternal = spy(realAms.mActivityTaskManager.getAtmInternal());
167         realAms.mOomAdjuster.mCachedAppOptimizer = Mockito.mock(CachedAppOptimizer.class);
168         realAms.mOomAdjuster = spy(realAms.mOomAdjuster);
169         ExtendedMockito.doNothing().when(() -> ProcessList.setOomAdj(anyInt(), anyInt(), anyInt()));
170         realAms.mPackageManagerInt = mPackageManagerInt;
171         realAms.mUsageStatsService = mUsageStatsManagerInt;
172         realAms.mProcessesReady = true;
173         mAms = spy(realAms);
174 
175         mSkipPolicy = spy(new BroadcastSkipPolicy(mAms));
176         doReturn(null).when(mSkipPolicy).shouldSkipMessage(any(), any());
177         doReturn(false).when(mSkipPolicy).disallowBackgroundStart(any());
178 
179         doReturn(mAppStartInfoTracker).when(mProcessList).getAppStartInfoTracker();
180     }
181 
tearDown()182     public void tearDown() throws Exception {
183         if (mHandlerThread != null) {
184             mHandlerThread.quit();
185         }
186     }
187 
getUidForPackage(@onNull String packageName)188     static int getUidForPackage(@NonNull String packageName) {
189         switch (packageName) {
190             case PACKAGE_ANDROID: return android.os.Process.SYSTEM_UID;
191             case PACKAGE_PHONE: return android.os.Process.PHONE_UID;
192             case PACKAGE_RED: return android.os.Process.FIRST_APPLICATION_UID + 1;
193             case PACKAGE_GREEN: return android.os.Process.FIRST_APPLICATION_UID + 2;
194             case PACKAGE_BLUE: return android.os.Process.FIRST_APPLICATION_UID + 3;
195             case PACKAGE_YELLOW: return android.os.Process.FIRST_APPLICATION_UID + 4;
196             case PACKAGE_ORANGE: return android.os.Process.FIRST_APPLICATION_UID + 5;
197             default: throw new IllegalArgumentException();
198         }
199     }
200 
getUidForPackage(@onNull String packageName, int userId)201     static int getUidForPackage(@NonNull String packageName, int userId) {
202         return UserHandle.getUid(userId, getUidForPackage(packageName));
203     }
204 
205     private class TestInjector extends ActivityManagerService.Injector {
TestInjector(Context context)206         TestInjector(Context context) {
207             super(context);
208         }
209 
210         @Override
getAppOpsService(File recentAccessesFile, File storageFile, Handler handler)211         public AppOpsService getAppOpsService(File recentAccessesFile, File storageFile,
212                                               Handler handler) {
213             return mAppOpsService;
214         }
215 
216         @Override
getUiHandler(ActivityManagerService service)217         public Handler getUiHandler(ActivityManagerService service) {
218             return mHandlerThread.getThreadHandler();
219         }
220 
221         @Override
getProcessList(ActivityManagerService service)222         public ProcessList getProcessList(ActivityManagerService service) {
223             return mProcessList;
224         }
225 
226         @Override
getBroadcastQueue(ActivityManagerService service)227         public BroadcastQueue getBroadcastQueue(ActivityManagerService service) {
228             return null;
229         }
230     }
231 
getTag()232     abstract String getTag();
233 
makeApplicationInfo(String packageName)234     static ApplicationInfo makeApplicationInfo(String packageName) {
235         return makeApplicationInfo(packageName, packageName, UserHandle.USER_SYSTEM);
236     }
237 
makeApplicationInfo(String packageName, String processName, int userId)238     static ApplicationInfo makeApplicationInfo(String packageName, String processName, int userId) {
239         final ApplicationInfo ai = new ApplicationInfo();
240         ai.packageName = packageName;
241         ai.processName = processName;
242         ai.uid = getUidForPackage(packageName, userId);
243         return ai;
244     }
245 
withPriority(ResolveInfo info, int priority)246     static ResolveInfo withPriority(ResolveInfo info, int priority) {
247         info.priority = priority;
248         return info;
249     }
250 
withPriority(BroadcastFilter filter, int priority)251     static BroadcastFilter withPriority(BroadcastFilter filter, int priority) {
252         filter.setPriority(priority);
253         return filter;
254     }
255 
makeManifestReceiver(String packageName, String name)256     static ResolveInfo makeManifestReceiver(String packageName, String name) {
257         return makeManifestReceiver(packageName, name, UserHandle.USER_SYSTEM);
258     }
259 
makeManifestReceiver(String packageName, String name, int userId)260     static ResolveInfo makeManifestReceiver(String packageName, String name, int userId) {
261         return makeManifestReceiver(packageName, packageName, name, userId);
262     }
263 
makeManifestReceiver(String packageName, String processName, String name, int userId)264     static ResolveInfo makeManifestReceiver(String packageName, String processName,
265             String name, int userId) {
266         final ResolveInfo ri = new ResolveInfo();
267         ri.activityInfo = new ActivityInfo();
268         ri.activityInfo.packageName = packageName;
269         ri.activityInfo.processName = processName;
270         ri.activityInfo.name = name;
271         ri.activityInfo.applicationInfo = makeApplicationInfo(packageName, processName, userId);
272         return ri;
273     }
274 
makeRegisteredReceiver(ProcessRecord app)275     BroadcastFilter makeRegisteredReceiver(ProcessRecord app) {
276         return makeRegisteredReceiver(app, 0);
277     }
278 
makeRegisteredReceiver(ProcessRecord app, int priority)279     BroadcastFilter makeRegisteredReceiver(ProcessRecord app, int priority) {
280         final ReceiverList receiverList = mRegisteredReceivers.get(app.getPid());
281         return makeRegisteredReceiver(receiverList, priority);
282     }
283 
makeRegisteredReceiver(ReceiverList receiverList, int priority)284     static BroadcastFilter makeRegisteredReceiver(ReceiverList receiverList, int priority) {
285         final IntentFilter filter = new IntentFilter();
286         filter.setPriority(priority);
287         final BroadcastFilter res = new BroadcastFilter(filter, receiverList,
288                 receiverList.app.info.packageName, null, null, null, receiverList.uid,
289                 receiverList.userId, false, false, true);
290         receiverList.add(res);
291         return res;
292     }
293 
setProcessFreezable(ProcessRecord app, boolean pendingFreeze, boolean frozen)294     void setProcessFreezable(ProcessRecord app, boolean pendingFreeze, boolean frozen) {
295         app.mOptRecord.setPendingFreeze(pendingFreeze);
296         app.mOptRecord.setFrozen(frozen);
297     }
298 }
299