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.DeviceAdminInfo.HEADLESS_DEVICE_OWNER_MODE_AFFILIATED;
20 import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE;
21 import static android.app.admin.DevicePolicyManager.STATE_USER_PROFILE_COMPLETE;
22 import static android.app.admin.DevicePolicyManager.STATE_USER_PROFILE_FINALIZED;
23 import static android.app.admin.DevicePolicyManager.STATE_USER_SETUP_COMPLETE;
24 import static android.app.admin.DevicePolicyManager.STATE_USER_SETUP_FINALIZED;
25 import static android.app.admin.DevicePolicyManager.STATE_USER_UNMANAGED;
26 import static android.content.Context.DEVICE_POLICY_SERVICE;
27 
28 import static com.android.internal.util.Preconditions.checkNotNull;
29 
30 import android.app.admin.DevicePolicyManager;
31 import android.app.admin.flags.Flags;
32 import android.content.Context;
33 import android.os.UserHandle;
34 
35 import com.android.internal.annotations.VisibleForTesting;
36 import com.android.managedprovisioning.common.ProvisionLogger;
37 import com.android.managedprovisioning.common.SettingsFacade;
38 import com.android.managedprovisioning.common.Utils;
39 import com.android.managedprovisioning.model.ProvisioningParams;
40 
41 /**
42  * Helper class to handle the user provisioning states.
43  *
44  * <p>This class calls interacts with {@link DevicePolicyManager} to handle the setting of
45  * user provisioning states at the end of provisioning.</p>
46  */
47 @VisibleForTesting
48 public class UserProvisioningStateHelper {
49     private final Context mContext;
50     private final DevicePolicyManager mDevicePolicyManager;
51     private final Utils mUtils;
52     private final SettingsFacade mSettingsFacade;
53     private final int mMyUserId;
54 
UserProvisioningStateHelper(Context context)55     public UserProvisioningStateHelper(Context context) {
56         this(context, new Utils(), new SettingsFacade(), UserHandle.myUserId());
57     }
58 
59     @VisibleForTesting
UserProvisioningStateHelper(Context context, Utils utils, SettingsFacade settingsFacade, int myUserId)60     UserProvisioningStateHelper(Context context,
61             Utils utils,
62             SettingsFacade settingsFacade,
63             int myUserId) {
64         mContext = checkNotNull(context);
65         mDevicePolicyManager = (DevicePolicyManager) mContext.getSystemService(
66                 DEVICE_POLICY_SERVICE);
67         mUtils = checkNotNull(utils);
68         mSettingsFacade = checkNotNull(settingsFacade);
69         mMyUserId = myUserId;
70     }
71 
72     /**
73      * Set the current users userProvisioningState depending on the following factors:
74      * <ul>
75      *     <li>We're setting up a managed-profile - need to set state on two users.</li>
76      *     <li>User-setup has previously been completed or not - skip states relating to
77      *     communicating with setup-wizard.</li>
78      *     <li>DPC requested we skip the rest of setup-wizard.</li>
79      * </ul>
80      *
81      * @param params configuration for current provisioning attempt
82      */
83     @VisibleForTesting
markUserProvisioningStateInitiallyDone(ProvisioningParams params)84     public void markUserProvisioningStateInitiallyDone(ProvisioningParams params) {
85         final boolean userSetupCompleted = mSettingsFacade.isUserSetupCompleted(mContext);
86 
87         int managedProfileUserId = UserHandle.USER_NULL;
88 
89         // new provisioning state for current user, if non-null
90         Integer newState = null;
91         // New provisioning state for managed-profile of current user, if non-null.
92         Integer newProfileState = null;
93 
94         if (params.provisioningAction.equals(ACTION_PROVISION_MANAGED_PROFILE)) {
95             // Managed profiles are a special case as two users are involved.
96             managedProfileUserId = mUtils.getManagedProfile(mContext).getIdentifier();
97             if (userSetupCompleted) {
98                 // SUW on current user is complete, so nothing much to do beyond indicating we're
99                 // all done.
100                 if (!isUserProvisioningStateProfileFinalized()) {
101                     newState = STATE_USER_PROFILE_FINALIZED;
102                 }
103                 newProfileState = STATE_USER_SETUP_FINALIZED;
104             } else {
105                 // We're still in SUW, so indicate that a managed-profile was setup on current user,
106                 // and that we're awaiting finalization on both.
107                 newState = STATE_USER_PROFILE_COMPLETE;
108                 newProfileState = STATE_USER_SETUP_COMPLETE;
109             }
110         } else if (userSetupCompleted) {
111             if (params.allowProvisioningAfterUserSetupComplete) {
112                 ProvisionLogger.logw("Provisioning after user setup complete is allowed, "
113                         + "updating provisioning state.");
114                 newState = STATE_USER_SETUP_COMPLETE;
115             } else {
116                 // User setup was previously completed this is an unexpected case.
117                 ProvisionLogger.logw("user_setup_complete set, but provisioning was started");
118             }
119         } else {
120             newState = STATE_USER_SETUP_COMPLETE;
121         }
122 
123         if (newState != null) {
124             setUserProvisioningState(newState, mMyUserId);
125             maybeSetHeadlessSystemUserProvisioningState(params, newState);
126         }
127         if (newProfileState != null) {
128             setUserProvisioningState(newProfileState, managedProfileUserId);
129         }
130     }
131 
132     /**
133      * Finalize the current user's userProvisioningState depending on the following factors:
134      * <ul>
135      *     <li>We're setting up a managed-profile - need to set state on two users.</li>
136      * </ul>
137      *
138      * @param params configuration for current provisioning attempt - if null (because
139      *               ManagedProvisioning wasn't used for first phase of provisioning) aassumes we
140      *               can just mark current user as being in finalized provisioning state
141      */
142     @VisibleForTesting
markUserProvisioningStateFinalized(ProvisioningParams params)143     public void markUserProvisioningStateFinalized(ProvisioningParams params) {
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_PROFILE_FINALIZED, mMyUserId);
149         } else {
150             setUserProvisioningState(STATE_USER_SETUP_FINALIZED, mMyUserId);
151             maybeSetHeadlessSystemUserProvisioningState(params, STATE_USER_SETUP_FINALIZED);
152         }
153     }
154 
155     /**
156      * Returns whether the calling user's provision state is unmanaged, finanalized or
157      * user profile finalized.
158      */
159     @VisibleForTesting
isStateUnmanagedOrFinalized()160     public boolean isStateUnmanagedOrFinalized() {
161         final int currentState = mDevicePolicyManager.getUserProvisioningState();
162         return currentState == STATE_USER_UNMANAGED
163                 || currentState == STATE_USER_SETUP_FINALIZED
164                 || currentState == STATE_USER_PROFILE_FINALIZED;
165     }
166 
167     /**
168      * Resets the provisioning state for {@link UserHandle#USER_SYSTEM} to {@link
169      * DevicePolicyManager#STATE_USER_UNMANAGED}.
170      */
resetPrimaryUserProvisioningState()171     public void resetPrimaryUserProvisioningState() {
172         setUserProvisioningState(STATE_USER_UNMANAGED, UserHandle.USER_SYSTEM);
173     }
174 
isUserProvisioningStateProfileFinalized()175     private boolean isUserProvisioningStateProfileFinalized() {
176         final int currentState = mDevicePolicyManager.getUserProvisioningState();
177         return currentState == STATE_USER_PROFILE_FINALIZED;
178     }
179 
setUserProvisioningState(int state, int userId)180     private void setUserProvisioningState(int state, int userId) {
181         ProvisionLogger.logi("Setting userProvisioningState for user " + userId + " to: " + state);
182         mDevicePolicyManager.setUserProvisioningState(state, userId);
183     }
184 
maybeSetHeadlessSystemUserProvisioningState(ProvisioningParams params, int newState)185     private void maybeSetHeadlessSystemUserProvisioningState(ProvisioningParams params, int newState) {
186         if (params.provisioningAction.equals(ACTION_PROVISION_MANAGED_PROFILE)) {
187             return; // No special headless logic for managed profiles
188         }
189         if (mUtils.isHeadlessSystemUserMode()
190                 && (!Flags.headlessDeviceOwnerProvisioningFixEnabled()
191                 || mDevicePolicyManager.getHeadlessDeviceOwnerMode()
192                 == HEADLESS_DEVICE_OWNER_MODE_AFFILIATED)
193                 && mMyUserId != UserHandle.USER_SYSTEM) {
194             // For affiliated DO, headless system user's DO has to be set on system user and
195             // therefore system user has to be marked the same as the calling user.
196             setUserProvisioningState(newState, UserHandle.USER_SYSTEM);
197         }
198     }
199 }
200