1ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway/*
2ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway * Copyright 2014, The Android Open Source Project
3ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway *
4ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway * Licensed under the Apache License, Version 2.0 (the "License");
5ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway * you may not use this file except in compliance with the License.
6ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway * You may obtain a copy of the License at
7ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway *
8ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway *      http://www.apache.org/licenses/LICENSE-2.0
9ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway *
10ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway * Unless required by applicable law or agreed to in writing, software
11ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway * distributed under the License is distributed on an "AS IS" BASIS,
12ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway * See the License for the specific language governing permissions and
14ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway * limitations under the License.
15ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway */
16ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway
17ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadwaypackage com.android.managedprovisioning;
18ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway
19d1784bd4d917bb36125e6faf125a2425c343838bSteven Ngimport static android.app.admin.DeviceAdminReceiver.ACTION_PROFILE_PROVISIONING_COMPLETE;
20d1784bd4d917bb36125e6faf125a2425c343838bSteven Ngimport static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE;
21d1784bd4d917bb36125e6faf125a2425c343838bSteven Ngimport static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE;
22d1784bd4d917bb36125e6faf125a2425c343838bSteven Ng
23ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadwayimport android.app.Activity;
24ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadwayimport android.app.admin.DevicePolicyManager;
25ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadwayimport android.content.BroadcastReceiver;
26ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadwayimport android.content.Context;
27ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadwayimport android.content.Intent;
28ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadwayimport android.os.Bundle;
29ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadwayimport android.os.UserHandle;
30ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway
3172023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franzimport com.android.managedprovisioning.common.IllegalProvisioningArgumentException;
3272023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franzimport com.android.managedprovisioning.common.Utils;
33d1784bd4d917bb36125e6faf125a2425c343838bSteven Ngimport com.android.managedprovisioning.model.ProvisioningParams;
347079df5a3fb155947004843ee8ec25b36127e3edSteven Ngimport com.android.managedprovisioning.parser.MessageParser;
35ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway
36ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway/*
37ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway * This class is used to make sure that we start the MDM after we shut the setup wizard down.
38ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway * The shut down of the setup wizard is initiated in the DeviceOwnerProvisioningActivity or
39ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway * ProfileOwnerProvisioningActivity by calling
40ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway * {@link DevicePolicyManager.setUserProvisioningState()}. This will cause the
41ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway * Setup wizard to shut down and send a ACTION_PROVISIONING_FINALIZATION intent. This intent is
42ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway * caught by this receiver instead which will send the
43ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway * ACTION_PROFILE_PROVISIONING_COMPLETE broadcast to the MDM, which can then present it's own
44ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway * activities.
45ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway */
46ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadwaypublic class FinalizationActivity extends Activity {
47ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway
48ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway    private ProvisioningParams mParams;
49ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway
50ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway    private static final String INTENT_STORE_NAME = "finalization-receiver";
51ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway
5272023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz    private final Utils mUtils = new Utils();
5372023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz
54ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway    @Override
55ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway    public void onCreate(Bundle savedInstanceState) {
56ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway        super.onCreate(savedInstanceState);
57ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway
58e04659786591df44c6fd359de5408fd8f7d6254bBenjamin Franz        DevicePolicyManager dpm = getSystemService(DevicePolicyManager.class);
59e04659786591df44c6fd359de5408fd8f7d6254bBenjamin Franz        int currentState = dpm.getUserProvisioningState();
60ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway
61e04659786591df44c6fd359de5408fd8f7d6254bBenjamin Franz        switch (currentState) {
62e04659786591df44c6fd359de5408fd8f7d6254bBenjamin Franz            case DevicePolicyManager.STATE_USER_SETUP_INCOMPLETE:
63e04659786591df44c6fd359de5408fd8f7d6254bBenjamin Franz            case DevicePolicyManager.STATE_USER_SETUP_COMPLETE:
64e04659786591df44c6fd359de5408fd8f7d6254bBenjamin Franz            case DevicePolicyManager.STATE_USER_PROFILE_COMPLETE:
65e04659786591df44c6fd359de5408fd8f7d6254bBenjamin Franz                finalizeProvisioning(dpm);
66e04659786591df44c6fd359de5408fd8f7d6254bBenjamin Franz                break;
67e04659786591df44c6fd359de5408fd8f7d6254bBenjamin Franz            case DevicePolicyManager.STATE_USER_UNMANAGED:
68e04659786591df44c6fd359de5408fd8f7d6254bBenjamin Franz            case DevicePolicyManager.STATE_USER_SETUP_FINALIZED:
69e04659786591df44c6fd359de5408fd8f7d6254bBenjamin Franz                // Nothing to do in these cases.
70e04659786591df44c6fd359de5408fd8f7d6254bBenjamin Franz                ProvisionLogger.logw("Received ACTION_PROVISIONING_FINALIZATION intent, but "
71e04659786591df44c6fd359de5408fd8f7d6254bBenjamin Franz                        + "nothing to do in state: " + currentState);
72e04659786591df44c6fd359de5408fd8f7d6254bBenjamin Franz                break;
73ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway        }
74ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway
75ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway        finish();
76ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway    }
77ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway
78ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway    public static void storeProvisioningParams(Context context, ProvisioningParams params) {
79ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway        Intent intent = new MessageParser().getIntentFromProvisioningParams(params);
80ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway        getIntentStore(context).save(intent);
81ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway    }
82ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway
83ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway    private void finalizeProvisioning(DevicePolicyManager dpm) {
84ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway        mParams = loadProvisioningParamsAndClearIntentStore();
85ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway        Intent provisioningCompleteIntent = getProvisioningCompleteIntent(dpm);
86ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway        if (provisioningCompleteIntent == null) {
87ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway            return;
88ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway        }
89ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway
90ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway        // It maybe the case that mParams is null at this point - we expect this to be the case if
91ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway        // ManagedProvisioning wasn't invoked to perform setup. We'll simply trigger the normal
92ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway        // broadcast so that the installed DPC knows that user-setup completed. Concrete use-case
93ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway        // is a user being setup through DevicePolicyManager.createAndInitializeUser() by the
94ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway        // device-owner, which sets profile-owner and then launches the user. Setup-wizard on the
95ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway        // user runs, and at the end of it's activity flow will trigger the finalization intent,
96ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway        // which then allows us to notify the DPC that profile setup is complete.
97ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway        if (mParams != null &&
98ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway                mParams.provisioningAction.equals(ACTION_PROVISION_MANAGED_PROFILE)) {
99ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway            // For the managed profile owner case, we need to send the provisioning complete
100ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway            // intent to the mdm. Once it has been received, we'll send
101ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway            // ACTION_MANAGED_PROFILE_PROVISIONED in the parent.
102ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway            finalizeManagedProfileOwnerProvisioning(provisioningCompleteIntent);
103ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway        } else {
104ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway            // For managed user and device owner, we just need to send the provisioning complete
105ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway            // intent to the mdm.
106ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway            sendBroadcast(provisioningCompleteIntent);
107ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway        }
108ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway
10972023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz        mUtils.markUserProvisioningStateFinalized(this, mParams);
110ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway    }
111ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway
112ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway    private void finalizeManagedProfileOwnerProvisioning(Intent provisioningCompleteIntent) {
11372023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz        UserHandle managedUserHandle = mUtils.getManagedProfile(this);
114ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway        if (managedUserHandle == null) {
115ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway            ProvisionLogger.loge("Failed to retrieve the userHandle of the managed profile.");
116ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway            return;
117ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway        }
118ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway        BroadcastReceiver mdmReceivedSuccessReceiver = new MdmReceivedSuccessReceiver(
11925a4d3d99c94d562cb11eef8bef81ddf4d602ec2Steven Ng                mParams.accountToMigrate, mParams.deviceAdminComponentName.getPackageName());
120ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway
121ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway        sendOrderedBroadcastAsUser(provisioningCompleteIntent, managedUserHandle, null,
122ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway                mdmReceivedSuccessReceiver, null, Activity.RESULT_OK, null, null);
123ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway    }
124ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway
125ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway    private Intent getProvisioningCompleteIntent(DevicePolicyManager dpm) {
126ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway        Intent intent = new Intent(ACTION_PROFILE_PROVISIONING_COMPLETE);
127ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway        try {
128ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway            // mParams maybe null for cases where DevicePolicyManager has directly set DO or PO and
129ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway            // ManagedProvisioning wasn't involved. In that case, we may still want to use the same
130ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway            // mechanism after setup-wizard to invoke the MDM, hence why we fallback to inspecting
131ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway            // device and profile-owner.
132ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway            if (mParams != null) {
133ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway                intent.setComponent(mParams.inferDeviceAdminComponentName(this));
134ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway            } else if (dpm.getDeviceOwner() != null) {
13572023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz                intent.setComponent(mUtils.findDeviceAdmin(dpm.getDeviceOwner(),
136ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway                        null /* mdmComponentName */, this));
137ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway            } else if (dpm.getProfileOwner() != null) {
13872023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz                intent.setComponent(mUtils.findDeviceAdmin(dpm.getProfileOwner().getPackageName(),
139ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway                        null /* mdmComponentName */, this));
140ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway            } else {
141ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway                return null;
142ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway            }
14372023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz        } catch (IllegalProvisioningArgumentException e) {
144ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway            ProvisionLogger.loge("Failed to infer the device admin component name", e);
145ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway            return null;
146ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway        }
147ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway        intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES | Intent.FLAG_RECEIVER_FOREGROUND);
148ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway        if (mParams != null && mParams.adminExtrasBundle != null) {
149ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway            intent.putExtra(EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE, mParams.adminExtrasBundle);
150ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway        }
151ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway        return intent;
152ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway    }
153ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway
154ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway    private ProvisioningParams loadProvisioningParamsAndClearIntentStore() {
155ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway        IntentStore intentStore = getIntentStore(this);
156ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway        Intent intent = intentStore.load();
157ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway        if (intent == null) {
158ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway            ProvisionLogger.loge("Fail to retrieve ProvisioningParams from intent store.");
159ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway            return null;
160ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway        }
161ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway        intentStore.clear();
162ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway
163ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway        try {
1647079df5a3fb155947004843ee8ec25b36127e3edSteven Ng            return new MessageParser().parse(intent, this);
165ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway        } catch (IllegalProvisioningArgumentException e) {
166ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway            ProvisionLogger.loge("Failed to parse provisioning intent", e);
167ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway        }
168ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway        return null;
169ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway    }
170ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway
171ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway    private static IntentStore getIntentStore(Context context) {
172ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway        return new IntentStore(context, INTENT_STORE_NAME);
173ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway    }
174ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway}
175