1 /* 2 * Copyright (C) 2016 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.managedprovisioning.task; 18 19 import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE; 20 import static org.mockito.Matchers.eq; 21 import static org.mockito.Mockito.doAnswer; 22 import static org.mockito.Mockito.verify; 23 import static org.mockito.Mockito.verifyNoMoreInteractions; 24 import static org.mockito.Mockito.verifyZeroInteractions; 25 import static org.mockito.Mockito.when; 26 27 import android.app.IActivityManager; 28 import android.content.BroadcastReceiver; 29 import android.content.Context; 30 import android.content.Intent; 31 import android.os.Handler; 32 import android.os.HandlerThread; 33 import android.os.RemoteException; 34 import android.os.UserHandle; 35 import android.test.AndroidTestCase; 36 import android.test.suitebuilder.annotation.SmallTest; 37 38 import com.android.managedprovisioning.model.ProvisioningParams; 39 40 import org.mockito.ArgumentCaptor; 41 import org.mockito.Mock; 42 import org.mockito.MockitoAnnotations; 43 import org.mockito.invocation.InvocationOnMock; 44 45 import java.util.concurrent.CountDownLatch; 46 import java.util.concurrent.TimeUnit; 47 48 /** 49 * Unit tests for {@link StartManagedProfileTask}. 50 */ 51 public class StartManagedProfileTaskTest extends AndroidTestCase { 52 private static final int TEST_USER_ID = 123; 53 private static final String TEST_MDM_PACKAGE_NAME = "com.test.mdm"; 54 private static final ProvisioningParams TEST_PARAMS = new ProvisioningParams.Builder() 55 .setDeviceAdminPackageName(TEST_MDM_PACKAGE_NAME) 56 .setProvisioningAction(ACTION_PROVISION_MANAGED_PROFILE) 57 .build(); 58 private static final Intent UNLOCK_INTENT = new Intent(Intent.ACTION_USER_UNLOCKED) 59 .putExtra(Intent.EXTRA_USER_HANDLE, TEST_USER_ID); 60 61 @Mock private IActivityManager mIActivityManager; 62 @Mock private Context mContext; 63 @Mock private AbstractProvisioningTask.Callback mCallback; 64 private ArgumentCaptor<BroadcastReceiver> mReceiverCaptor = 65 ArgumentCaptor.forClass(BroadcastReceiver.class); 66 67 private StartManagedProfileTask mTask; 68 private HandlerThread mHandlerThread; 69 private final CountDownLatch mStartInBackgroundLatch = new CountDownLatch(1); 70 private final CountDownLatch mSuccessLatch = new CountDownLatch(1); 71 72 public void setUp() { 73 // this is necessary for mockito to work 74 System.setProperty("dexmaker.dexcache", getContext().getCacheDir().toString()); 75 MockitoAnnotations.initMocks(this); 76 77 mHandlerThread = new HandlerThread("Test thread"); 78 mHandlerThread.start(); 79 80 mTask = new StartManagedProfileTask(mIActivityManager, mContext, TEST_PARAMS, mCallback); 81 82 // register a countdown latch for the success callback 83 doAnswer((InvocationOnMock invocationOnMock) -> { 84 mSuccessLatch.countDown(); 85 return null; 86 }).when(mCallback).onSuccess(mTask); 87 } 88 89 public void tearDown() { 90 mHandlerThread.quitSafely(); 91 } 92 93 @SmallTest 94 public void testSuccess() throws Exception { 95 // GIVEN that starting the user succeeds 96 doAnswer((InvocationOnMock invocationOnMock) -> { 97 mStartInBackgroundLatch.countDown(); 98 return true; 99 }).when(mIActivityManager).startUserInBackground(TEST_USER_ID); 100 101 // WHEN the task is run (on a handler thread to avoid deadlocks) 102 new Handler(mHandlerThread.getLooper()).post(() -> mTask.run(TEST_USER_ID)); 103 104 // THEN user unlock should have been called 105 assertTrue(mStartInBackgroundLatch.await(1, TimeUnit.SECONDS)); 106 107 // THEN an unlock receiver should be registered 108 verify(mContext).registerReceiverAsUser( 109 mReceiverCaptor.capture(), 110 eq(UserHandle.of(TEST_USER_ID)), 111 eq(StartManagedProfileTask.UNLOCK_FILTER), 112 eq(null), eq(null)); 113 114 // THEN the success callback should not have been called 115 verifyZeroInteractions(mCallback); 116 117 // WHEN the unlock broadcast is sent 118 mReceiverCaptor.getValue().onReceive(mContext, UNLOCK_INTENT); 119 120 // THEN the success callback should be called 121 assertTrue(mSuccessLatch.await(1, TimeUnit.SECONDS)); 122 verify(mCallback).onSuccess(mTask); 123 verifyNoMoreInteractions(mCallback); 124 125 verify(mContext).unregisterReceiver(mReceiverCaptor.getValue()); 126 } 127 128 @SmallTest 129 public void testError() throws Exception { 130 // GIVEN that starting the user in background fails 131 when(mIActivityManager.startUserInBackground(TEST_USER_ID)).thenReturn(false); 132 133 // WHEN the task is run 134 mTask.run(TEST_USER_ID); 135 136 // THEN an unlock receiver should be registered 137 verify(mContext).registerReceiverAsUser( 138 mReceiverCaptor.capture(), 139 eq(UserHandle.of(TEST_USER_ID)), 140 eq(StartManagedProfileTask.UNLOCK_FILTER), 141 eq(null), eq(null)); 142 143 // THEN the error callback should have been called 144 verify(mCallback).onError(mTask, 0); 145 verifyNoMoreInteractions(mCallback); 146 147 verify(mContext).unregisterReceiver(mReceiverCaptor.getValue()); 148 } 149 150 @SmallTest 151 public void testRemoteException() throws Exception { 152 // GIVEN that starting the user in background throws a remote exception 153 when(mIActivityManager.startUserInBackground(TEST_USER_ID)) 154 .thenThrow(new RemoteException()); 155 156 // WHEN the task is run 157 mTask.run(TEST_USER_ID); 158 159 // THEN an unlock receiver should be registered 160 verify(mContext).registerReceiverAsUser( 161 mReceiverCaptor.capture(), 162 eq(UserHandle.of(TEST_USER_ID)), 163 eq(StartManagedProfileTask.UNLOCK_FILTER), 164 eq(null), eq(null)); 165 166 // THEN the error callback should have been called 167 verify(mCallback).onError(mTask, 0); 168 verifyNoMoreInteractions(mCallback); 169 170 verify(mContext).unregisterReceiver(mReceiverCaptor.getValue()); 171 } 172 } 173