1 /* 2 * Copyright (C) 2017 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 package com.android.compatibility.common.util.devicepolicy.provisioning; 17 18 import static android.app.admin.DevicePolicyManager.ACTION_MANAGED_PROFILE_PROVISIONED; 19 import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE; 20 import static android.content.Intent.ACTION_MANAGED_PROFILE_ADDED; 21 22 import android.content.BroadcastReceiver; 23 import android.content.Context; 24 import android.content.Intent; 25 import android.content.IntentFilter; 26 import android.os.Bundle; 27 import android.os.RemoteException; 28 import android.util.Log; 29 30 import androidx.test.InstrumentationRegistry; 31 import androidx.test.uiautomator.UiDevice; 32 33 import com.android.compatibility.common.util.BlockingBroadcastReceiver; 34 35 import java.util.concurrent.CountDownLatch; 36 import java.util.concurrent.LinkedBlockingQueue; 37 import java.util.concurrent.TimeUnit; 38 39 // TODO(b/183395856): Remove once the remaining silent provisioning tests are removed. 40 public class SilentProvisioningTestManager { 41 private static final long TIMEOUT_SECONDS = 120L; 42 private static final String TAG = "SilentProvisioningTest"; 43 44 private final LinkedBlockingQueue<Boolean> mProvisioningResults = new LinkedBlockingQueue(1); 45 46 private final IBooleanCallback mProvisioningResultCallback = new IBooleanCallback.Stub() { 47 @Override 48 public void onResult(boolean result) { 49 try { 50 mProvisioningResults.put(result); 51 } catch (InterruptedException e) { 52 Log.e(TAG, "IBooleanCallback.callback", e); 53 } 54 } 55 }; 56 57 private final Context mContext; 58 private Intent mReceivedProfileProvisionedIntent; 59 SilentProvisioningTestManager(Context context)60 public SilentProvisioningTestManager(Context context) { 61 mContext = context.getApplicationContext(); 62 } 63 getReceviedProfileProvisionedIntent()64 public Intent getReceviedProfileProvisionedIntent() { 65 return mReceivedProfileProvisionedIntent; 66 } 67 startProvisioningAndWait(Intent provisioningIntent)68 public boolean startProvisioningAndWait(Intent provisioningIntent) throws InterruptedException { 69 wakeUpAndDismissInsecureKeyguard(); 70 mContext.startActivity(getStartIntent(provisioningIntent)); 71 Log.i(TAG, "startActivity on user " + mContext.getUserId() + " with " + provisioningIntent); 72 73 if (ACTION_PROVISION_MANAGED_PROFILE.equals(provisioningIntent.getAction())) { 74 return waitManagedProfileProvisioning(); 75 } else { 76 return waitDeviceOwnerProvisioning(); 77 } 78 } 79 waitDeviceOwnerProvisioning()80 private boolean waitDeviceOwnerProvisioning() throws InterruptedException { 81 return pollProvisioningResult(); 82 } 83 waitManagedProfileProvisioning()84 private boolean waitManagedProfileProvisioning() throws InterruptedException { 85 BlockingBroadcastReceiver managedProfileProvisionedReceiver = 86 new BlockingBroadcastReceiver(mContext, ACTION_MANAGED_PROFILE_PROVISIONED); 87 BlockingBroadcastReceiver managedProfileAddedReceiver = 88 new BlockingBroadcastReceiver(mContext, ACTION_MANAGED_PROFILE_ADDED); 89 try { 90 managedProfileProvisionedReceiver.register(); 91 managedProfileAddedReceiver.register(); 92 93 if (!pollProvisioningResult()) { 94 return false; 95 } 96 97 mReceivedProfileProvisionedIntent = 98 managedProfileProvisionedReceiver.awaitForBroadcast( 99 TimeUnit.SECONDS.toMillis(TIMEOUT_SECONDS)); 100 if (mReceivedProfileProvisionedIntent == null) { 101 Log.i(TAG, "managedProfileProvisionedReceiver.awaitForBroadcast(): failed"); 102 return false; 103 } 104 105 if (managedProfileAddedReceiver.awaitForBroadcast( 106 TimeUnit.SECONDS.toMillis(TIMEOUT_SECONDS)) == null) { 107 Log.i(TAG, "managedProfileAddedReceiver.awaitForBroadcast(): failed"); 108 return false; 109 } 110 } finally { 111 managedProfileProvisionedReceiver.unregisterQuietly(); 112 managedProfileAddedReceiver.unregisterQuietly(); 113 } 114 return true; 115 } 116 pollProvisioningResult()117 private boolean pollProvisioningResult() throws InterruptedException { 118 Boolean result = mProvisioningResults.poll(TIMEOUT_SECONDS, TimeUnit.SECONDS); 119 if (result == null) { 120 Log.i(TAG, "ManagedProvisioning doesn't return result within " 121 + TIMEOUT_SECONDS + " seconds "); 122 return false; 123 } 124 125 if (!result) { 126 Log.i(TAG, "Failed to provision"); 127 return false; 128 } 129 return true; 130 } 131 getStartIntent(Intent intent)132 private Intent getStartIntent(Intent intent) { 133 final Bundle bundle = new Bundle(); 134 bundle.putParcelable(Intent.EXTRA_INTENT, intent); 135 bundle.putBinder(StartProvisioningActivity.EXTRA_BOOLEAN_CALLBACK, 136 mProvisioningResultCallback.asBinder()); 137 return new Intent(mContext, StartProvisioningActivity.class) 138 .putExtras(bundle) 139 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 140 } 141 wakeUpAndDismissInsecureKeyguard()142 private static void wakeUpAndDismissInsecureKeyguard() { 143 try { 144 UiDevice uiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()); 145 uiDevice.wakeUp(); 146 uiDevice.pressMenu(); 147 } catch (RemoteException e) { 148 Log.e(TAG, "wakeUpScreen", e); 149 } 150 } 151 152 private static class BlockingReceiver extends BroadcastReceiver { 153 154 private final CountDownLatch mLatch = new CountDownLatch(1); 155 private final Context mContext; 156 private final String mAction; 157 private Intent mReceivedIntent; 158 BlockingReceiver(Context context, String action)159 private BlockingReceiver(Context context, String action) { 160 mContext = context; 161 mAction = action; 162 mReceivedIntent = null; 163 } 164 register()165 public void register() { 166 mContext.registerReceiver(this, new IntentFilter(mAction), 167 Context.RECEIVER_EXPORTED_UNAUDITED); 168 } 169 await()170 public boolean await() throws InterruptedException { 171 return mLatch.await(TIMEOUT_SECONDS, TimeUnit.SECONDS); 172 } 173 getReceivedIntent()174 public Intent getReceivedIntent() { 175 return mReceivedIntent; 176 } 177 178 @Override onReceive(Context context, Intent intent)179 public void onReceive(Context context, Intent intent) { 180 mReceivedIntent = intent; 181 mLatch.countDown(); 182 } 183 } 184 } 185