blob: c186e48e8794d90719d4d8848229003daf6a0baa [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 Shukla2fd43ba2018-03-22 16:57:49 -070019import static org.junit.Assert.assertEquals;
Suprabh Shukla021b57a2018-03-08 18:21:50 -080020import static org.junit.Assert.assertFalse;
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -070021import static org.junit.Assert.assertNotNull;
Suprabh Shukla021b57a2018-03-08 18:21:50 -080022import static org.junit.Assert.assertNull;
23import static org.junit.Assert.assertTrue;
Suprabh Shukla3c3af142018-03-30 00:28:37 -070024import static org.junit.Assert.fail;
Suprabh Shukla77e22452018-05-22 18:02:37 -070025import static org.junit.Assume.assumeTrue;
Suprabh Shukla021b57a2018-03-08 18:21:50 -080026
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -070027import android.app.AppGlobals;
Suprabh Shukla021b57a2018-03-08 18:21:50 -080028import android.content.BroadcastReceiver;
29import android.content.ComponentName;
30import android.content.Context;
31import android.content.Intent;
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -070032import android.content.IntentFilter;
33import android.content.pm.IPackageManager;
Suprabh Shukla19b41f32018-03-26 22:35:13 -070034import android.content.pm.LauncherApps;
Suprabh Shukla021b57a2018-03-08 18:21:50 -080035import android.content.pm.PackageManager;
Suprabh Shuklac401f152018-04-10 17:07:32 -070036import android.content.res.Resources;
Suprabh Shukla021b57a2018-03-08 18:21:50 -080037import android.os.BaseBundle;
38import android.os.Bundle;
39import android.os.Handler;
40import android.os.Looper;
41import android.os.PersistableBundle;
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -070042import android.os.RemoteException;
Suprabh Shukla19b41f32018-03-26 22:35:13 -070043import android.os.UserHandle;
Suprabh Shukla021b57a2018-03-08 18:21:50 -080044import android.support.test.InstrumentationRegistry;
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -070045import android.support.test.filters.LargeTest;
Suprabh Shukla021b57a2018-03-08 18:21:50 -080046import android.support.test.runner.AndroidJUnit4;
Suprabh Shukla3c3af142018-03-30 00:28:37 -070047import android.support.test.uiautomator.By;
48import android.support.test.uiautomator.UiDevice;
49import android.support.test.uiautomator.UiObject2;
50import android.support.test.uiautomator.Until;
Suprabh Shukla19b41f32018-03-26 22:35:13 -070051import android.util.Log;
Suprabh Shukla3c3af142018-03-30 00:28:37 -070052import android.view.IWindowManager;
53import android.view.WindowManagerGlobal;
Suprabh Shukla021b57a2018-03-08 18:21:50 -080054
Suprabh Shukla3c3af142018-03-30 00:28:37 -070055import com.android.servicestests.apps.suspendtestapp.SuspendTestActivity;
Suprabh Shukla021b57a2018-03-08 18:21:50 -080056import com.android.servicestests.apps.suspendtestapp.SuspendTestReceiver;
57
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -070058import org.junit.After;
Suprabh Shukla021b57a2018-03-08 18:21:50 -080059import org.junit.Before;
60import org.junit.Test;
61import org.junit.runner.RunWith;
62
Suprabh Shukla77e22452018-05-22 18:02:37 -070063import java.io.IOException;
Suprabh Shukla19b41f32018-03-26 22:35:13 -070064import java.util.Arrays;
Suprabh Shukla021b57a2018-03-08 18:21:50 -080065import java.util.concurrent.CountDownLatch;
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -070066import java.util.concurrent.SynchronousQueue;
Suprabh Shukla021b57a2018-03-08 18:21:50 -080067import java.util.concurrent.TimeUnit;
68import java.util.concurrent.atomic.AtomicReference;
69
70@RunWith(AndroidJUnit4.class)
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -070071@LargeTest
Suprabh Shukla021b57a2018-03-08 18:21:50 -080072public class SuspendPackagesTest {
Suprabh Shukla19b41f32018-03-26 22:35:13 -070073 private static final String TAG = SuspendPackagesTest.class.getSimpleName();
Suprabh Shuklac401f152018-04-10 17:07:32 -070074 private static final String TEST_APP_LABEL = "Suspend Test App";
Suprabh Shukla021b57a2018-03-08 18:21:50 -080075 private static final String TEST_APP_PACKAGE_NAME = SuspendTestReceiver.PACKAGE_NAME;
76 private static final String[] PACKAGES_TO_SUSPEND = new String[]{TEST_APP_PACKAGE_NAME};
77
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -070078 public static final String INSTRUMENTATION_PACKAGE = "com.android.frameworks.servicestests";
79 public static final String ACTION_REPORT_MY_PACKAGE_SUSPENDED =
80 INSTRUMENTATION_PACKAGE + ".action.REPORT_MY_PACKAGE_SUSPENDED";
81 public static final String ACTION_REPORT_MY_PACKAGE_UNSUSPENDED =
82 INSTRUMENTATION_PACKAGE + ".action.REPORT_MY_PACKAGE_UNSUSPENDED";
Suprabh Shukla3c3af142018-03-30 00:28:37 -070083 public static final String ACTION_REPORT_TEST_ACTIVITY_STARTED =
84 INSTRUMENTATION_PACKAGE + ".action.REPORT_TEST_ACTIVITY_STARTED";
85 public static final String ACTION_REPORT_TEST_ACTIVITY_STOPPED =
86 INSTRUMENTATION_PACKAGE + ".action.REPORT_TEST_ACTIVITY_STOPPED";
87 public static final String ACTION_REPORT_MORE_DETAILS_ACTIVITY_STARTED =
88 INSTRUMENTATION_PACKAGE + ".action.REPORT_MORE_DETAILS_ACTIVITY_STARTED";
89 public static final String ACTION_FINISH_TEST_ACTIVITY =
90 INSTRUMENTATION_PACKAGE + ".action.FINISH_TEST_ACTIVITY";
91 public static final String EXTRA_RECEIVED_PACKAGE_NAME =
92 SuspendPackagesTest.INSTRUMENTATION_PACKAGE + ".extra.RECEIVED_PACKAGE_NAME";
93
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -070094
Suprabh Shukla021b57a2018-03-08 18:21:50 -080095 private Context mContext;
96 private PackageManager mPackageManager;
Suprabh Shukla19b41f32018-03-26 22:35:13 -070097 private LauncherApps mLauncherApps;
Suprabh Shukla021b57a2018-03-08 18:21:50 -080098 private Handler mReceiverHandler;
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -070099 private AppCommunicationReceiver mAppCommsReceiver;
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700100 private StubbedCallback mTestCallback;
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700101 private UiDevice mUiDevice;
Suprabh Shukla77e22452018-05-22 18:02:37 -0700102 private ComponentName mDeviceAdminComponent;
103 private boolean mPoSet;
104 private boolean mDoSet;
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700105
106 private static final class AppCommunicationReceiver extends BroadcastReceiver {
107 private Context context;
108 private boolean registered;
109 private SynchronousQueue<Intent> intentQueue = new SynchronousQueue<>();
110
111 AppCommunicationReceiver(Context context) {
112 this.context = context;
113 }
114
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700115 void register(Handler handler, String... actions) {
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700116 registered = true;
117 final IntentFilter intentFilter = new IntentFilter();
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700118 for (String action : actions) {
119 intentFilter.addAction(action);
120 }
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700121 context.registerReceiver(this, intentFilter, null, handler);
122 }
123
124 void unregister() {
125 if (registered) {
126 context.unregisterReceiver(this);
127 }
128 }
129
130 @Override
131 public void onReceive(Context context, Intent intent) {
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700132 Log.d(TAG, "AppCommunicationReceiver#onReceive: " + intent.getAction());
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700133 try {
134 intentQueue.offer(intent, 5, TimeUnit.SECONDS);
135 } catch (InterruptedException ie) {
136 throw new RuntimeException("Receiver thread interrupted", ie);
137 }
138 }
139
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700140 Intent pollForIntent(long secondsToWait) {
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700141 if (!registered) {
142 throw new IllegalStateException("Receiver not registered");
143 }
144 final Intent intent;
145 try {
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700146 intent = intentQueue.poll(secondsToWait, TimeUnit.SECONDS);
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700147 } catch (InterruptedException ie) {
148 throw new RuntimeException("Interrupted while waiting for app broadcast", ie);
149 }
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700150 return intent;
151 }
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700152
153 void drainPendingBroadcasts() {
154 while (pollForIntent(5) != null);
155 }
156
157 Intent receiveIntentFromApp() {
158 final Intent intentReceived = pollForIntent(5);
159 assertNotNull("No intent received from app within 5 seconds", intentReceived);
160 return intentReceived;
161 }
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700162 }
Suprabh Shukla021b57a2018-03-08 18:21:50 -0800163
164 @Before
165 public void setUp() {
166 mContext = InstrumentationRegistry.getTargetContext();
167 mPackageManager = mContext.getPackageManager();
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700168 mLauncherApps = (LauncherApps) mContext.getSystemService(Context.LAUNCHER_APPS_SERVICE);
Suprabh Shukla021b57a2018-03-08 18:21:50 -0800169 mReceiverHandler = new Handler(Looper.getMainLooper());
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700170 mUiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
Suprabh Shukla77e22452018-05-22 18:02:37 -0700171 mDeviceAdminComponent = new ComponentName(mContext,
172 "com.android.server.devicepolicy.DummyDeviceAdmins$Admin1");
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700173 IPackageManager ipm = AppGlobals.getPackageManager();
174 try {
175 // Otherwise implicit broadcasts will not be delivered.
176 ipm.setPackageStoppedState(TEST_APP_PACKAGE_NAME, false, mContext.getUserId());
177 } catch (RemoteException e) {
178 e.rethrowAsRuntimeException();
179 }
180 unsuspendTestPackage();
181 mAppCommsReceiver = new AppCommunicationReceiver(mContext);
Suprabh Shukla021b57a2018-03-08 18:21:50 -0800182 }
183
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700184 /**
185 * Care should be taken when used with {@link #mAppCommsReceiver} in the same test as both use
186 * the same handler.
187 */
Suprabh Shukla021b57a2018-03-08 18:21:50 -0800188 private Bundle requestAppAction(String action) throws InterruptedException {
189 final AtomicReference<Bundle> result = new AtomicReference<>();
190 final CountDownLatch receiverLatch = new CountDownLatch(1);
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700191 final ComponentName testReceiverComponent = new ComponentName(TEST_APP_PACKAGE_NAME,
192 SuspendTestReceiver.class.getCanonicalName());
Suprabh Shukla021b57a2018-03-08 18:21:50 -0800193 final Intent broadcastIntent = new Intent(action)
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700194 .setComponent(testReceiverComponent)
Suprabh Shukla021b57a2018-03-08 18:21:50 -0800195 .setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
196 mContext.sendOrderedBroadcast(broadcastIntent, null, new BroadcastReceiver() {
197 @Override
198 public void onReceive(Context context, Intent intent) {
199 result.set(getResultExtras(true));
200 receiverLatch.countDown();
201 }
202 }, mReceiverHandler, 0, null, null);
203
204 assertTrue("Test receiver timed out ", receiverLatch.await(5, TimeUnit.SECONDS));
205 return result.get();
206 }
207
208 private PersistableBundle getExtras(String keyPrefix, long lval, String sval, double dval) {
209 final PersistableBundle extras = new PersistableBundle(3);
210 extras.putLong(keyPrefix + ".LONG_VALUE", lval);
211 extras.putDouble(keyPrefix + ".DOUBLE_VALUE", dval);
212 extras.putString(keyPrefix + ".STRING_VALUE", sval);
213 return extras;
214 }
215
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700216 private void suspendTestPackage(PersistableBundle appExtras, PersistableBundle launcherExtras,
217 String dialogMessage) {
Suprabh Shukla021b57a2018-03-08 18:21:50 -0800218 final String[] unchangedPackages = mPackageManager.setPackagesSuspended(
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700219 PACKAGES_TO_SUSPEND, true, appExtras, launcherExtras, dialogMessage);
Suprabh Shukla021b57a2018-03-08 18:21:50 -0800220 assertTrue("setPackagesSuspended returned non-empty list", unchangedPackages.length == 0);
221 }
222
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700223 private void unsuspendTestPackage() {
224 final String[] unchangedPackages = mPackageManager.setPackagesSuspended(
225 PACKAGES_TO_SUSPEND, false, null, null, null);
226 assertTrue("setPackagesSuspended returned non-empty list", unchangedPackages.length == 0);
227 }
228
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700229 private void startTestAppActivity() {
230 final Intent testActivity = new Intent()
231 .setComponent(new ComponentName(TEST_APP_PACKAGE_NAME,
232 SuspendTestActivity.class.getCanonicalName()))
233 .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
234 mContext.startActivity(testActivity);
235 }
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700236
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700237 private static boolean areSameExtras(BaseBundle expected, BaseBundle received) {
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700238 if (expected != null) {
239 expected.get(""); // hack to unparcel the bundles.
240 }
241 if (received != null) {
242 received.get("");
243 }
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700244 return BaseBundle.kindofEquals(expected, received);
245 }
246
247 private static void assertSameExtras(String message, BaseBundle expected, BaseBundle received) {
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700248 if (!areSameExtras(expected, received)) {
249 fail(message + ": [expected: " + expected + "; received: " + received + "]");
250 }
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700251 }
252
Suprabh Shukla021b57a2018-03-08 18:21:50 -0800253 @Test
Suprabh Shukla96212bc2018-04-10 15:04:51 -0700254 public void testIsPackageSuspended() throws Exception {
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700255 suspendTestPackage(null, null, null);
Suprabh Shukla021b57a2018-03-08 18:21:50 -0800256 assertTrue("isPackageSuspended is false",
257 mPackageManager.isPackageSuspended(TEST_APP_PACKAGE_NAME));
258 }
259
260 @Test
261 public void testSuspendedStateFromApp() throws Exception {
262 Bundle resultFromApp = requestAppAction(SuspendTestReceiver.ACTION_GET_SUSPENDED_STATE);
263 assertFalse(resultFromApp.getBoolean(SuspendTestReceiver.EXTRA_SUSPENDED, true));
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700264 assertNull(resultFromApp.getBundle(SuspendTestReceiver.EXTRA_SUSPENDED_APP_EXTRAS));
Suprabh Shukla021b57a2018-03-08 18:21:50 -0800265
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700266 final PersistableBundle appExtras = getExtras("testSuspendedStateFromApp", 20, "20", 0.2);
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700267 suspendTestPackage(appExtras, null, null);
Suprabh Shukla021b57a2018-03-08 18:21:50 -0800268
269 resultFromApp = requestAppAction(SuspendTestReceiver.ACTION_GET_SUSPENDED_STATE);
270 assertTrue("resultFromApp:suspended is false",
271 resultFromApp.getBoolean(SuspendTestReceiver.EXTRA_SUSPENDED));
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700272 final Bundle receivedAppExtras =
273 resultFromApp.getBundle(SuspendTestReceiver.EXTRA_SUSPENDED_APP_EXTRAS);
274 assertSameExtras("Received app extras different to the ones supplied",
275 appExtras, receivedAppExtras);
276 }
277
278 @Test
279 public void testMyPackageSuspendedUnsuspended() {
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700280 mAppCommsReceiver.register(mReceiverHandler, ACTION_REPORT_MY_PACKAGE_SUSPENDED,
281 ACTION_REPORT_MY_PACKAGE_UNSUSPENDED);
282 mAppCommsReceiver.drainPendingBroadcasts();
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700283 final PersistableBundle appExtras = getExtras("testMyPackageSuspendBroadcasts", 1, "1", .1);
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700284 suspendTestPackage(appExtras, null, null);
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700285 Intent intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700286 assertEquals("MY_PACKAGE_SUSPENDED delivery not reported",
287 ACTION_REPORT_MY_PACKAGE_SUSPENDED, intentFromApp.getAction());
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700288 assertSameExtras("Received app extras different to the ones supplied", appExtras,
289 intentFromApp.getBundleExtra(SuspendTestReceiver.EXTRA_SUSPENDED_APP_EXTRAS));
290 unsuspendTestPackage();
291 intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700292 assertEquals("MY_PACKAGE_UNSUSPENDED delivery not reported",
293 ACTION_REPORT_MY_PACKAGE_UNSUSPENDED, intentFromApp.getAction());
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700294 }
295
296 @Test
297 public void testUpdatingAppExtras() {
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700298 mAppCommsReceiver.register(mReceiverHandler, ACTION_REPORT_MY_PACKAGE_SUSPENDED);
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700299 final PersistableBundle extras1 = getExtras("testMyPackageSuspendedOnChangingExtras", 1,
300 "1", 0.1);
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700301 suspendTestPackage(extras1, null, null);
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700302 Intent intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700303 assertEquals("MY_PACKAGE_SUSPENDED delivery not reported",
304 ACTION_REPORT_MY_PACKAGE_SUSPENDED, intentFromApp.getAction());
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700305 assertSameExtras("Received app extras different to the ones supplied", extras1,
306 intentFromApp.getBundleExtra(SuspendTestReceiver.EXTRA_SUSPENDED_APP_EXTRAS));
307 final PersistableBundle extras2 = getExtras("testMyPackageSuspendedOnChangingExtras", 2,
308 "2", 0.2);
Suprabh Shukla45b9e402018-04-09 17:33:53 -0700309 suspendTestPackage(extras2, null, null);
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700310 intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700311 assertEquals("MY_PACKAGE_SUSPENDED delivery not reported",
312 ACTION_REPORT_MY_PACKAGE_SUSPENDED, intentFromApp.getAction());
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700313 assertSameExtras("Received app extras different to the updated extras", extras2,
314 intentFromApp.getBundleExtra(SuspendTestReceiver.EXTRA_SUSPENDED_APP_EXTRAS));
315 }
316
317 @Test
318 public void testCannotSuspendSelf() {
319 final String[] unchangedPkgs = mPackageManager.setPackagesSuspended(
320 new String[]{mContext.getOpPackageName()}, true, null, null, null);
321 assertTrue(unchangedPkgs.length == 1);
322 assertEquals(mContext.getOpPackageName(), unchangedPkgs[0]);
323 }
324
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700325 @Test
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700326 public void testActivityStoppedOnSuspend() {
327 mAppCommsReceiver.register(mReceiverHandler, ACTION_REPORT_TEST_ACTIVITY_STARTED,
328 ACTION_REPORT_TEST_ACTIVITY_STOPPED);
329 startTestAppActivity();
330 Intent intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
331 assertEquals("Test activity start not reported",
332 ACTION_REPORT_TEST_ACTIVITY_STARTED, intentFromApp.getAction());
333 suspendTestPackage(null, null, null);
334 intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
335 assertEquals("Test activity stop not reported on suspending the test app",
336 ACTION_REPORT_TEST_ACTIVITY_STOPPED, intentFromApp.getAction());
337 }
338
339 @Test
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700340 public void testGetLauncherExtrasNonNull() {
341 final Bundle extrasWhenUnsuspended = mLauncherApps.getSuspendedPackageLauncherExtras(
342 TEST_APP_PACKAGE_NAME, mContext.getUser());
343 assertNull("Non null extras when package unsuspended:", extrasWhenUnsuspended);
344 final PersistableBundle launcherExtras = getExtras("testGetLauncherExtras", 1, "1", 0.1);
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700345 suspendTestPackage(null, launcherExtras, null);
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700346 final Bundle receivedExtras = mLauncherApps.getSuspendedPackageLauncherExtras(
347 TEST_APP_PACKAGE_NAME, mContext.getUser());
348 assertSameExtras("Received launcher extras different to the ones supplied", launcherExtras,
349 receivedExtras);
350 }
351
352 @Test
353 public void testGetLauncherExtrasNull() {
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700354 suspendTestPackage(null, null, null);
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700355 final Bundle extrasWhenNoneGiven = mLauncherApps.getSuspendedPackageLauncherExtras(
356 TEST_APP_PACKAGE_NAME, mContext.getUser());
357 assertNull("Non null extras when null extras provided:", extrasWhenNoneGiven);
358 }
359
360 @Test
361 public void testGetLauncherExtrasInvalidPackage() {
362 final Bundle extrasForInvalidPackage = mLauncherApps.getSuspendedPackageLauncherExtras(
363 "test.nonexistent.packagename", mContext.getUser());
364 assertNull("Non null extras for an invalid package:", extrasForInvalidPackage);
365 }
366
367 @Test
368 public void testOnPackagesSuspendedNewAndOld() throws InterruptedException {
369 final PersistableBundle suppliedExtras = getExtras(
370 "testOnPackagesSuspendedNewAndOld", 2, "2", 0.2);
371 final AtomicReference<String> overridingBothCallbackResult = new AtomicReference<>("");
372 final CountDownLatch twoCallbackLatch = new CountDownLatch(2);
373 mTestCallback = new StubbedCallback() {
374 @Override
375 public void onPackagesSuspended(String[] packageNames, UserHandle user) {
376 overridingBothCallbackResult.set(overridingBothCallbackResult.get()
377 + "Old callback called even when the new one is overriden. ");
378 twoCallbackLatch.countDown();
379 }
380
381 @Override
Suprabh Shukla96212bc2018-04-10 15:04:51 -0700382 public void onPackagesSuspended(String[] packageNames, UserHandle user,
383 Bundle launcherExtras) {
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700384 final StringBuilder errorString = new StringBuilder();
385 if (!Arrays.equals(packageNames, PACKAGES_TO_SUSPEND)) {
386 errorString.append("Received unexpected packageNames in onPackagesSuspended:");
387 for (String packageName : packageNames) {
388 errorString.append(" " + packageName);
389 }
390 errorString.append(". ");
391 }
392 if (user.getIdentifier() != mContext.getUserId()) {
393 errorString.append("Received wrong user " + user.getIdentifier() + ". ");
394 }
395 if (!areSameExtras(launcherExtras, suppliedExtras)) {
396 errorString.append("Unexpected launcherExtras, supplied: " + suppliedExtras
397 + ", received: " + launcherExtras + ". ");
398 }
399 overridingBothCallbackResult.set(overridingBothCallbackResult.get()
400 + errorString.toString());
401 twoCallbackLatch.countDown();
402 }
403 };
404 mLauncherApps.registerCallback(mTestCallback, mReceiverHandler);
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700405 suspendTestPackage(null, suppliedExtras, null);
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700406 assertFalse("Both callbacks were invoked", twoCallbackLatch.await(5, TimeUnit.SECONDS));
407 twoCallbackLatch.countDown();
408 assertTrue("No callback was invoked", twoCallbackLatch.await(2, TimeUnit.SECONDS));
409 final String result = overridingBothCallbackResult.get();
410 assertTrue("Callbacks did not complete as expected: " + result, result.isEmpty());
411 }
412
413 @Test
414 public void testOnPackagesSuspendedOld() throws InterruptedException {
415 final PersistableBundle suppliedExtras = getExtras(
416 "testOnPackagesSuspendedOld", 2, "2", 0.2);
417 final AtomicReference<String> overridingOneCallbackResult = new AtomicReference<>("");
418 final CountDownLatch oneCallbackLatch = new CountDownLatch(1);
419 mTestCallback = new StubbedCallback() {
420 @Override
421 public void onPackagesSuspended(String[] packageNames, UserHandle user) {
422 final StringBuilder errorString = new StringBuilder();
423 if (!Arrays.equals(packageNames, PACKAGES_TO_SUSPEND)) {
424 errorString.append("Received unexpected packageNames in onPackagesSuspended:");
425 for (String packageName : packageNames) {
426 errorString.append(" " + packageName);
427 }
428 errorString.append(". ");
429 }
430 if (user.getIdentifier() != mContext.getUserId()) {
431 errorString.append("Received wrong user " + user.getIdentifier() + ". ");
432 }
433 overridingOneCallbackResult.set(overridingOneCallbackResult.get()
434 + errorString.toString());
435 oneCallbackLatch.countDown();
436 }
437 };
438 mLauncherApps.registerCallback(mTestCallback, mReceiverHandler);
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700439 suspendTestPackage(null, suppliedExtras, null);
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700440 assertTrue("Callback not invoked", oneCallbackLatch.await(5, TimeUnit.SECONDS));
441 final String result = overridingOneCallbackResult.get();
442 assertTrue("Callback did not complete as expected: " + result, result.isEmpty());
443 }
444
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700445 private void turnScreenOn() throws Exception {
446 if (!mUiDevice.isScreenOn()) {
447 mUiDevice.wakeUp();
448 }
449 final IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
450 wm.dismissKeyguard(null, null);
451 }
452
453 @Test
454 public void testInterceptorActivity() throws Exception {
455 turnScreenOn();
456 mAppCommsReceiver.register(mReceiverHandler, ACTION_REPORT_MORE_DETAILS_ACTIVITY_STARTED,
457 ACTION_REPORT_TEST_ACTIVITY_STARTED);
Suprabh Shuklac401f152018-04-10 17:07:32 -0700458 final String testMessage = "This is a test message to report suspension of %1$s";
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700459 suspendTestPackage(null, null, testMessage);
460 startTestAppActivity();
461 assertNull("No broadcast was expected from app", mAppCommsReceiver.pollForIntent(2));
Suprabh Shuklac401f152018-04-10 17:07:32 -0700462 assertNotNull("Given dialog message not shown", mUiDevice.wait(
463 Until.findObject(By.text(String.format(testMessage, TEST_APP_LABEL))), 5000));
464 final String buttonText = mContext.getResources().getString(Resources.getSystem()
465 .getIdentifier("app_suspended_more_details", "string", "android"));
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700466 final UiObject2 moreDetailsButton = mUiDevice.findObject(
467 By.clickable(true).text(buttonText));
Suprabh Shuklac401f152018-04-10 17:07:32 -0700468 assertNotNull(buttonText + " button not shown", moreDetailsButton);
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700469 moreDetailsButton.click();
470 final Intent intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
Suprabh Shuklac401f152018-04-10 17:07:32 -0700471 assertEquals(buttonText + " activity start not reported",
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700472 ACTION_REPORT_MORE_DETAILS_ACTIVITY_STARTED, intentFromApp.getAction());
473 final String receivedPackageName = intentFromApp.getStringExtra(
474 EXTRA_RECEIVED_PACKAGE_NAME);
Suprabh Shuklac401f152018-04-10 17:07:32 -0700475 assertEquals("Wrong package name received by " + buttonText + " activity",
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700476 TEST_APP_PACKAGE_NAME, receivedPackageName);
477 }
478
Suprabh Shukla77e22452018-05-22 18:02:37 -0700479 private boolean setProfileOwner() throws IOException {
480 final String result = mUiDevice.executeShellCommand("dpm set-profile-owner --user cur "
481 + mDeviceAdminComponent.flattenToString());
482 return mPoSet = result.trim().startsWith("Success");
483 }
484
485 private boolean setDeviceOwner() throws IOException {
486 final String result = mUiDevice.executeShellCommand("dpm set-device-owner --user cur "
487 + mDeviceAdminComponent.flattenToString());
488 return mDoSet = result.trim().startsWith("Success");
489 }
490
491 private void removeProfileOrDeviceOwner() throws IOException {
492 if (mPoSet || mDoSet) {
493 mUiDevice.executeShellCommand("dpm remove-active-admin --user cur "
494 + mDeviceAdminComponent.flattenToString());
495 mPoSet = mDoSet = false;
496 }
497 }
498
499 @Test
500 public void testCannotSuspendWhenProfileOwner() throws IOException {
501 assumeTrue(mPackageManager.hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN));
502 assertTrue("Profile-owner could not be set", setProfileOwner());
503 try {
504 suspendTestPackage(null, null, null);
505 fail("Suspend succeeded. Expected UnsupportedOperationException");
506 } catch (UnsupportedOperationException uex) {
507 }
508 }
509
510 @Test
511 public void testCannotSuspendWhenDeviceOwner() throws IOException {
512 assumeTrue(mPackageManager.hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN));
513 assertTrue("Device-owner could not be set", setDeviceOwner());
514 try {
515 suspendTestPackage(null, null, null);
516 fail("Suspend succeeded. Expected UnsupportedOperationException");
517 } catch (UnsupportedOperationException uex) {
518 }
519 }
520
521 @Test
522 public void testPackageUnsuspendedOnAddingDeviceOwner() throws IOException {
523 assumeTrue(mPackageManager.hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN));
524 mAppCommsReceiver.register(mReceiverHandler, ACTION_REPORT_MY_PACKAGE_UNSUSPENDED,
525 ACTION_REPORT_MY_PACKAGE_SUSPENDED);
526 mAppCommsReceiver.drainPendingBroadcasts();
527 suspendTestPackage(null, null, null);
528 Intent intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
529 assertEquals(ACTION_REPORT_MY_PACKAGE_SUSPENDED, intentFromApp.getAction());
530 assertTrue("Device-owner could not be set", setDeviceOwner());
531 intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
532 assertEquals(ACTION_REPORT_MY_PACKAGE_UNSUSPENDED, intentFromApp.getAction());
533 }
534
535 @Test
536 public void testPackageUnsuspendedOnAddingProfileOwner() throws IOException {
537 assumeTrue(mPackageManager.hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN));
538 mAppCommsReceiver.register(mReceiverHandler, ACTION_REPORT_MY_PACKAGE_UNSUSPENDED,
539 ACTION_REPORT_MY_PACKAGE_SUSPENDED);
540 mAppCommsReceiver.drainPendingBroadcasts();
541 suspendTestPackage(null, null, null);
542 Intent intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
543 assertEquals(ACTION_REPORT_MY_PACKAGE_SUSPENDED, intentFromApp.getAction());
544 assertTrue("Profile-owner could not be set", setProfileOwner());
545 intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
546 assertEquals(ACTION_REPORT_MY_PACKAGE_UNSUSPENDED, intentFromApp.getAction());
547 }
548
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700549 @After
Suprabh Shukla77e22452018-05-22 18:02:37 -0700550 public void tearDown() throws IOException {
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700551 mAppCommsReceiver.unregister();
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700552 if (mTestCallback != null) {
553 mLauncherApps.unregisterCallback(mTestCallback);
554 }
Suprabh Shukla77e22452018-05-22 18:02:37 -0700555 removeProfileOrDeviceOwner();
Suprabh Shukla3c3af142018-03-30 00:28:37 -0700556 mContext.sendBroadcast(new Intent(ACTION_FINISH_TEST_ACTIVITY)
557 .setPackage(TEST_APP_PACKAGE_NAME));
Suprabh Shukla2fd43ba2018-03-22 16:57:49 -0700558 }
559
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700560 private static abstract class StubbedCallback extends LauncherApps.Callback {
561
562 @Override
563 public void onPackageRemoved(String packageName, UserHandle user) {
564 }
565
566 @Override
567 public void onPackageAdded(String packageName, UserHandle user) {
568 }
569
570 @Override
571 public void onPackageChanged(String packageName, UserHandle user) {
572 }
573
574 @Override
575 public void onPackagesAvailable(String[] packageNames, UserHandle user, boolean replacing) {
576
577 }
578
579 @Override
580 public void onPackagesUnavailable(String[] packageNames, UserHandle user,
581 boolean replacing) {
582 }
Suprabh Shukla021b57a2018-03-08 18:21:50 -0800583 }
584}