1 /* 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 17 package com.android.server.pm; 18 19 import static org.junit.Assert.assertEquals; 20 import static org.junit.Assert.assertFalse; 21 import static org.junit.Assert.assertNotNull; 22 import static org.junit.Assert.assertNull; 23 import static org.junit.Assert.assertTrue; 24 import static org.junit.Assert.fail; 25 import static org.junit.Assume.assumeTrue; 26 27 import android.app.AppGlobals; 28 import android.content.BroadcastReceiver; 29 import android.content.ComponentName; 30 import android.content.Context; 31 import android.content.Intent; 32 import android.content.IntentFilter; 33 import android.content.pm.IPackageManager; 34 import android.content.pm.LauncherApps; 35 import android.content.pm.PackageManager; 36 import android.content.res.Resources; 37 import android.os.BaseBundle; 38 import android.os.Bundle; 39 import android.os.Handler; 40 import android.os.Looper; 41 import android.os.PersistableBundle; 42 import android.os.RemoteException; 43 import android.os.UserHandle; 44 import android.support.test.InstrumentationRegistry; 45 import android.support.test.filters.LargeTest; 46 import android.support.test.runner.AndroidJUnit4; 47 import android.support.test.uiautomator.By; 48 import android.support.test.uiautomator.UiDevice; 49 import android.support.test.uiautomator.UiObject2; 50 import android.support.test.uiautomator.Until; 51 import android.util.Log; 52 import android.view.IWindowManager; 53 import android.view.WindowManagerGlobal; 54 55 import com.android.servicestests.apps.suspendtestapp.SuspendTestActivity; 56 import com.android.servicestests.apps.suspendtestapp.SuspendTestReceiver; 57 58 import org.junit.After; 59 import org.junit.Before; 60 import org.junit.Test; 61 import org.junit.runner.RunWith; 62 63 import java.io.IOException; 64 import java.util.Arrays; 65 import java.util.concurrent.CountDownLatch; 66 import java.util.concurrent.SynchronousQueue; 67 import java.util.concurrent.TimeUnit; 68 import java.util.concurrent.atomic.AtomicReference; 69 70 @RunWith(AndroidJUnit4.class) 71 @LargeTest 72 public class SuspendPackagesTest { 73 private static final String TAG = SuspendPackagesTest.class.getSimpleName(); 74 private static final String TEST_APP_LABEL = "Suspend Test App"; 75 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 78 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"; 83 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 94 95 private Context mContext; 96 private PackageManager mPackageManager; 97 private LauncherApps mLauncherApps; 98 private Handler mReceiverHandler; 99 private AppCommunicationReceiver mAppCommsReceiver; 100 private StubbedCallback mTestCallback; 101 private UiDevice mUiDevice; 102 private ComponentName mDeviceAdminComponent; 103 private boolean mPoSet; 104 private boolean mDoSet; 105 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 115 void register(Handler handler, String... actions) { 116 registered = true; 117 final IntentFilter intentFilter = new IntentFilter(); 118 for (String action : actions) { 119 intentFilter.addAction(action); 120 } 121 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) { 132 Log.d(TAG, "AppCommunicationReceiver#onReceive: " + intent.getAction()); 133 try { 134 intentQueue.offer(intent, 5, TimeUnit.SECONDS); 135 } catch (InterruptedException ie) { 136 throw new RuntimeException("Receiver thread interrupted", ie); 137 } 138 } 139 140 Intent pollForIntent(long secondsToWait) { 141 if (!registered) { 142 throw new IllegalStateException("Receiver not registered"); 143 } 144 final Intent intent; 145 try { 146 intent = intentQueue.poll(secondsToWait, TimeUnit.SECONDS); 147 } catch (InterruptedException ie) { 148 throw new RuntimeException("Interrupted while waiting for app broadcast", ie); 149 } 150 return intent; 151 } 152 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 } 162 } 163 164 @Before 165 public void setUp() { 166 mContext = InstrumentationRegistry.getTargetContext(); 167 mPackageManager = mContext.getPackageManager(); 168 mLauncherApps = (LauncherApps) mContext.getSystemService(Context.LAUNCHER_APPS_SERVICE); 169 mReceiverHandler = new Handler(Looper.getMainLooper()); 170 mUiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()); 171 mDeviceAdminComponent = new ComponentName(mContext, 172 "com.android.server.devicepolicy.DummyDeviceAdmins$Admin1"); 173 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); 182 } 183 184 /** 185 * Care should be taken when used with {@link #mAppCommsReceiver} in the same test as both use 186 * the same handler. 187 */ 188 private Bundle requestAppAction(String action) throws InterruptedException { 189 final AtomicReference<Bundle> result = new AtomicReference<>(); 190 final CountDownLatch receiverLatch = new CountDownLatch(1); 191 final ComponentName testReceiverComponent = new ComponentName(TEST_APP_PACKAGE_NAME, 192 SuspendTestReceiver.class.getCanonicalName()); 193 final Intent broadcastIntent = new Intent(action) 194 .setComponent(testReceiverComponent) 195 .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 216 private void suspendTestPackage(PersistableBundle appExtras, PersistableBundle launcherExtras, 217 String dialogMessage) { 218 final String[] unchangedPackages = mPackageManager.setPackagesSuspended( 219 PACKAGES_TO_SUSPEND, true, appExtras, launcherExtras, dialogMessage); 220 assertTrue("setPackagesSuspended returned non-empty list", unchangedPackages.length == 0); 221 } 222 223 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 229 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 } 236 237 private static boolean areSameExtras(BaseBundle expected, BaseBundle received) { 238 if (expected != null) { 239 expected.get(""); // hack to unparcel the bundles. 240 } 241 if (received != null) { 242 received.get(""); 243 } 244 return BaseBundle.kindofEquals(expected, received); 245 } 246 247 private static void assertSameExtras(String message, BaseBundle expected, BaseBundle received) { 248 if (!areSameExtras(expected, received)) { 249 fail(message + ": [expected: " + expected + "; received: " + received + "]"); 250 } 251 } 252 253 @Test 254 public void testIsPackageSuspended() throws Exception { 255 suspendTestPackage(null, null, null); 256 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)); 264 assertNull(resultFromApp.getBundle(SuspendTestReceiver.EXTRA_SUSPENDED_APP_EXTRAS)); 265 266 final PersistableBundle appExtras = getExtras("testSuspendedStateFromApp", 20, "20", 0.2); 267 suspendTestPackage(appExtras, null, null); 268 269 resultFromApp = requestAppAction(SuspendTestReceiver.ACTION_GET_SUSPENDED_STATE); 270 assertTrue("resultFromApp:suspended is false", 271 resultFromApp.getBoolean(SuspendTestReceiver.EXTRA_SUSPENDED)); 272 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() { 280 mAppCommsReceiver.register(mReceiverHandler, ACTION_REPORT_MY_PACKAGE_SUSPENDED, 281 ACTION_REPORT_MY_PACKAGE_UNSUSPENDED); 282 mAppCommsReceiver.drainPendingBroadcasts(); 283 final PersistableBundle appExtras = getExtras("testMyPackageSuspendBroadcasts", 1, "1", .1); 284 suspendTestPackage(appExtras, null, null); 285 Intent intentFromApp = mAppCommsReceiver.receiveIntentFromApp(); 286 assertEquals("MY_PACKAGE_SUSPENDED delivery not reported", 287 ACTION_REPORT_MY_PACKAGE_SUSPENDED, intentFromApp.getAction()); 288 assertSameExtras("Received app extras different to the ones supplied", appExtras, 289 intentFromApp.getBundleExtra(SuspendTestReceiver.EXTRA_SUSPENDED_APP_EXTRAS)); 290 unsuspendTestPackage(); 291 intentFromApp = mAppCommsReceiver.receiveIntentFromApp(); 292 assertEquals("MY_PACKAGE_UNSUSPENDED delivery not reported", 293 ACTION_REPORT_MY_PACKAGE_UNSUSPENDED, intentFromApp.getAction()); 294 } 295 296 @Test 297 public void testUpdatingAppExtras() { 298 mAppCommsReceiver.register(mReceiverHandler, ACTION_REPORT_MY_PACKAGE_SUSPENDED); 299 final PersistableBundle extras1 = getExtras("testMyPackageSuspendedOnChangingExtras", 1, 300 "1", 0.1); 301 suspendTestPackage(extras1, null, null); 302 Intent intentFromApp = mAppCommsReceiver.receiveIntentFromApp(); 303 assertEquals("MY_PACKAGE_SUSPENDED delivery not reported", 304 ACTION_REPORT_MY_PACKAGE_SUSPENDED, intentFromApp.getAction()); 305 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); 309 suspendTestPackage(extras2, null, null); 310 intentFromApp = mAppCommsReceiver.receiveIntentFromApp(); 311 assertEquals("MY_PACKAGE_SUSPENDED delivery not reported", 312 ACTION_REPORT_MY_PACKAGE_SUSPENDED, intentFromApp.getAction()); 313 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 325 @Test 326 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 340 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); 345 suspendTestPackage(null, launcherExtras, null); 346 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() { 354 suspendTestPackage(null, null, null); 355 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 382 public void onPackagesSuspended(String[] packageNames, UserHandle user, 383 Bundle launcherExtras) { 384 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); 405 suspendTestPackage(null, suppliedExtras, null); 406 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); 439 suspendTestPackage(null, suppliedExtras, null); 440 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 445 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); 458 final String testMessage = "This is a test message to report suspension of %1$s"; 459 suspendTestPackage(null, null, testMessage); 460 startTestAppActivity(); 461 assertNull("No broadcast was expected from app", mAppCommsReceiver.pollForIntent(2)); 462 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")); 466 final UiObject2 moreDetailsButton = mUiDevice.findObject( 467 By.clickable(true).text(buttonText)); 468 assertNotNull(buttonText + " button not shown", moreDetailsButton); 469 moreDetailsButton.click(); 470 final Intent intentFromApp = mAppCommsReceiver.receiveIntentFromApp(); 471 assertEquals(buttonText + " activity start not reported", 472 ACTION_REPORT_MORE_DETAILS_ACTIVITY_STARTED, intentFromApp.getAction()); 473 final String receivedPackageName = intentFromApp.getStringExtra( 474 EXTRA_RECEIVED_PACKAGE_NAME); 475 assertEquals("Wrong package name received by " + buttonText + " activity", 476 TEST_APP_PACKAGE_NAME, receivedPackageName); 477 } 478 479 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 549 @After 550 public void tearDown() throws IOException { 551 mAppCommsReceiver.unregister(); 552 if (mTestCallback != null) { 553 mLauncherApps.unregisterCallback(mTestCallback); 554 } 555 removeProfileOrDeviceOwner(); 556 mContext.sendBroadcast(new Intent(ACTION_FINISH_TEST_ACTIVITY) 557 .setPackage(TEST_APP_PACKAGE_NAME)); 558 } 559 560 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 } 583 } 584 } 585