• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2019, 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.finalization;
18 
19 import static android.content.Intent.ACTION_USER_UNLOCKED;
20 
21 import static com.android.managedprovisioning.finalization.FinalizationController.PROVISIONING_FINALIZED_RESULT_CHILD_ACTIVITY_LAUNCHED;
22 import static com.android.managedprovisioning.finalization.FinalizationController.PROVISIONING_FINALIZED_RESULT_WAIT_FOR_WORK_PROFILE_AVAILABLE;
23 import static com.android.managedprovisioning.provisioning.Constants.PROVISIONING_SERVICE_INTENT;
24 
25 import android.app.Activity;
26 import android.app.BackgroundServiceStartNotAllowedException;
27 import android.content.BroadcastReceiver;
28 import android.content.Context;
29 import android.content.Intent;
30 import android.content.IntentFilter;
31 import android.os.Bundle;
32 import android.os.StrictMode;
33 import android.os.UserHandle;
34 import android.os.UserManager;
35 import android.view.WindowManager;
36 
37 import com.android.managedprovisioning.common.ProvisionLogger;
38 import com.android.managedprovisioning.common.TransitionHelper;
39 
40 /**
41  * Instances of this base class manage interactions with a Device Policy Controller app after it has
42  * been set up as either a Device Owner or a Profile Owner.
43  *
44  * Once we are sure that the DPC app has had an opportunity to run its own setup activities, we
45  * record in the system that provisioning has been finalized.
46  *
47  * Different instances of this class will be tailored to run at different points in the Setup
48  * Wizard user flows.
49  */
50 public abstract class FinalizationActivityBase extends Activity {
51 
52     private static final String CONTROLLER_STATE_KEY = "controller_state";
53 
54     private final TransitionHelper mTransitionHelper;
55     private FinalizationController mFinalizationController;
56     private boolean mIsReceiverRegistered;
57     private boolean mRestoring;
58 
59     private final BroadcastReceiver mUserUnlockedReceiver = new BroadcastReceiver() {
60         @Override
61         public void onReceive(Context context, Intent intent) {
62             if (!ACTION_USER_UNLOCKED.equals(intent.getAction())) {
63                 return;
64             }
65             int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, /* defaultValue= */ -1);
66             UserManager userManager = getSystemService(UserManager.class);
67             if (!userManager.isManagedProfile(userId)) {
68                 return;
69             }
70             tryFinalizeProvisioning();
71             unregisterUserUnlockedReceiver();
72         }
73     };
74 
FinalizationActivityBase(TransitionHelper transitionHelper)75     FinalizationActivityBase(TransitionHelper transitionHelper) {
76         mTransitionHelper = transitionHelper;
77     }
78 
79     @Override
onCreate(Bundle savedInstanceState)80     public final void onCreate(Bundle savedInstanceState) {
81         // TODO(b/123987694): Investigate use of buffered i/o for provisioning params file
82         StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
83                 .permitUnbufferedIo()
84                 .build());
85         mTransitionHelper.applyContentScreenTransitions(this);
86         super.onCreate(savedInstanceState);
87         getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
88 
89         mFinalizationController = createFinalizationController();
90 
91         mRestoring = savedInstanceState != null;
92         if (mRestoring) {
93             final Bundle controllerState = savedInstanceState.getBundle(CONTROLLER_STATE_KEY);
94             if (controllerState != null) {
95                 mFinalizationController.restoreInstanceState(controllerState);
96             }
97 
98             // If savedInstanceState is not null, we already executed the logic below, so don't do
99             // it again now.  We likely just need to wait for a child activity to complete, so we
100             // can execute an onActivityResult() callback before finishing this activity.
101             return;
102         }
103     }
104 
105     @Override
onStart()106     protected void onStart() {
107         super.onStart();
108         try {
109             getApplicationContext().startService(PROVISIONING_SERVICE_INTENT);
110         } catch (BackgroundServiceStartNotAllowedException e) {
111             ProvisionLogger.loge(e);
112         }
113         if (!mRestoring) {
114             tryFinalizeProvisioning();
115         }
116     }
117 
getTransitionHelper()118     protected TransitionHelper getTransitionHelper() {
119         return mTransitionHelper;
120     }
121 
tryFinalizeProvisioning()122     private void tryFinalizeProvisioning() {
123         // Register receiver first to avoid race condition when user becomes unlocked after
124         // the user unlocked check. This will be unregistered if we don't need it
125         mIsReceiverRegistered = false;
126         registerUserUnlockedReceiver();
127         mFinalizationController.provisioningFinalized();
128         final int result = mFinalizationController.getProvisioningFinalizedResult();
129         if (PROVISIONING_FINALIZED_RESULT_CHILD_ACTIVITY_LAUNCHED == result) {
130             onFinalizationCompletedWithChildActivityLaunched();
131         } else if (PROVISIONING_FINALIZED_RESULT_WAIT_FOR_WORK_PROFILE_AVAILABLE != result) {
132             if (FinalizationController.PROVISIONING_FINALIZED_RESULT_SKIPPED != result) {
133                 mFinalizationController.commitFinalizedState();
134             }
135             setResult(RESULT_OK);
136             getTransitionHelper().finishActivity(this);
137         }
138 
139         if (PROVISIONING_FINALIZED_RESULT_WAIT_FOR_WORK_PROFILE_AVAILABLE != result) {
140             unregisterUserUnlockedReceiver();
141         }
142     }
143 
registerUserUnlockedReceiver()144     private void registerUserUnlockedReceiver() {
145         IntentFilter filter = new IntentFilter();
146         filter.addAction(ACTION_USER_UNLOCKED);
147         registerReceiverAsUser(
148                 mUserUnlockedReceiver,
149                 UserHandle.ALL,
150                 filter,
151                 /* broadcastPermission= */ null,
152                 /* scheduler= */ null);
153         mIsReceiverRegistered = true;
154     }
155 
unregisterUserUnlockedReceiver()156     private void unregisterUserUnlockedReceiver() {
157         if (!mIsReceiverRegistered) {
158             return;
159         }
160         unregisterReceiver(mUserUnlockedReceiver);
161         mIsReceiverRegistered = false;
162     }
163 
164     @Override
onSaveInstanceState(Bundle outState)165     protected final void onSaveInstanceState(Bundle outState) {
166         super.onSaveInstanceState(outState);
167 
168         final Bundle controllerState = new Bundle();
169         outState.putBundle(CONTROLLER_STATE_KEY, controllerState);
170         mFinalizationController.saveInstanceState(controllerState);
171     }
172 
173     @Override
onDestroy()174     public final void onDestroy() {
175         mFinalizationController.activityDestroyed(isFinishing());
176         unregisterUserUnlockedReceiver();
177         getApplicationContext().stopService(PROVISIONING_SERVICE_INTENT);
178         super.onDestroy();
179     }
180 
181     /**
182      * Return the finalization controller instance that was constructed in {@link #onCreate}.
183      */
getFinalizationController()184     protected FinalizationController getFinalizationController() {
185         return mFinalizationController;
186     }
187 
188     /**
189      * Construct the correct subtype of FinalizationController.
190      */
createFinalizationController()191     protected abstract FinalizationController createFinalizationController();
192 
193     /**
194      * Hook for code that should run when the controller has launched a child activity.
195      */
onFinalizationCompletedWithChildActivityLaunched()196     protected abstract void onFinalizationCompletedWithChildActivityLaunched();
197 }
198