1 /*
2  * Copyright 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.finalization;
18 
19 import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE;
20 import static android.app.admin.DevicePolicyManager.STATE_USER_PROFILE_COMPLETE;
21 import static android.app.admin.DevicePolicyManager.STATE_USER_SETUP_COMPLETE;
22 import static android.app.admin.DevicePolicyManager.STATE_USER_SETUP_FINALIZED;
23 import static android.app.admin.DevicePolicyManager.STATE_USER_SETUP_INCOMPLETE;
24 import static android.app.admin.DevicePolicyManager.STATE_USER_UNMANAGED;
25 import static android.content.Context.DEVICE_POLICY_SERVICE;
26 import static com.android.internal.util.Preconditions.checkNotNull;
27 
28 import android.app.admin.DevicePolicyManager;
29 import android.content.Context;
30 import android.os.UserHandle;
31 
32 import com.android.internal.annotations.VisibleForTesting;
33 import com.android.managedprovisioning.common.ProvisionLogger;
34 import com.android.managedprovisioning.common.SettingsFacade;
35 import com.android.managedprovisioning.common.Utils;
36 import com.android.managedprovisioning.model.ProvisioningParams;
37 
38 /**
39  * Helper class to handle the user provisioning states.
40  *
41  * <p>This class calls interacts with {@link DevicePolicyManager} to handle the setting of
42  * user provisioning states at the end of provisioning.</p>
43  */
44 @VisibleForTesting
45 public class UserProvisioningStateHelper {
46     private final Context mContext;
47     private final DevicePolicyManager mDevicePolicyManager;
48     private final Utils mUtils;
49     private final SettingsFacade mSettingsFacade;
50     private final int mMyUserId;
51 
UserProvisioningStateHelper(Context context)52     public UserProvisioningStateHelper(Context context) {
53         this(context, new Utils(), new SettingsFacade(), UserHandle.myUserId());
54     }
55 
56     @VisibleForTesting
UserProvisioningStateHelper(Context context, Utils utils, SettingsFacade settingsFacade, int myUserId)57     UserProvisioningStateHelper(Context context,
58             Utils utils,
59             SettingsFacade settingsFacade,
60             int myUserId) {
61         mContext = checkNotNull(context);
62         mDevicePolicyManager = (DevicePolicyManager) mContext.getSystemService(
63                 DEVICE_POLICY_SERVICE);
64         mUtils = checkNotNull(utils);
65         mSettingsFacade = checkNotNull(settingsFacade);
66         mMyUserId = myUserId;
67     }
68 
69     /**
70      * Set the current users userProvisioningState depending on the following factors:
71      * <ul>
72      *     <li>We're setting up a managed-profile - need to set state on two users.</li>
73      *     <li>User-setup has previously been completed or not - skip states relating to
74      *     communicating with setup-wizard.</li>
75      *     <li>DPC requested we skip the rest of setup-wizard.</li>
76      * </ul>
77      *
78      * @param params configuration for current provisioning attempt
79      */
80     @VisibleForTesting
markUserProvisioningStateInitiallyDone(ProvisioningParams params)81     public void markUserProvisioningStateInitiallyDone(ProvisioningParams params) {
82         final boolean userSetupCompleted = mSettingsFacade.isUserSetupCompleted(mContext);
83 
84         int managedProfileUserId = UserHandle.USER_NULL;
85 
86         // new provisioning state for current user, if non-null
87         Integer newState = null;
88         // New provisioning state for managed-profile of current user, if non-null.
89         Integer newProfileState = null;
90 
91         if (params.provisioningAction.equals(ACTION_PROVISION_MANAGED_PROFILE)) {
92             // Managed profiles are a special case as two users are involved.
93             managedProfileUserId = mUtils.getManagedProfile(mContext).getIdentifier();
94             if (userSetupCompleted) {
95                 // SUW on current user is complete, so nothing much to do beyond indicating we're
96                 // all done.
97                 newProfileState = STATE_USER_SETUP_FINALIZED;
98             } else {
99                 // We're still in SUW, so indicate that a managed-profile was setup on current user,
100                 // and that we're awaiting finalization on both.
101                 newState = STATE_USER_PROFILE_COMPLETE;
102                 newProfileState = STATE_USER_SETUP_COMPLETE;
103             }
104         } else if (userSetupCompleted) {
105             if (params.isTransitioningFromRegularToChild) {
106                 // During a transition to child, the user had already been through the unmanaged
107                 // setup flow once, but now it is going through the DO provisioning flow. Therefore,
108                 // update the provisioning state so that the flow can continue.
109                 ProvisionLogger.logw("User transitioning to child, updating provisioning state.");
110                 newState = STATE_USER_SETUP_COMPLETE;
111             } else {
112                 // User setup was previously completed this is an unexpected case.
113                 ProvisionLogger.logw("user_setup_complete set, but provisioning was started");
114             }
115         } else if (params.skipUserSetup) {
116             // DPC requested setup-wizard is skipped, indicate this to SUW.
117             newState = STATE_USER_SETUP_COMPLETE;
118         } else {
119             // DPC requested setup-wizard is not skipped, indicate this to SUW.
120             newState = STATE_USER_SETUP_INCOMPLETE;
121         }
122 
123         if (newState != null) {
124             setUserProvisioningState(newState, mMyUserId);
125         }
126         if (newProfileState != null) {
127             setUserProvisioningState(newProfileState, managedProfileUserId);
128         }
129     }
130 
131     /**
132      * Finalize the current users userProvisioningState depending on the following factors:
133      * <ul>
134      *     <li>We're setting up a managed-profile - need to set state on two users.</li>
135      * </ul>
136      *
137      * @param params configuration for current provisioning attempt - if null (because
138      *               ManagedProvisioning wasn't used for first phase of provisioning) aassumes we
139      *               can just mark current user as being in finalized provisioning state
140      */
141     @VisibleForTesting
markUserProvisioningStateFinalized(ProvisioningParams params)142     public void markUserProvisioningStateFinalized(ProvisioningParams params) {
143 
144         if (params.provisioningAction.equals(ACTION_PROVISION_MANAGED_PROFILE)) {
145             // Managed profiles are a special case as two users are involved.
146             final int managedProfileUserId = mUtils.getManagedProfile(mContext).getIdentifier();
147             setUserProvisioningState(STATE_USER_SETUP_FINALIZED, managedProfileUserId);
148             setUserProvisioningState(STATE_USER_UNMANAGED, mMyUserId);
149         } else {
150             setUserProvisioningState(STATE_USER_SETUP_FINALIZED, mMyUserId);
151         }
152     }
153 
154     @VisibleForTesting
isStateUnmanagedOrFinalized()155     public boolean isStateUnmanagedOrFinalized() {
156         final int currentState = mDevicePolicyManager.getUserProvisioningState();
157         return currentState == STATE_USER_UNMANAGED || currentState == STATE_USER_SETUP_FINALIZED;
158     }
159 
setUserProvisioningState(int state, int userId)160     private void setUserProvisioningState(int state, int userId) {
161         ProvisionLogger.logi("Setting userProvisioningState for user " + userId + " to: " + state);
162         mDevicePolicyManager.setUserProvisioningState(state, userId);
163     }
164 }
165