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