blob: 376f5cd3ab471c08cdfd2f6b0a6f0e75c7d7d5ae [file] [log] [blame]
Suprabh Shukla021b57a2018-03-08 18:21:50 -08001/*
2 * Copyright (C) 2018 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
17package com.android.server.pm;
18
Suprabh Shukla3017fe42018-11-08 19:00:01 -080019import static android.app.AppOpsManager.MODE_ALLOWED;
20import static android.app.AppOpsManager.MODE_IGNORED;
Suprabh Shukla873e19f2019-09-16 13:20:22 -070021import static android.app.AppOpsManager.OP_CAMERA;
Suprabh Shukla3017fe42018-11-08 19:00:01 -080022import static android.app.AppOpsManager.OP_PLAY_AUDIO;
Suprabh Shukla873e19f2019-09-16 13:20:22 -070023import static android.app.AppOpsManager.OP_RECORD_AUDIO;
24import static android.app.AppOpsManager.opToName;
Suprabh Shukla3017fe42018-11-08 19:00:01 -080025
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -070026import static org.junit.Assert.assertEquals;
Suprabh Shukla021b57a2018-03-08 18:21:50 -080027import static org.junit.Assert.assertFalse;
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -070028import static org.junit.Assert.assertNotNull;
Suprabh Shukla021b57a2018-03-08 18:21:50 -080029import static org.junit.Assert.assertNull;
30import static org.junit.Assert.assertTrue;
Suprabh Shukla3c3af142018-03-30 00:28:37 -070031import static org.junit.Assert.fail;
Suprabh Shukla77e22452018-05-22 18:02:37 -070032import static org.junit.Assume.assumeTrue;
Suprabh Shukla021b57a2018-03-08 18:21:50 -080033
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -070034import android.app.AppGlobals;
Suprabh Shukla021b57a2018-03-08 18:21:50 -080035import android.content.BroadcastReceiver;
36import android.content.ComponentName;
37import android.content.Context;
38import android.content.Intent;
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -070039import android.content.IntentFilter;
40import android.content.pm.IPackageManager;
Suprabh Shukla19b41f32018-03-26 22:35:13 -070041import android.content.pm.LauncherApps;
Suprabh Shukla021b57a2018-03-08 18:21:50 -080042import android.content.pm.PackageManager;
Suprabh Shukla389cb6f2018-10-01 18:20:39 -070043import android.content.pm.SuspendDialogInfo;
Suprabh Shuklac401f152018-04-10 17:07:32 -070044import android.content.res.Resources;
Suprabh Shukla021b57a2018-03-08 18:21:50 -080045import android.os.BaseBundle;
46import android.os.Bundle;
47import android.os.Handler;
48import android.os.Looper;
49import android.os.PersistableBundle;
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -070050import android.os.RemoteException;
Suprabh Shukla3017fe42018-11-08 19:00:01 -080051import android.os.ServiceManager;
Suprabh Shukla19b41f32018-03-26 22:35:13 -070052import android.os.UserHandle;
Suprabh Shukla3c3af142018-03-30 00:28:37 -070053import android.support.test.uiautomator.By;
54import android.support.test.uiautomator.UiDevice;
55import android.support.test.uiautomator.UiObject2;
56import android.support.test.uiautomator.Until;
Suprabh Shukla19b41f32018-03-26 22:35:13 -070057import android.util.Log;
Suprabh Shukla3c3af142018-03-30 00:28:37 -070058import android.view.IWindowManager;
59import android.view.WindowManagerGlobal;
Suprabh Shukla021b57a2018-03-08 18:21:50 -080060
Brett Chabota26eda92018-07-23 13:08:30 -070061import androidx.test.InstrumentationRegistry;
62import androidx.test.filters.LargeTest;
63import androidx.test.runner.AndroidJUnit4;
64
Suprabh Shukla3017fe42018-11-08 19:00:01 -080065import com.android.internal.app.IAppOpsCallback;
66import com.android.internal.app.IAppOpsService;
Suprabh Shukla3c3af142018-03-30 00:28:37 -070067import com.android.servicestests.apps.suspendtestapp.SuspendTestActivity;
Suprabh Shukla021b57a2018-03-08 18:21:50 -080068import com.android.servicestests.apps.suspendtestapp.SuspendTestReceiver;
69
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -070070import org.junit.After;
Suprabh Shukla021b57a2018-03-08 18:21:50 -080071import org.junit.Before;
72import org.junit.Test;
73import org.junit.runner.RunWith;
74
Suprabh Shukla77e22452018-05-22 18:02:37 -070075import java.io.IOException;
Suprabh Shukla19b41f32018-03-26 22:35:13 -070076import java.util.Arrays;
Suprabh Shukla021b57a2018-03-08 18:21:50 -080077import java.util.concurrent.CountDownLatch;
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -070078import java.util.concurrent.SynchronousQueue;
Suprabh Shukla021b57a2018-03-08 18:21:50 -080079import java.util.concurrent.TimeUnit;
80import java.util.concurrent.atomic.AtomicReference;
81
82@RunWith(AndroidJUnit4.class)
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -070083@LargeTest
Suprabh Shukla021b57a2018-03-08 18:21:50 -080084public class SuspendPackagesTest {
Suprabh Shukla19b41f32018-03-26 22:35:13 -070085 private static final String TAG = SuspendPackagesTest.class.getSimpleName();
Suprabh Shuklac401f152018-04-10 17:07:32 -070086 private static final String TEST_APP_LABEL = "Suspend Test App";
Suprabh Shukla021b57a2018-03-08 18:21:50 -080087 private static final String TEST_APP_PACKAGE_NAME = SuspendTestReceiver.PACKAGE_NAME;
88 private static final String[] PACKAGES_TO_SUSPEND = new String[]{TEST_APP_PACKAGE_NAME};
89
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -070090 public static final String INSTRUMENTATION_PACKAGE = "com.android.frameworks.servicestests";
91 public static final String ACTION_REPORT_MY_PACKAGE_SUSPENDED =
92 INSTRUMENTATION_PACKAGE + ".action.REPORT_MY_PACKAGE_SUSPENDED";
93 public static final String ACTION_REPORT_MY_PACKAGE_UNSUSPENDED =
94 INSTRUMENTATION_PACKAGE + ".action.REPORT_MY_PACKAGE_UNSUSPENDED";
Suprabh Shukla3c3af142018-03-30 00:28:37 -070095 public static final String ACTION_REPORT_TEST_ACTIVITY_STARTED =
96 INSTRUMENTATION_PACKAGE + ".action.REPORT_TEST_ACTIVITY_STARTED";
97 public static final String ACTION_REPORT_TEST_ACTIVITY_STOPPED =
98 INSTRUMENTATION_PACKAGE + ".action.REPORT_TEST_ACTIVITY_STOPPED";
99 public static final String ACTION_REPORT_MORE_DETAILS_ACTIVITY_STARTED =
100 INSTRUMENTATION_PACKAGE + ".action.REPORT_MORE_DETAILS_ACTIVITY_STARTED";
101 public static final String ACTION_FINISH_TEST_ACTIVITY =
102 INSTRUMENTATION_PACKAGE + ".action.FINISH_TEST_ACTIVITY";
103 public static final String EXTRA_RECEIVED_PACKAGE_NAME =
104 SuspendPackagesTest.INSTRUMENTATION_PACKAGE + ".extra.RECEIVED_PACKAGE_NAME";
105
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700106
Suprabh Shukla021b57a2018-03-08 18:21:50 -0800107 private Context mContext;
108 private PackageManager mPackageManager;
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700109 private LauncherApps mLauncherApps;
Suprabh Shukla021b57a2018-03-08 18:21:50 -0800110 private Handler mReceiverHandler;
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700111 private AppCommunicationReceiver mAppCommsReceiver;
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700112 private StubbedCallback mTestCallback;
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700113 private UiDevice mUiDevice;
Suprabh Shukla77e22452018-05-22 18:02:37 -0700114 private ComponentName mDeviceAdminComponent;
115 private boolean mPoSet;
116 private boolean mDoSet;
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700117
118 private static final class AppCommunicationReceiver extends BroadcastReceiver {
119 private Context context;
120 private boolean registered;
121 private SynchronousQueue<Intent> intentQueue = new SynchronousQueue<>();
122
123 AppCommunicationReceiver(Context context) {
124 this.context = context;
125 }
126
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700127 void register(Handler handler, String... actions) {
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700128 registered = true;
129 final IntentFilter intentFilter = new IntentFilter();
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700130 for (String action : actions) {
131 intentFilter.addAction(action);
132 }
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700133 context.registerReceiver(this, intentFilter, null, handler);
134 }
135
136 void unregister() {
137 if (registered) {
138 context.unregisterReceiver(this);
139 }
140 }
141
142 @Override
143 public void onReceive(Context context, Intent intent) {
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700144 Log.d(TAG, "AppCommunicationReceiver#onReceive: " + intent.getAction());
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700145 try {
146 intentQueue.offer(intent, 5, TimeUnit.SECONDS);
147 } catch (InterruptedException ie) {
148 throw new RuntimeException("Receiver thread interrupted", ie);
149 }
150 }
151
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700152 Intent pollForIntent(long secondsToWait) {
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700153 if (!registered) {
154 throw new IllegalStateException("Receiver not registered");
155 }
156 final Intent intent;
157 try {
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700158 intent = intentQueue.poll(secondsToWait, TimeUnit.SECONDS);
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700159 } catch (InterruptedException ie) {
160 throw new RuntimeException("Interrupted while waiting for app broadcast", ie);
161 }
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700162 return intent;
163 }
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700164
165 void drainPendingBroadcasts() {
Suprabh Shukla389cb6f2018-10-01 18:20:39 -0700166 while (pollForIntent(5) != null) ;
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700167 }
168
169 Intent receiveIntentFromApp() {
170 final Intent intentReceived = pollForIntent(5);
171 assertNotNull("No intent received from app within 5 seconds", intentReceived);
172 return intentReceived;
173 }
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700174 }
Suprabh Shukla021b57a2018-03-08 18:21:50 -0800175
176 @Before
177 public void setUp() {
178 mContext = InstrumentationRegistry.getTargetContext();
179 mPackageManager = mContext.getPackageManager();
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700180 mLauncherApps = (LauncherApps) mContext.getSystemService(Context.LAUNCHER_APPS_SERVICE);
Suprabh Shukla021b57a2018-03-08 18:21:50 -0800181 mReceiverHandler = new Handler(Looper.getMainLooper());
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700182 mUiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
Suprabh Shukla77e22452018-05-22 18:02:37 -0700183 mDeviceAdminComponent = new ComponentName(mContext,
184 "com.android.server.devicepolicy.DummyDeviceAdmins$Admin1");
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700185 IPackageManager ipm = AppGlobals.getPackageManager();
186 try {
187 // Otherwise implicit broadcasts will not be delivered.
188 ipm.setPackageStoppedState(TEST_APP_PACKAGE_NAME, false, mContext.getUserId());
189 } catch (RemoteException e) {
190 e.rethrowAsRuntimeException();
191 }
192 unsuspendTestPackage();
193 mAppCommsReceiver = new AppCommunicationReceiver(mContext);
Suprabh Shukla021b57a2018-03-08 18:21:50 -0800194 }
195
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700196 /**
197 * Care should be taken when used with {@link #mAppCommsReceiver} in the same test as both use
198 * the same handler.
199 */
Suprabh Shukla021b57a2018-03-08 18:21:50 -0800200 private Bundle requestAppAction(String action) throws InterruptedException {
201 final AtomicReference<Bundle> result = new AtomicReference<>();
202 final CountDownLatch receiverLatch = new CountDownLatch(1);
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700203 final ComponentName testReceiverComponent = new ComponentName(TEST_APP_PACKAGE_NAME,
204 SuspendTestReceiver.class.getCanonicalName());
Suprabh Shukla021b57a2018-03-08 18:21:50 -0800205 final Intent broadcastIntent = new Intent(action)
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700206 .setComponent(testReceiverComponent)
Suprabh Shukla021b57a2018-03-08 18:21:50 -0800207 .setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
208 mContext.sendOrderedBroadcast(broadcastIntent, null, new BroadcastReceiver() {
209 @Override
210 public void onReceive(Context context, Intent intent) {
211 result.set(getResultExtras(true));
212 receiverLatch.countDown();
213 }
214 }, mReceiverHandler, 0, null, null);
215
216 assertTrue("Test receiver timed out ", receiverLatch.await(5, TimeUnit.SECONDS));
217 return result.get();
218 }
219
220 private PersistableBundle getExtras(String keyPrefix, long lval, String sval, double dval) {
221 final PersistableBundle extras = new PersistableBundle(3);
222 extras.putLong(keyPrefix + ".LONG_VALUE", lval);
223 extras.putDouble(keyPrefix + ".DOUBLE_VALUE", dval);
224 extras.putString(keyPrefix + ".STRING_VALUE", sval);
225 return extras;
226 }
227
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700228 private void suspendTestPackage(PersistableBundle appExtras, PersistableBundle launcherExtras,
Suprabh Shukla389cb6f2018-10-01 18:20:39 -0700229 SuspendDialogInfo dialogInfo) {
Suprabh Shukla021b57a2018-03-08 18:21:50 -0800230 final String[] unchangedPackages = mPackageManager.setPackagesSuspended(
Suprabh Shukla389cb6f2018-10-01 18:20:39 -0700231 PACKAGES_TO_SUSPEND, true, appExtras, launcherExtras, dialogInfo);
Suprabh Shukla021b57a2018-03-08 18:21:50 -0800232 assertTrue("setPackagesSuspended returned non-empty list", unchangedPackages.length == 0);
233 }
234
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700235 private void unsuspendTestPackage() {
236 final String[] unchangedPackages = mPackageManager.setPackagesSuspended(
Suprabh Shukla389cb6f2018-10-01 18:20:39 -0700237 PACKAGES_TO_SUSPEND, false, null, null, (SuspendDialogInfo) null);
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700238 assertTrue("setPackagesSuspended returned non-empty list", unchangedPackages.length == 0);
239 }
240
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700241 private void startTestAppActivity() {
242 final Intent testActivity = new Intent()
243 .setComponent(new ComponentName(TEST_APP_PACKAGE_NAME,
244 SuspendTestActivity.class.getCanonicalName()))
245 .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
246 mContext.startActivity(testActivity);
247 }
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700248
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700249 private static boolean areSameExtras(BaseBundle expected, BaseBundle received) {
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700250 if (expected != null) {
251 expected.get(""); // hack to unparcel the bundles.
252 }
253 if (received != null) {
254 received.get("");
255 }
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700256 return BaseBundle.kindofEquals(expected, received);
257 }
258
259 private static void assertSameExtras(String message, BaseBundle expected, BaseBundle received) {
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700260 if (!areSameExtras(expected, received)) {
261 fail(message + ": [expected: " + expected + "; received: " + received + "]");
262 }
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700263 }
264
Suprabh Shukla021b57a2018-03-08 18:21:50 -0800265 @Test
Suprabh Shukla96212bc2018-04-10 15:04:51 -0700266 public void testIsPackageSuspended() throws Exception {
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700267 suspendTestPackage(null, null, null);
Suprabh Shukla021b57a2018-03-08 18:21:50 -0800268 assertTrue("isPackageSuspended is false",
269 mPackageManager.isPackageSuspended(TEST_APP_PACKAGE_NAME));
270 }
271
272 @Test
273 public void testSuspendedStateFromApp() throws Exception {
274 Bundle resultFromApp = requestAppAction(SuspendTestReceiver.ACTION_GET_SUSPENDED_STATE);
275 assertFalse(resultFromApp.getBoolean(SuspendTestReceiver.EXTRA_SUSPENDED, true));
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700276 assertNull(resultFromApp.getBundle(SuspendTestReceiver.EXTRA_SUSPENDED_APP_EXTRAS));
Suprabh Shukla021b57a2018-03-08 18:21:50 -0800277
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700278 final PersistableBundle appExtras = getExtras("testSuspendedStateFromApp", 20, "20", 0.2);
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700279 suspendTestPackage(appExtras, null, null);
Suprabh Shukla021b57a2018-03-08 18:21:50 -0800280
281 resultFromApp = requestAppAction(SuspendTestReceiver.ACTION_GET_SUSPENDED_STATE);
282 assertTrue("resultFromApp:suspended is false",
283 resultFromApp.getBoolean(SuspendTestReceiver.EXTRA_SUSPENDED));
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700284 final Bundle receivedAppExtras =
285 resultFromApp.getBundle(SuspendTestReceiver.EXTRA_SUSPENDED_APP_EXTRAS);
286 assertSameExtras("Received app extras different to the ones supplied",
287 appExtras, receivedAppExtras);
288 }
289
290 @Test
291 public void testMyPackageSuspendedUnsuspended() {
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700292 mAppCommsReceiver.register(mReceiverHandler, ACTION_REPORT_MY_PACKAGE_SUSPENDED,
293 ACTION_REPORT_MY_PACKAGE_UNSUSPENDED);
294 mAppCommsReceiver.drainPendingBroadcasts();
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700295 final PersistableBundle appExtras = getExtras("testMyPackageSuspendBroadcasts", 1, "1", .1);
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700296 suspendTestPackage(appExtras, null, null);
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700297 Intent intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700298 assertEquals("MY_PACKAGE_SUSPENDED delivery not reported",
299 ACTION_REPORT_MY_PACKAGE_SUSPENDED, intentFromApp.getAction());
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700300 assertSameExtras("Received app extras different to the ones supplied", appExtras,
301 intentFromApp.getBundleExtra(SuspendTestReceiver.EXTRA_SUSPENDED_APP_EXTRAS));
302 unsuspendTestPackage();
303 intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700304 assertEquals("MY_PACKAGE_UNSUSPENDED delivery not reported",
305 ACTION_REPORT_MY_PACKAGE_UNSUSPENDED, intentFromApp.getAction());
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700306 }
307
308 @Test
309 public void testUpdatingAppExtras() {
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700310 mAppCommsReceiver.register(mReceiverHandler, ACTION_REPORT_MY_PACKAGE_SUSPENDED);
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700311 final PersistableBundle extras1 = getExtras("testMyPackageSuspendedOnChangingExtras", 1,
312 "1", 0.1);
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700313 suspendTestPackage(extras1, null, null);
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700314 Intent intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700315 assertEquals("MY_PACKAGE_SUSPENDED delivery not reported",
316 ACTION_REPORT_MY_PACKAGE_SUSPENDED, intentFromApp.getAction());
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700317 assertSameExtras("Received app extras different to the ones supplied", extras1,
318 intentFromApp.getBundleExtra(SuspendTestReceiver.EXTRA_SUSPENDED_APP_EXTRAS));
319 final PersistableBundle extras2 = getExtras("testMyPackageSuspendedOnChangingExtras", 2,
320 "2", 0.2);
Suprabh Shukla45b9e402018-04-09 17:33:53 -0700321 suspendTestPackage(extras2, null, null);
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700322 intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700323 assertEquals("MY_PACKAGE_SUSPENDED delivery not reported",
324 ACTION_REPORT_MY_PACKAGE_SUSPENDED, intentFromApp.getAction());
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700325 assertSameExtras("Received app extras different to the updated extras", extras2,
326 intentFromApp.getBundleExtra(SuspendTestReceiver.EXTRA_SUSPENDED_APP_EXTRAS));
327 }
328
329 @Test
330 public void testCannotSuspendSelf() {
331 final String[] unchangedPkgs = mPackageManager.setPackagesSuspended(
Suprabh Shukla389cb6f2018-10-01 18:20:39 -0700332 new String[]{mContext.getOpPackageName()}, true, null, null,
333 (SuspendDialogInfo) null);
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700334 assertTrue(unchangedPkgs.length == 1);
335 assertEquals(mContext.getOpPackageName(), unchangedPkgs[0]);
336 }
337
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700338 @Test
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700339 public void testActivityStoppedOnSuspend() {
340 mAppCommsReceiver.register(mReceiverHandler, ACTION_REPORT_TEST_ACTIVITY_STARTED,
341 ACTION_REPORT_TEST_ACTIVITY_STOPPED);
342 startTestAppActivity();
343 Intent intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
344 assertEquals("Test activity start not reported",
345 ACTION_REPORT_TEST_ACTIVITY_STARTED, intentFromApp.getAction());
346 suspendTestPackage(null, null, null);
347 intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
348 assertEquals("Test activity stop not reported on suspending the test app",
349 ACTION_REPORT_TEST_ACTIVITY_STOPPED, intentFromApp.getAction());
350 }
351
352 @Test
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700353 public void testGetLauncherExtrasNonNull() {
354 final Bundle extrasWhenUnsuspended = mLauncherApps.getSuspendedPackageLauncherExtras(
355 TEST_APP_PACKAGE_NAME, mContext.getUser());
356 assertNull("Non null extras when package unsuspended:", extrasWhenUnsuspended);
357 final PersistableBundle launcherExtras = getExtras("testGetLauncherExtras", 1, "1", 0.1);
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700358 suspendTestPackage(null, launcherExtras, null);
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700359 final Bundle receivedExtras = mLauncherApps.getSuspendedPackageLauncherExtras(
360 TEST_APP_PACKAGE_NAME, mContext.getUser());
361 assertSameExtras("Received launcher extras different to the ones supplied", launcherExtras,
362 receivedExtras);
363 }
364
365 @Test
366 public void testGetLauncherExtrasNull() {
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700367 suspendTestPackage(null, null, null);
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700368 final Bundle extrasWhenNoneGiven = mLauncherApps.getSuspendedPackageLauncherExtras(
369 TEST_APP_PACKAGE_NAME, mContext.getUser());
370 assertNull("Non null extras when null extras provided:", extrasWhenNoneGiven);
371 }
372
373 @Test
374 public void testGetLauncherExtrasInvalidPackage() {
375 final Bundle extrasForInvalidPackage = mLauncherApps.getSuspendedPackageLauncherExtras(
376 "test.nonexistent.packagename", mContext.getUser());
377 assertNull("Non null extras for an invalid package:", extrasForInvalidPackage);
378 }
379
380 @Test
381 public void testOnPackagesSuspendedNewAndOld() throws InterruptedException {
382 final PersistableBundle suppliedExtras = getExtras(
383 "testOnPackagesSuspendedNewAndOld", 2, "2", 0.2);
384 final AtomicReference<String> overridingBothCallbackResult = new AtomicReference<>("");
385 final CountDownLatch twoCallbackLatch = new CountDownLatch(2);
386 mTestCallback = new StubbedCallback() {
387 @Override
388 public void onPackagesSuspended(String[] packageNames, UserHandle user) {
389 overridingBothCallbackResult.set(overridingBothCallbackResult.get()
390 + "Old callback called even when the new one is overriden. ");
391 twoCallbackLatch.countDown();
392 }
393
394 @Override
Suprabh Shukla96212bc2018-04-10 15:04:51 -0700395 public void onPackagesSuspended(String[] packageNames, UserHandle user,
396 Bundle launcherExtras) {
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700397 final StringBuilder errorString = new StringBuilder();
398 if (!Arrays.equals(packageNames, PACKAGES_TO_SUSPEND)) {
399 errorString.append("Received unexpected packageNames in onPackagesSuspended:");
400 for (String packageName : packageNames) {
401 errorString.append(" " + packageName);
402 }
403 errorString.append(". ");
404 }
405 if (user.getIdentifier() != mContext.getUserId()) {
406 errorString.append("Received wrong user " + user.getIdentifier() + ". ");
407 }
408 if (!areSameExtras(launcherExtras, suppliedExtras)) {
409 errorString.append("Unexpected launcherExtras, supplied: " + suppliedExtras
410 + ", received: " + launcherExtras + ". ");
411 }
412 overridingBothCallbackResult.set(overridingBothCallbackResult.get()
413 + errorString.toString());
414 twoCallbackLatch.countDown();
415 }
416 };
417 mLauncherApps.registerCallback(mTestCallback, mReceiverHandler);
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700418 suspendTestPackage(null, suppliedExtras, null);
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700419 assertFalse("Both callbacks were invoked", twoCallbackLatch.await(5, TimeUnit.SECONDS));
420 twoCallbackLatch.countDown();
421 assertTrue("No callback was invoked", twoCallbackLatch.await(2, TimeUnit.SECONDS));
422 final String result = overridingBothCallbackResult.get();
423 assertTrue("Callbacks did not complete as expected: " + result, result.isEmpty());
424 }
425
426 @Test
427 public void testOnPackagesSuspendedOld() throws InterruptedException {
428 final PersistableBundle suppliedExtras = getExtras(
429 "testOnPackagesSuspendedOld", 2, "2", 0.2);
430 final AtomicReference<String> overridingOneCallbackResult = new AtomicReference<>("");
431 final CountDownLatch oneCallbackLatch = new CountDownLatch(1);
432 mTestCallback = new StubbedCallback() {
433 @Override
434 public void onPackagesSuspended(String[] packageNames, UserHandle user) {
435 final StringBuilder errorString = new StringBuilder();
436 if (!Arrays.equals(packageNames, PACKAGES_TO_SUSPEND)) {
437 errorString.append("Received unexpected packageNames in onPackagesSuspended:");
438 for (String packageName : packageNames) {
439 errorString.append(" " + packageName);
440 }
441 errorString.append(". ");
442 }
443 if (user.getIdentifier() != mContext.getUserId()) {
444 errorString.append("Received wrong user " + user.getIdentifier() + ". ");
445 }
446 overridingOneCallbackResult.set(overridingOneCallbackResult.get()
447 + errorString.toString());
448 oneCallbackLatch.countDown();
449 }
450 };
451 mLauncherApps.registerCallback(mTestCallback, mReceiverHandler);
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700452 suspendTestPackage(null, suppliedExtras, null);
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700453 assertTrue("Callback not invoked", oneCallbackLatch.await(5, TimeUnit.SECONDS));
454 final String result = overridingOneCallbackResult.get();
455 assertTrue("Callback did not complete as expected: " + result, result.isEmpty());
456 }
457
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700458 private void turnScreenOn() throws Exception {
459 if (!mUiDevice.isScreenOn()) {
460 mUiDevice.wakeUp();
461 }
462 final IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
463 wm.dismissKeyguard(null, null);
464 }
465
466 @Test
467 public void testInterceptorActivity() throws Exception {
468 turnScreenOn();
469 mAppCommsReceiver.register(mReceiverHandler, ACTION_REPORT_MORE_DETAILS_ACTIVITY_STARTED,
470 ACTION_REPORT_TEST_ACTIVITY_STARTED);
Suprabh Shuklac401f152018-04-10 17:07:32 -0700471 final String testMessage = "This is a test message to report suspension of %1$s";
Suprabh Shukla389cb6f2018-10-01 18:20:39 -0700472 suspendTestPackage(null, null,
473 new SuspendDialogInfo.Builder().setMessage(testMessage).build());
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700474 startTestAppActivity();
475 assertNull("No broadcast was expected from app", mAppCommsReceiver.pollForIntent(2));
Suprabh Shuklac401f152018-04-10 17:07:32 -0700476 assertNotNull("Given dialog message not shown", mUiDevice.wait(
477 Until.findObject(By.text(String.format(testMessage, TEST_APP_LABEL))), 5000));
478 final String buttonText = mContext.getResources().getString(Resources.getSystem()
479 .getIdentifier("app_suspended_more_details", "string", "android"));
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700480 final UiObject2 moreDetailsButton = mUiDevice.findObject(
481 By.clickable(true).text(buttonText));
Suprabh Shuklac401f152018-04-10 17:07:32 -0700482 assertNotNull(buttonText + " button not shown", moreDetailsButton);
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700483 moreDetailsButton.click();
484 final Intent intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
Suprabh Shuklac401f152018-04-10 17:07:32 -0700485 assertEquals(buttonText + " activity start not reported",
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700486 ACTION_REPORT_MORE_DETAILS_ACTIVITY_STARTED, intentFromApp.getAction());
487 final String receivedPackageName = intentFromApp.getStringExtra(
488 EXTRA_RECEIVED_PACKAGE_NAME);
Suprabh Shuklac401f152018-04-10 17:07:32 -0700489 assertEquals("Wrong package name received by " + buttonText + " activity",
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700490 TEST_APP_PACKAGE_NAME, receivedPackageName);
491 }
492
Suprabh Shukla77e22452018-05-22 18:02:37 -0700493 private boolean setProfileOwner() throws IOException {
494 final String result = mUiDevice.executeShellCommand("dpm set-profile-owner --user cur "
495 + mDeviceAdminComponent.flattenToString());
496 return mPoSet = result.trim().startsWith("Success");
497 }
498
499 private boolean setDeviceOwner() throws IOException {
500 final String result = mUiDevice.executeShellCommand("dpm set-device-owner --user cur "
501 + mDeviceAdminComponent.flattenToString());
502 return mDoSet = result.trim().startsWith("Success");
503 }
504
505 private void removeProfileOrDeviceOwner() throws IOException {
506 if (mPoSet || mDoSet) {
507 mUiDevice.executeShellCommand("dpm remove-active-admin --user cur "
508 + mDeviceAdminComponent.flattenToString());
509 mPoSet = mDoSet = false;
510 }
511 }
512
513 @Test
Jason Parks4e9335a2019-03-14 11:11:33 -0700514 public void testCanSuspendWhenProfileOwner() throws IOException {
Suprabh Shukla77e22452018-05-22 18:02:37 -0700515 assumeTrue(mPackageManager.hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN));
516 assertTrue("Profile-owner could not be set", setProfileOwner());
Jason Parks4e9335a2019-03-14 11:11:33 -0700517 suspendTestPackage(null, null, null);
Suprabh Shukla77e22452018-05-22 18:02:37 -0700518 }
519
520 @Test
Jason Parks4e9335a2019-03-14 11:11:33 -0700521 public void testCanSuspendWhenDeviceOwner() throws IOException {
Suprabh Shukla77e22452018-05-22 18:02:37 -0700522 assumeTrue(mPackageManager.hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN));
523 assertTrue("Device-owner could not be set", setDeviceOwner());
Jason Parks4e9335a2019-03-14 11:11:33 -0700524 suspendTestPackage(null, null, null);
Suprabh Shukla77e22452018-05-22 18:02:37 -0700525 }
526
527 @Test
528 public void testPackageUnsuspendedOnAddingDeviceOwner() throws IOException {
529 assumeTrue(mPackageManager.hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN));
530 mAppCommsReceiver.register(mReceiverHandler, ACTION_REPORT_MY_PACKAGE_UNSUSPENDED,
531 ACTION_REPORT_MY_PACKAGE_SUSPENDED);
532 mAppCommsReceiver.drainPendingBroadcasts();
533 suspendTestPackage(null, null, null);
534 Intent intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
535 assertEquals(ACTION_REPORT_MY_PACKAGE_SUSPENDED, intentFromApp.getAction());
536 assertTrue("Device-owner could not be set", setDeviceOwner());
537 intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
538 assertEquals(ACTION_REPORT_MY_PACKAGE_UNSUSPENDED, intentFromApp.getAction());
539 }
540
541 @Test
542 public void testPackageUnsuspendedOnAddingProfileOwner() throws IOException {
543 assumeTrue(mPackageManager.hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN));
544 mAppCommsReceiver.register(mReceiverHandler, ACTION_REPORT_MY_PACKAGE_UNSUSPENDED,
545 ACTION_REPORT_MY_PACKAGE_SUSPENDED);
546 mAppCommsReceiver.drainPendingBroadcasts();
547 suspendTestPackage(null, null, null);
548 Intent intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
549 assertEquals(ACTION_REPORT_MY_PACKAGE_SUSPENDED, intentFromApp.getAction());
550 assertTrue("Profile-owner could not be set", setProfileOwner());
551 intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
552 assertEquals(ACTION_REPORT_MY_PACKAGE_UNSUSPENDED, intentFromApp.getAction());
553 }
554
Suprabh Shukla3017fe42018-11-08 19:00:01 -0800555 @Test
Suprabh Shukla873e19f2019-09-16 13:20:22 -0700556 public void testCameraBlockedOnSuspend() throws Exception {
557 assertOpBlockedOnSuspend(OP_CAMERA);
558 }
559
560 @Test
561 public void testPlayAudioBlockedOnSuspend() throws Exception {
562 assertOpBlockedOnSuspend(OP_PLAY_AUDIO);
563 }
564
565 @Test
566 public void testRecordAudioBlockedOnSuspend() throws Exception {
567 assertOpBlockedOnSuspend(OP_RECORD_AUDIO);
568 }
569
570 private void assertOpBlockedOnSuspend(int code) throws Exception {
Suprabh Shukla3017fe42018-11-08 19:00:01 -0800571 final IAppOpsService iAppOps = IAppOpsService.Stub.asInterface(
572 ServiceManager.getService(Context.APP_OPS_SERVICE));
573 final CountDownLatch latch = new CountDownLatch(1);
574 final IAppOpsCallback watcher = new IAppOpsCallback.Stub() {
575 @Override
576 public void opChanged(int op, int uid, String packageName) {
Suprabh Shukla873e19f2019-09-16 13:20:22 -0700577 if (op == code && packageName.equals(TEST_APP_PACKAGE_NAME)) {
Suprabh Shukla3017fe42018-11-08 19:00:01 -0800578 latch.countDown();
579 }
580 }
581 };
Suprabh Shukla873e19f2019-09-16 13:20:22 -0700582 iAppOps.startWatchingMode(code, TEST_APP_PACKAGE_NAME, watcher);
Suprabh Shukla3017fe42018-11-08 19:00:01 -0800583 final int testPackageUid = mPackageManager.getPackageUid(TEST_APP_PACKAGE_NAME, 0);
Suprabh Shukla873e19f2019-09-16 13:20:22 -0700584 int opMode = iAppOps.checkOperation(code, testPackageUid, TEST_APP_PACKAGE_NAME);
585 assertEquals("Op " + opToName(code) + " disallowed for unsuspended package", MODE_ALLOWED,
586 opMode);
Suprabh Shukla3017fe42018-11-08 19:00:01 -0800587 suspendTestPackage(null, null, null);
588 assertTrue("AppOpsWatcher did not callback", latch.await(5, TimeUnit.SECONDS));
Suprabh Shukla873e19f2019-09-16 13:20:22 -0700589 opMode = iAppOps.checkOperation(code, testPackageUid, TEST_APP_PACKAGE_NAME);
590 assertEquals("Op " + opToName(code) + " allowed for suspended package", MODE_IGNORED,
591 opMode);
Suprabh Shukla3017fe42018-11-08 19:00:01 -0800592 iAppOps.stopWatchingMode(watcher);
593 }
594
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700595 @After
Suprabh Shukla77e22452018-05-22 18:02:37 -0700596 public void tearDown() throws IOException {
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700597 mAppCommsReceiver.unregister();
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700598 if (mTestCallback != null) {
599 mLauncherApps.unregisterCallback(mTestCallback);
600 }
Suprabh Shukla77e22452018-05-22 18:02:37 -0700601 removeProfileOrDeviceOwner();
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700602 mContext.sendBroadcast(new Intent(ACTION_FINISH_TEST_ACTIVITY)
603 .setPackage(TEST_APP_PACKAGE_NAME));
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700604 }
605
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700606 private static abstract class StubbedCallback extends LauncherApps.Callback {
607
608 @Override
609 public void onPackageRemoved(String packageName, UserHandle user) {
610 }
611
612 @Override
613 public void onPackageAdded(String packageName, UserHandle user) {
614 }
615
616 @Override
617 public void onPackageChanged(String packageName, UserHandle user) {
618 }
619
620 @Override
621 public void onPackagesAvailable(String[] packageNames, UserHandle user, boolean replacing) {
622
623 }
624
625 @Override
626 public void onPackagesUnavailable(String[] packageNames, UserHandle user,
627 boolean replacing) {
628 }
Suprabh Shukla021b57a2018-03-08 18:21:50 -0800629 }
630}