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
17package com.android.managedprovisioning.finalization;
18
19import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE;
20import static android.app.admin.DevicePolicyManager.STATE_USER_PROFILE_COMPLETE;
21import static android.app.admin.DevicePolicyManager.STATE_USER_SETUP_COMPLETE;
22import static android.app.admin.DevicePolicyManager.STATE_USER_SETUP_FINALIZED;
23import static android.app.admin.DevicePolicyManager.STATE_USER_SETUP_INCOMPLETE;
24import static android.app.admin.DevicePolicyManager.STATE_USER_UNMANAGED;
25import static android.content.Context.DEVICE_POLICY_SERVICE;
26import static com.android.internal.util.Preconditions.checkNotNull;
27
28import android.app.admin.DevicePolicyManager;
29import android.content.Context;
30import android.os.UserHandle;
31
32import com.android.internal.annotations.VisibleForTesting;
33import com.android.managedprovisioning.common.ProvisionLogger;
34import com.android.managedprovisioning.common.SettingsFacade;
35import com.android.managedprovisioning.common.Utils;
36import 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
45public 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
52    UserProvisioningStateHelper(Context context) {
53        this(context, new Utils(), new SettingsFacade(), UserHandle.myUserId());
54    }
55
56    @VisibleForTesting
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
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            // User setup was previously completed this is an unexpected case.
106            ProvisionLogger.logw("user_setup_complete set, but provisioning was started");
107        } else if (params.skipUserSetup) {
108            // DPC requested setup-wizard is skipped, indicate this to SUW.
109            newState = STATE_USER_SETUP_COMPLETE;
110        } else {
111            // DPC requested setup-wizard is not skipped, indicate this to SUW.
112            newState = STATE_USER_SETUP_INCOMPLETE;
113        }
114
115        if (newState != null) {
116            setUserProvisioningState(newState, mMyUserId);
117        }
118        if (newProfileState != null) {
119            setUserProvisioningState(newProfileState, managedProfileUserId);
120        }
121    }
122
123    /**
124     * Finalize the current users userProvisioningState depending on the following factors:
125     * <ul>
126     *     <li>We're setting up a managed-profile - need to set state on two users.</li>
127     * </ul>
128     *
129     * @param params configuration for current provisioning attempt - if null (because
130     *               ManagedProvisioning wasn't used for first phase of provisioning) aassumes we
131     *               can just mark current user as being in finalized provisioning state
132     */
133    @VisibleForTesting
134    public void markUserProvisioningStateFinalized(ProvisioningParams params) {
135
136        if (params.provisioningAction.equals(ACTION_PROVISION_MANAGED_PROFILE)) {
137            // Managed profiles are a special case as two users are involved.
138            final int managedProfileUserId = mUtils.getManagedProfile(mContext).getIdentifier();
139            setUserProvisioningState(STATE_USER_SETUP_FINALIZED, managedProfileUserId);
140            setUserProvisioningState(STATE_USER_UNMANAGED, mMyUserId);
141        } else {
142            setUserProvisioningState(STATE_USER_SETUP_FINALIZED, mMyUserId);
143        }
144    }
145
146    @VisibleForTesting
147    public boolean isStateUnmanagedOrFinalized() {
148        final int currentState = mDevicePolicyManager.getUserProvisioningState();
149        return currentState == STATE_USER_UNMANAGED || currentState == STATE_USER_SETUP_FINALIZED;
150    }
151
152    private void setUserProvisioningState(int state, int userId) {
153        ProvisionLogger.logi("Setting userProvisioningState for user " + userId + " to: " + state);
154        mDevicePolicyManager.setUserProvisioningState(state, userId);
155    }
156}
157