blob: d5d32bdd00ccd32ed41ea9184f0acda7488a3527 [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;
21import static android.app.AppOpsManager.OP_PLAY_AUDIO;
22
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -070023import static org.junit.Assert.assertEquals;
Suprabh Shukla021b57a2018-03-08 18:21:50 -080024import static org.junit.Assert.assertFalse;
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -070025import static org.junit.Assert.assertNotNull;
Suprabh Shukla021b57a2018-03-08 18:21:50 -080026import static org.junit.Assert.assertNull;
27import static org.junit.Assert.assertTrue;
Suprabh Shukla3c3af142018-03-30 00:28:37 -070028import static org.junit.Assert.fail;
Suprabh Shukla77e22452018-05-22 18:02:37 -070029import static org.junit.Assume.assumeTrue;
Suprabh Shukla021b57a2018-03-08 18:21:50 -080030
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -070031import android.app.AppGlobals;
Suprabh Shukla021b57a2018-03-08 18:21:50 -080032import android.content.BroadcastReceiver;
33import android.content.ComponentName;
34import android.content.Context;
35import android.content.Intent;
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -070036import android.content.IntentFilter;
37import android.content.pm.IPackageManager;
Suprabh Shukla19b41f32018-03-26 22:35:13 -070038import android.content.pm.LauncherApps;
Suprabh Shukla021b57a2018-03-08 18:21:50 -080039import android.content.pm.PackageManager;
Suprabh Shukla389cb6f2018-10-01 18:20:39 -070040import android.content.pm.SuspendDialogInfo;
Suprabh Shuklac401f152018-04-10 17:07:32 -070041import android.content.res.Resources;
Suprabh Shukla3017fe42018-11-08 19:00:01 -080042import android.media.AudioAttributes;
Suprabh Shukla021b57a2018-03-08 18:21:50 -080043import android.os.BaseBundle;
44import android.os.Bundle;
45import android.os.Handler;
46import android.os.Looper;
47import android.os.PersistableBundle;
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -070048import android.os.RemoteException;
Suprabh Shukla3017fe42018-11-08 19:00:01 -080049import android.os.ServiceManager;
Suprabh Shukla19b41f32018-03-26 22:35:13 -070050import android.os.UserHandle;
Suprabh Shukla3c3af142018-03-30 00:28:37 -070051import android.support.test.uiautomator.By;
52import android.support.test.uiautomator.UiDevice;
53import android.support.test.uiautomator.UiObject2;
54import android.support.test.uiautomator.Until;
Suprabh Shukla19b41f32018-03-26 22:35:13 -070055import android.util.Log;
Suprabh Shukla3c3af142018-03-30 00:28:37 -070056import android.view.IWindowManager;
57import android.view.WindowManagerGlobal;
Suprabh Shukla021b57a2018-03-08 18:21:50 -080058
Brett Chabota26eda92018-07-23 13:08:30 -070059import androidx.test.InstrumentationRegistry;
60import androidx.test.filters.LargeTest;
61import androidx.test.runner.AndroidJUnit4;
62
Suprabh Shukla3017fe42018-11-08 19:00:01 -080063import com.android.internal.app.IAppOpsCallback;
64import com.android.internal.app.IAppOpsService;
Suprabh Shukla3c3af142018-03-30 00:28:37 -070065import com.android.servicestests.apps.suspendtestapp.SuspendTestActivity;
Suprabh Shukla021b57a2018-03-08 18:21:50 -080066import com.android.servicestests.apps.suspendtestapp.SuspendTestReceiver;
67
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -070068import org.junit.After;
Suprabh Shukla021b57a2018-03-08 18:21:50 -080069import org.junit.Before;
70import org.junit.Test;
71import org.junit.runner.RunWith;
72
Suprabh Shukla77e22452018-05-22 18:02:37 -070073import java.io.IOException;
Suprabh Shukla19b41f32018-03-26 22:35:13 -070074import java.util.Arrays;
Suprabh Shukla021b57a2018-03-08 18:21:50 -080075import java.util.concurrent.CountDownLatch;
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -070076import java.util.concurrent.SynchronousQueue;
Suprabh Shukla021b57a2018-03-08 18:21:50 -080077import java.util.concurrent.TimeUnit;
78import java.util.concurrent.atomic.AtomicReference;
79
80@RunWith(AndroidJUnit4.class)
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -070081@LargeTest
Suprabh Shukla021b57a2018-03-08 18:21:50 -080082public class SuspendPackagesTest {
Suprabh Shukla19b41f32018-03-26 22:35:13 -070083 private static final String TAG = SuspendPackagesTest.class.getSimpleName();
Suprabh Shuklac401f152018-04-10 17:07:32 -070084 private static final String TEST_APP_LABEL = "Suspend Test App";
Suprabh Shukla021b57a2018-03-08 18:21:50 -080085 private static final String TEST_APP_PACKAGE_NAME = SuspendTestReceiver.PACKAGE_NAME;
86 private static final String[] PACKAGES_TO_SUSPEND = new String[]{TEST_APP_PACKAGE_NAME};
87
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -070088 public static final String INSTRUMENTATION_PACKAGE = "com.android.frameworks.servicestests";
89 public static final String ACTION_REPORT_MY_PACKAGE_SUSPENDED =
90 INSTRUMENTATION_PACKAGE + ".action.REPORT_MY_PACKAGE_SUSPENDED";
91 public static final String ACTION_REPORT_MY_PACKAGE_UNSUSPENDED =
92 INSTRUMENTATION_PACKAGE + ".action.REPORT_MY_PACKAGE_UNSUSPENDED";
Suprabh Shukla3c3af142018-03-30 00:28:37 -070093 public static final String ACTION_REPORT_TEST_ACTIVITY_STARTED =
94 INSTRUMENTATION_PACKAGE + ".action.REPORT_TEST_ACTIVITY_STARTED";
95 public static final String ACTION_REPORT_TEST_ACTIVITY_STOPPED =
96 INSTRUMENTATION_PACKAGE + ".action.REPORT_TEST_ACTIVITY_STOPPED";
97 public static final String ACTION_REPORT_MORE_DETAILS_ACTIVITY_STARTED =
98 INSTRUMENTATION_PACKAGE + ".action.REPORT_MORE_DETAILS_ACTIVITY_STARTED";
99 public static final String ACTION_FINISH_TEST_ACTIVITY =
100 INSTRUMENTATION_PACKAGE + ".action.FINISH_TEST_ACTIVITY";
101 public static final String EXTRA_RECEIVED_PACKAGE_NAME =
102 SuspendPackagesTest.INSTRUMENTATION_PACKAGE + ".extra.RECEIVED_PACKAGE_NAME";
103
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700104
Suprabh Shukla021b57a2018-03-08 18:21:50 -0800105 private Context mContext;
106 private PackageManager mPackageManager;
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700107 private LauncherApps mLauncherApps;
Suprabh Shukla021b57a2018-03-08 18:21:50 -0800108 private Handler mReceiverHandler;
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700109 private AppCommunicationReceiver mAppCommsReceiver;
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700110 private StubbedCallback mTestCallback;
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700111 private UiDevice mUiDevice;
Suprabh Shukla77e22452018-05-22 18:02:37 -0700112 private ComponentName mDeviceAdminComponent;
113 private boolean mPoSet;
114 private boolean mDoSet;
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700115
116 private static final class AppCommunicationReceiver extends BroadcastReceiver {
117 private Context context;
118 private boolean registered;
119 private SynchronousQueue<Intent> intentQueue = new SynchronousQueue<>();
120
121 AppCommunicationReceiver(Context context) {
122 this.context = context;
123 }
124
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700125 void register(Handler handler, String... actions) {
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700126 registered = true;
127 final IntentFilter intentFilter = new IntentFilter();
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700128 for (String action : actions) {
129 intentFilter.addAction(action);
130 }
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700131 context.registerReceiver(this, intentFilter, null, handler);
132 }
133
134 void unregister() {
135 if (registered) {
136 context.unregisterReceiver(this);
137 }
138 }
139
140 @Override
141 public void onReceive(Context context, Intent intent) {
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700142 Log.d(TAG, "AppCommunicationReceiver#onReceive: " + intent.getAction());
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700143 try {
144 intentQueue.offer(intent, 5, TimeUnit.SECONDS);
145 } catch (InterruptedException ie) {
146 throw new RuntimeException("Receiver thread interrupted", ie);
147 }
148 }
149
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700150 Intent pollForIntent(long secondsToWait) {
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700151 if (!registered) {
152 throw new IllegalStateException("Receiver not registered");
153 }
154 final Intent intent;
155 try {
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700156 intent = intentQueue.poll(secondsToWait, TimeUnit.SECONDS);
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700157 } catch (InterruptedException ie) {
158 throw new RuntimeException("Interrupted while waiting for app broadcast", ie);
159 }
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700160 return intent;
161 }
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700162
163 void drainPendingBroadcasts() {
Suprabh Shukla389cb6f2018-10-01 18:20:39 -0700164 while (pollForIntent(5) != null) ;
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700165 }
166
167 Intent receiveIntentFromApp() {
168 final Intent intentReceived = pollForIntent(5);
169 assertNotNull("No intent received from app within 5 seconds", intentReceived);
170 return intentReceived;
171 }
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700172 }
Suprabh Shukla021b57a2018-03-08 18:21:50 -0800173
174 @Before
175 public void setUp() {
176 mContext = InstrumentationRegistry.getTargetContext();
177 mPackageManager = mContext.getPackageManager();
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700178 mLauncherApps = (LauncherApps) mContext.getSystemService(Context.LAUNCHER_APPS_SERVICE);
Suprabh Shukla021b57a2018-03-08 18:21:50 -0800179 mReceiverHandler = new Handler(Looper.getMainLooper());
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700180 mUiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
Suprabh Shukla77e22452018-05-22 18:02:37 -0700181 mDeviceAdminComponent = new ComponentName(mContext,
182 "com.android.server.devicepolicy.DummyDeviceAdmins$Admin1");
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700183 IPackageManager ipm = AppGlobals.getPackageManager();
184 try {
185 // Otherwise implicit broadcasts will not be delivered.
186 ipm.setPackageStoppedState(TEST_APP_PACKAGE_NAME, false, mContext.getUserId());
187 } catch (RemoteException e) {
188 e.rethrowAsRuntimeException();
189 }
190 unsuspendTestPackage();
191 mAppCommsReceiver = new AppCommunicationReceiver(mContext);
Suprabh Shukla021b57a2018-03-08 18:21:50 -0800192 }
193
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700194 /**
195 * Care should be taken when used with {@link #mAppCommsReceiver} in the same test as both use
196 * the same handler.
197 */
Suprabh Shukla021b57a2018-03-08 18:21:50 -0800198 private Bundle requestAppAction(String action) throws InterruptedException {
199 final AtomicReference<Bundle> result = new AtomicReference<>();
200 final CountDownLatch receiverLatch = new CountDownLatch(1);
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700201 final ComponentName testReceiverComponent = new ComponentName(TEST_APP_PACKAGE_NAME,
202 SuspendTestReceiver.class.getCanonicalName());
Suprabh Shukla021b57a2018-03-08 18:21:50 -0800203 final Intent broadcastIntent = new Intent(action)
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700204 .setComponent(testReceiverComponent)
Suprabh Shukla021b57a2018-03-08 18:21:50 -0800205 .setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
206 mContext.sendOrderedBroadcast(broadcastIntent, null, new BroadcastReceiver() {
207 @Override
208 public void onReceive(Context context, Intent intent) {
209 result.set(getResultExtras(true));
210 receiverLatch.countDown();
211 }
212 }, mReceiverHandler, 0, null, null);
213
214 assertTrue("Test receiver timed out ", receiverLatch.await(5, TimeUnit.SECONDS));
215 return result.get();
216 }
217
218 private PersistableBundle getExtras(String keyPrefix, long lval, String sval, double dval) {
219 final PersistableBundle extras = new PersistableBundle(3);
220 extras.putLong(keyPrefix + ".LONG_VALUE", lval);
221 extras.putDouble(keyPrefix + ".DOUBLE_VALUE", dval);
222 extras.putString(keyPrefix + ".STRING_VALUE", sval);
223 return extras;
224 }
225
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700226 private void suspendTestPackage(PersistableBundle appExtras, PersistableBundle launcherExtras,
Suprabh Shukla389cb6f2018-10-01 18:20:39 -0700227 SuspendDialogInfo dialogInfo) {
Suprabh Shukla021b57a2018-03-08 18:21:50 -0800228 final String[] unchangedPackages = mPackageManager.setPackagesSuspended(
Suprabh Shukla389cb6f2018-10-01 18:20:39 -0700229 PACKAGES_TO_SUSPEND, true, appExtras, launcherExtras, dialogInfo);
Suprabh Shukla021b57a2018-03-08 18:21:50 -0800230 assertTrue("setPackagesSuspended returned non-empty list", unchangedPackages.length == 0);
231 }
232
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700233 private void unsuspendTestPackage() {
234 final String[] unchangedPackages = mPackageManager.setPackagesSuspended(
Suprabh Shukla389cb6f2018-10-01 18:20:39 -0700235 PACKAGES_TO_SUSPEND, false, null, null, (SuspendDialogInfo) null);
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700236 assertTrue("setPackagesSuspended returned non-empty list", unchangedPackages.length == 0);
237 }
238
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700239 private void startTestAppActivity() {
240 final Intent testActivity = new Intent()
241 .setComponent(new ComponentName(TEST_APP_PACKAGE_NAME,
242 SuspendTestActivity.class.getCanonicalName()))
243 .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
244 mContext.startActivity(testActivity);
245 }
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700246
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700247 private static boolean areSameExtras(BaseBundle expected, BaseBundle received) {
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700248 if (expected != null) {
249 expected.get(""); // hack to unparcel the bundles.
250 }
251 if (received != null) {
252 received.get("");
253 }
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700254 return BaseBundle.kindofEquals(expected, received);
255 }
256
257 private static void assertSameExtras(String message, BaseBundle expected, BaseBundle received) {
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700258 if (!areSameExtras(expected, received)) {
259 fail(message + ": [expected: " + expected + "; received: " + received + "]");
260 }
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700261 }
262
Suprabh Shukla021b57a2018-03-08 18:21:50 -0800263 @Test
Suprabh Shukla96212bc2018-04-10 15:04:51 -0700264 public void testIsPackageSuspended() throws Exception {
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700265 suspendTestPackage(null, null, null);
Suprabh Shukla021b57a2018-03-08 18:21:50 -0800266 assertTrue("isPackageSuspended is false",
267 mPackageManager.isPackageSuspended(TEST_APP_PACKAGE_NAME));
268 }
269
270 @Test
271 public void testSuspendedStateFromApp() throws Exception {
272 Bundle resultFromApp = requestAppAction(SuspendTestReceiver.ACTION_GET_SUSPENDED_STATE);
273 assertFalse(resultFromApp.getBoolean(SuspendTestReceiver.EXTRA_SUSPENDED, true));
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700274 assertNull(resultFromApp.getBundle(SuspendTestReceiver.EXTRA_SUSPENDED_APP_EXTRAS));
Suprabh Shukla021b57a2018-03-08 18:21:50 -0800275
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700276 final PersistableBundle appExtras = getExtras("testSuspendedStateFromApp", 20, "20", 0.2);
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700277 suspendTestPackage(appExtras, null, null);
Suprabh Shukla021b57a2018-03-08 18:21:50 -0800278
279 resultFromApp = requestAppAction(SuspendTestReceiver.ACTION_GET_SUSPENDED_STATE);
280 assertTrue("resultFromApp:suspended is false",
281 resultFromApp.getBoolean(SuspendTestReceiver.EXTRA_SUSPENDED));
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700282 final Bundle receivedAppExtras =
283 resultFromApp.getBundle(SuspendTestReceiver.EXTRA_SUSPENDED_APP_EXTRAS);
284 assertSameExtras("Received app extras different to the ones supplied",
285 appExtras, receivedAppExtras);
286 }
287
288 @Test
289 public void testMyPackageSuspendedUnsuspended() {
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700290 mAppCommsReceiver.register(mReceiverHandler, ACTION_REPORT_MY_PACKAGE_SUSPENDED,
291 ACTION_REPORT_MY_PACKAGE_UNSUSPENDED);
292 mAppCommsReceiver.drainPendingBroadcasts();
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700293 final PersistableBundle appExtras = getExtras("testMyPackageSuspendBroadcasts", 1, "1", .1);
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700294 suspendTestPackage(appExtras, null, null);
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700295 Intent intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700296 assertEquals("MY_PACKAGE_SUSPENDED delivery not reported",
297 ACTION_REPORT_MY_PACKAGE_SUSPENDED, intentFromApp.getAction());
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700298 assertSameExtras("Received app extras different to the ones supplied", appExtras,
299 intentFromApp.getBundleExtra(SuspendTestReceiver.EXTRA_SUSPENDED_APP_EXTRAS));
300 unsuspendTestPackage();
301 intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700302 assertEquals("MY_PACKAGE_UNSUSPENDED delivery not reported",
303 ACTION_REPORT_MY_PACKAGE_UNSUSPENDED, intentFromApp.getAction());
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700304 }
305
306 @Test
307 public void testUpdatingAppExtras() {
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700308 mAppCommsReceiver.register(mReceiverHandler, ACTION_REPORT_MY_PACKAGE_SUSPENDED);
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700309 final PersistableBundle extras1 = getExtras("testMyPackageSuspendedOnChangingExtras", 1,
310 "1", 0.1);
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700311 suspendTestPackage(extras1, null, null);
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700312 Intent intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700313 assertEquals("MY_PACKAGE_SUSPENDED delivery not reported",
314 ACTION_REPORT_MY_PACKAGE_SUSPENDED, intentFromApp.getAction());
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700315 assertSameExtras("Received app extras different to the ones supplied", extras1,
316 intentFromApp.getBundleExtra(SuspendTestReceiver.EXTRA_SUSPENDED_APP_EXTRAS));
317 final PersistableBundle extras2 = getExtras("testMyPackageSuspendedOnChangingExtras", 2,
318 "2", 0.2);
Suprabh Shukla45b9e402018-04-09 17:33:53 -0700319 suspendTestPackage(extras2, null, null);
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700320 intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700321 assertEquals("MY_PACKAGE_SUSPENDED delivery not reported",
322 ACTION_REPORT_MY_PACKAGE_SUSPENDED, intentFromApp.getAction());
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700323 assertSameExtras("Received app extras different to the updated extras", extras2,
324 intentFromApp.getBundleExtra(SuspendTestReceiver.EXTRA_SUSPENDED_APP_EXTRAS));
325 }
326
327 @Test
328 public void testCannotSuspendSelf() {
329 final String[] unchangedPkgs = mPackageManager.setPackagesSuspended(
Suprabh Shukla389cb6f2018-10-01 18:20:39 -0700330 new String[]{mContext.getOpPackageName()}, true, null, null,
331 (SuspendDialogInfo) null);
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700332 assertTrue(unchangedPkgs.length == 1);
333 assertEquals(mContext.getOpPackageName(), unchangedPkgs[0]);
334 }
335
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700336 @Test
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700337 public void testActivityStoppedOnSuspend() {
338 mAppCommsReceiver.register(mReceiverHandler, ACTION_REPORT_TEST_ACTIVITY_STARTED,
339 ACTION_REPORT_TEST_ACTIVITY_STOPPED);
340 startTestAppActivity();
341 Intent intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
342 assertEquals("Test activity start not reported",
343 ACTION_REPORT_TEST_ACTIVITY_STARTED, intentFromApp.getAction());
344 suspendTestPackage(null, null, null);
345 intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
346 assertEquals("Test activity stop not reported on suspending the test app",
347 ACTION_REPORT_TEST_ACTIVITY_STOPPED, intentFromApp.getAction());
348 }
349
350 @Test
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700351 public void testGetLauncherExtrasNonNull() {
352 final Bundle extrasWhenUnsuspended = mLauncherApps.getSuspendedPackageLauncherExtras(
353 TEST_APP_PACKAGE_NAME, mContext.getUser());
354 assertNull("Non null extras when package unsuspended:", extrasWhenUnsuspended);
355 final PersistableBundle launcherExtras = getExtras("testGetLauncherExtras", 1, "1", 0.1);
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700356 suspendTestPackage(null, launcherExtras, null);
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700357 final Bundle receivedExtras = mLauncherApps.getSuspendedPackageLauncherExtras(
358 TEST_APP_PACKAGE_NAME, mContext.getUser());
359 assertSameExtras("Received launcher extras different to the ones supplied", launcherExtras,
360 receivedExtras);
361 }
362
363 @Test
364 public void testGetLauncherExtrasNull() {
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700365 suspendTestPackage(null, null, null);
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700366 final Bundle extrasWhenNoneGiven = mLauncherApps.getSuspendedPackageLauncherExtras(
367 TEST_APP_PACKAGE_NAME, mContext.getUser());
368 assertNull("Non null extras when null extras provided:", extrasWhenNoneGiven);
369 }
370
371 @Test
372 public void testGetLauncherExtrasInvalidPackage() {
373 final Bundle extrasForInvalidPackage = mLauncherApps.getSuspendedPackageLauncherExtras(
374 "test.nonexistent.packagename", mContext.getUser());
375 assertNull("Non null extras for an invalid package:", extrasForInvalidPackage);
376 }
377
378 @Test
379 public void testOnPackagesSuspendedNewAndOld() throws InterruptedException {
380 final PersistableBundle suppliedExtras = getExtras(
381 "testOnPackagesSuspendedNewAndOld", 2, "2", 0.2);
382 final AtomicReference<String> overridingBothCallbackResult = new AtomicReference<>("");
383 final CountDownLatch twoCallbackLatch = new CountDownLatch(2);
384 mTestCallback = new StubbedCallback() {
385 @Override
386 public void onPackagesSuspended(String[] packageNames, UserHandle user) {
387 overridingBothCallbackResult.set(overridingBothCallbackResult.get()
388 + "Old callback called even when the new one is overriden. ");
389 twoCallbackLatch.countDown();
390 }
391
392 @Override
Suprabh Shukla96212bc2018-04-10 15:04:51 -0700393 public void onPackagesSuspended(String[] packageNames, UserHandle user,
394 Bundle launcherExtras) {
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700395 final StringBuilder errorString = new StringBuilder();
396 if (!Arrays.equals(packageNames, PACKAGES_TO_SUSPEND)) {
397 errorString.append("Received unexpected packageNames in onPackagesSuspended:");
398 for (String packageName : packageNames) {
399 errorString.append(" " + packageName);
400 }
401 errorString.append(". ");
402 }
403 if (user.getIdentifier() != mContext.getUserId()) {
404 errorString.append("Received wrong user " + user.getIdentifier() + ". ");
405 }
406 if (!areSameExtras(launcherExtras, suppliedExtras)) {
407 errorString.append("Unexpected launcherExtras, supplied: " + suppliedExtras
408 + ", received: " + launcherExtras + ". ");
409 }
410 overridingBothCallbackResult.set(overridingBothCallbackResult.get()
411 + errorString.toString());
412 twoCallbackLatch.countDown();
413 }
414 };
415 mLauncherApps.registerCallback(mTestCallback, mReceiverHandler);
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700416 suspendTestPackage(null, suppliedExtras, null);
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700417 assertFalse("Both callbacks were invoked", twoCallbackLatch.await(5, TimeUnit.SECONDS));
418 twoCallbackLatch.countDown();
419 assertTrue("No callback was invoked", twoCallbackLatch.await(2, TimeUnit.SECONDS));
420 final String result = overridingBothCallbackResult.get();
421 assertTrue("Callbacks did not complete as expected: " + result, result.isEmpty());
422 }
423
424 @Test
425 public void testOnPackagesSuspendedOld() throws InterruptedException {
426 final PersistableBundle suppliedExtras = getExtras(
427 "testOnPackagesSuspendedOld", 2, "2", 0.2);
428 final AtomicReference<String> overridingOneCallbackResult = new AtomicReference<>("");
429 final CountDownLatch oneCallbackLatch = new CountDownLatch(1);
430 mTestCallback = new StubbedCallback() {
431 @Override
432 public void onPackagesSuspended(String[] packageNames, UserHandle user) {
433 final StringBuilder errorString = new StringBuilder();
434 if (!Arrays.equals(packageNames, PACKAGES_TO_SUSPEND)) {
435 errorString.append("Received unexpected packageNames in onPackagesSuspended:");
436 for (String packageName : packageNames) {
437 errorString.append(" " + packageName);
438 }
439 errorString.append(". ");
440 }
441 if (user.getIdentifier() != mContext.getUserId()) {
442 errorString.append("Received wrong user " + user.getIdentifier() + ". ");
443 }
444 overridingOneCallbackResult.set(overridingOneCallbackResult.get()
445 + errorString.toString());
446 oneCallbackLatch.countDown();
447 }
448 };
449 mLauncherApps.registerCallback(mTestCallback, mReceiverHandler);
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700450 suspendTestPackage(null, suppliedExtras, null);
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700451 assertTrue("Callback not invoked", oneCallbackLatch.await(5, TimeUnit.SECONDS));
452 final String result = overridingOneCallbackResult.get();
453 assertTrue("Callback did not complete as expected: " + result, result.isEmpty());
454 }
455
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700456 private void turnScreenOn() throws Exception {
457 if (!mUiDevice.isScreenOn()) {
458 mUiDevice.wakeUp();
459 }
460 final IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
461 wm.dismissKeyguard(null, null);
462 }
463
464 @Test
465 public void testInterceptorActivity() throws Exception {
466 turnScreenOn();
467 mAppCommsReceiver.register(mReceiverHandler, ACTION_REPORT_MORE_DETAILS_ACTIVITY_STARTED,
468 ACTION_REPORT_TEST_ACTIVITY_STARTED);
Suprabh Shuklac401f152018-04-10 17:07:32 -0700469 final String testMessage = "This is a test message to report suspension of %1$s";
Suprabh Shukla389cb6f2018-10-01 18:20:39 -0700470 suspendTestPackage(null, null,
471 new SuspendDialogInfo.Builder().setMessage(testMessage).build());
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700472 startTestAppActivity();
473 assertNull("No broadcast was expected from app", mAppCommsReceiver.pollForIntent(2));
Suprabh Shuklac401f152018-04-10 17:07:32 -0700474 assertNotNull("Given dialog message not shown", mUiDevice.wait(
475 Until.findObject(By.text(String.format(testMessage, TEST_APP_LABEL))), 5000));
476 final String buttonText = mContext.getResources().getString(Resources.getSystem()
477 .getIdentifier("app_suspended_more_details", "string", "android"));
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700478 final UiObject2 moreDetailsButton = mUiDevice.findObject(
479 By.clickable(true).text(buttonText));
Suprabh Shuklac401f152018-04-10 17:07:32 -0700480 assertNotNull(buttonText + " button not shown", moreDetailsButton);
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700481 moreDetailsButton.click();
482 final Intent intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
Suprabh Shuklac401f152018-04-10 17:07:32 -0700483 assertEquals(buttonText + " activity start not reported",
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700484 ACTION_REPORT_MORE_DETAILS_ACTIVITY_STARTED, intentFromApp.getAction());
485 final String receivedPackageName = intentFromApp.getStringExtra(
486 EXTRA_RECEIVED_PACKAGE_NAME);
Suprabh Shuklac401f152018-04-10 17:07:32 -0700487 assertEquals("Wrong package name received by " + buttonText + " activity",
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700488 TEST_APP_PACKAGE_NAME, receivedPackageName);
489 }
490
Suprabh Shukla77e22452018-05-22 18:02:37 -0700491 private boolean setProfileOwner() throws IOException {
492 final String result = mUiDevice.executeShellCommand("dpm set-profile-owner --user cur "
493 + mDeviceAdminComponent.flattenToString());
494 return mPoSet = result.trim().startsWith("Success");
495 }
496
497 private boolean setDeviceOwner() throws IOException {
498 final String result = mUiDevice.executeShellCommand("dpm set-device-owner --user cur "
499 + mDeviceAdminComponent.flattenToString());
500 return mDoSet = result.trim().startsWith("Success");
501 }
502
503 private void removeProfileOrDeviceOwner() throws IOException {
504 if (mPoSet || mDoSet) {
505 mUiDevice.executeShellCommand("dpm remove-active-admin --user cur "
506 + mDeviceAdminComponent.flattenToString());
507 mPoSet = mDoSet = false;
508 }
509 }
510
511 @Test
Jason Parks4e9335a2019-03-14 11:11:33 -0700512 public void testCanSuspendWhenProfileOwner() throws IOException {
Suprabh Shukla77e22452018-05-22 18:02:37 -0700513 assumeTrue(mPackageManager.hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN));
514 assertTrue("Profile-owner could not be set", setProfileOwner());
Jason Parks4e9335a2019-03-14 11:11:33 -0700515 suspendTestPackage(null, null, null);
Suprabh Shukla77e22452018-05-22 18:02:37 -0700516 }
517
518 @Test
Jason Parks4e9335a2019-03-14 11:11:33 -0700519 public void testCanSuspendWhenDeviceOwner() throws IOException {
Suprabh Shukla77e22452018-05-22 18:02:37 -0700520 assumeTrue(mPackageManager.hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN));
521 assertTrue("Device-owner could not be set", setDeviceOwner());
Jason Parks4e9335a2019-03-14 11:11:33 -0700522 suspendTestPackage(null, null, null);
Suprabh Shukla77e22452018-05-22 18:02:37 -0700523 }
524
525 @Test
526 public void testPackageUnsuspendedOnAddingDeviceOwner() throws IOException {
527 assumeTrue(mPackageManager.hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN));
528 mAppCommsReceiver.register(mReceiverHandler, ACTION_REPORT_MY_PACKAGE_UNSUSPENDED,
529 ACTION_REPORT_MY_PACKAGE_SUSPENDED);
530 mAppCommsReceiver.drainPendingBroadcasts();
531 suspendTestPackage(null, null, null);
532 Intent intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
533 assertEquals(ACTION_REPORT_MY_PACKAGE_SUSPENDED, intentFromApp.getAction());
534 assertTrue("Device-owner could not be set", setDeviceOwner());
535 intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
536 assertEquals(ACTION_REPORT_MY_PACKAGE_UNSUSPENDED, intentFromApp.getAction());
537 }
538
539 @Test
540 public void testPackageUnsuspendedOnAddingProfileOwner() throws IOException {
541 assumeTrue(mPackageManager.hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN));
542 mAppCommsReceiver.register(mReceiverHandler, ACTION_REPORT_MY_PACKAGE_UNSUSPENDED,
543 ACTION_REPORT_MY_PACKAGE_SUSPENDED);
544 mAppCommsReceiver.drainPendingBroadcasts();
545 suspendTestPackage(null, null, null);
546 Intent intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
547 assertEquals(ACTION_REPORT_MY_PACKAGE_SUSPENDED, intentFromApp.getAction());
548 assertTrue("Profile-owner could not be set", setProfileOwner());
549 intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
550 assertEquals(ACTION_REPORT_MY_PACKAGE_UNSUSPENDED, intentFromApp.getAction());
551 }
552
Suprabh Shukla3017fe42018-11-08 19:00:01 -0800553 @Test
554 public void testAudioOpBlockedOnSuspend() throws Exception {
555 final IAppOpsService iAppOps = IAppOpsService.Stub.asInterface(
556 ServiceManager.getService(Context.APP_OPS_SERVICE));
557 final CountDownLatch latch = new CountDownLatch(1);
558 final IAppOpsCallback watcher = new IAppOpsCallback.Stub() {
559 @Override
560 public void opChanged(int op, int uid, String packageName) {
561 if (op == OP_PLAY_AUDIO && packageName.equals(TEST_APP_PACKAGE_NAME)) {
562 latch.countDown();
563 }
564 }
565 };
566 iAppOps.startWatchingMode(OP_PLAY_AUDIO, TEST_APP_PACKAGE_NAME, watcher);
567 final int testPackageUid = mPackageManager.getPackageUid(TEST_APP_PACKAGE_NAME, 0);
568 int audioOpMode = iAppOps.checkAudioOperation(OP_PLAY_AUDIO,
569 AudioAttributes.USAGE_UNKNOWN, testPackageUid, TEST_APP_PACKAGE_NAME);
570 assertEquals("Audio muted for unsuspended package", MODE_ALLOWED, audioOpMode);
571 suspendTestPackage(null, null, null);
572 assertTrue("AppOpsWatcher did not callback", latch.await(5, TimeUnit.SECONDS));
573 audioOpMode = iAppOps.checkAudioOperation(OP_PLAY_AUDIO,
574 AudioAttributes.USAGE_UNKNOWN, testPackageUid, TEST_APP_PACKAGE_NAME);
575 assertEquals("Audio not muted for suspended package", MODE_IGNORED, audioOpMode);
576 iAppOps.stopWatchingMode(watcher);
577 }
578
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700579 @After
Suprabh Shukla77e22452018-05-22 18:02:37 -0700580 public void tearDown() throws IOException {
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700581 mAppCommsReceiver.unregister();
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700582 if (mTestCallback != null) {
583 mLauncherApps.unregisterCallback(mTestCallback);
584 }
Suprabh Shukla77e22452018-05-22 18:02:37 -0700585 removeProfileOrDeviceOwner();
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700586 mContext.sendBroadcast(new Intent(ACTION_FINISH_TEST_ACTIVITY)
587 .setPackage(TEST_APP_PACKAGE_NAME));
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700588 }
589
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700590 private static abstract class StubbedCallback extends LauncherApps.Callback {
591
592 @Override
593 public void onPackageRemoved(String packageName, UserHandle user) {
594 }
595
596 @Override
597 public void onPackageAdded(String packageName, UserHandle user) {
598 }
599
600 @Override
601 public void onPackageChanged(String packageName, UserHandle user) {
602 }
603
604 @Override
605 public void onPackagesAvailable(String[] packageNames, UserHandle user, boolean replacing) {
606
607 }
608
609 @Override
610 public void onPackagesUnavailable(String[] packageNames, UserHandle user,
611 boolean replacing) {
612 }
Suprabh Shukla021b57a2018-03-08 18:21:50 -0800613 }
614}