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.uiautomator.UiDevice;
29 import android.util.Log;
30 
31 import androidx.test.InstrumentationRegistry;
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         }
168 
await()169         public boolean await() throws InterruptedException {
170             return mLatch.await(TIMEOUT_SECONDS, TimeUnit.SECONDS);
171         }
172 
getReceivedIntent()173         public Intent getReceivedIntent() {
174             return mReceivedIntent;
175         }
176 
177         @Override
onReceive(Context context, Intent intent)178         public void onReceive(Context context, Intent intent) {
179             mReceivedIntent = intent;
180             mLatch.countDown();
181         }
182     }
183 }
184