ProvisioningActivity.java revision c2656f5a7bf6ec67336c1cf404e44ce14472b380
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.provisioning;
18
19import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PROVISIONING_PROVISIONING_ACTIVITY_TIME_MS;
20
21import android.app.Activity;
22import android.app.DialogFragment;
23import android.os.Bundle;
24import android.support.annotation.VisibleForTesting;
25import android.view.accessibility.AccessibilityEvent;
26import android.widget.TextView;
27
28import com.android.managedprovisioning.R;
29import com.android.managedprovisioning.common.DialogBuilder;
30import com.android.managedprovisioning.common.ProvisionLogger;
31import com.android.managedprovisioning.common.SetupGlifLayoutActivity;
32import com.android.managedprovisioning.common.SimpleDialog;
33import com.android.managedprovisioning.common.Utils;
34import com.android.managedprovisioning.model.CustomizationParams;
35import com.android.managedprovisioning.model.ProvisioningParams;
36
37/**
38 * Progress activity shown whilst provisioning is ongoing.
39 *
40 * <p>This activity registers for updates of the provisioning process from the
41 * {@link ProvisioningManager}. It shows progress updates as provisioning progresses and handles
42 * showing of cancel and error dialogs.</p>
43 */
44public class ProvisioningActivity extends SetupGlifLayoutActivity
45        implements SimpleDialog.SimpleDialogListener, ProvisioningManagerCallback {
46
47    private static final String KEY_PROVISIONING_STARTED = "ProvisioningStarted";
48
49    private static final String ERROR_DIALOG_OK = "ErrorDialogOk";
50    private static final String ERROR_DIALOG_RESET = "ErrorDialogReset";
51    private static final String CANCEL_PROVISIONING_DIALOG_OK = "CancelProvisioningDialogOk";
52    private static final String CANCEL_PROVISIONING_DIALOG_RESET = "CancelProvisioningDialogReset";
53
54    private TextView mProgressTextView;
55    private ProvisioningParams mParams;
56    private ProvisioningManager mProvisioningManager;
57
58    public ProvisioningActivity() {
59        this(null, new Utils());
60    }
61
62    @VisibleForTesting
63    public ProvisioningActivity(ProvisioningManager provisioningManager, Utils utils) {
64        super(utils);
65        mProvisioningManager = provisioningManager;
66    }
67
68    // Lazily initialize ProvisioningManager, since we can't call in ProvisioningManager.getInstance
69    // in constructor as base context is not available in constructor
70    private ProvisioningManager getProvisioningManager() {
71        if (mProvisioningManager == null) {
72            mProvisioningManager = ProvisioningManager.getInstance(this);
73        }
74        return mProvisioningManager;
75    }
76
77    @Override
78    protected void onCreate(Bundle savedInstanceState) {
79        super.onCreate(savedInstanceState);
80        mParams = getIntent().getParcelableExtra(ProvisioningParams.EXTRA_PROVISIONING_PARAMS);
81        initializeUi(mParams);
82        mProgressTextView = (TextView) findViewById(R.id.prog_text);
83
84        if (savedInstanceState == null
85                || !savedInstanceState.getBoolean(KEY_PROVISIONING_STARTED)) {
86            getProvisioningManager().maybeStartProvisioning(mParams);
87        }
88    }
89
90    @Override
91    protected void onSaveInstanceState(Bundle outState) {
92        super.onSaveInstanceState(outState);
93        outState.putBoolean(KEY_PROVISIONING_STARTED, true);
94    }
95
96    @Override
97    protected void onResume() {
98        super.onResume();
99        if (!isAnyDialogAdded()) {
100            getProvisioningManager().registerListener(this);
101        }
102    }
103
104    private boolean isAnyDialogAdded() {
105        return isDialogAdded(ERROR_DIALOG_OK)
106                || isDialogAdded(ERROR_DIALOG_RESET)
107                || isDialogAdded(CANCEL_PROVISIONING_DIALOG_OK)
108                || isDialogAdded(CANCEL_PROVISIONING_DIALOG_RESET);
109    }
110
111    @Override
112    public void onPause() {
113        getProvisioningManager().unregisterListener(this);
114        super.onPause();
115    }
116
117    @Override
118    public void onBackPressed() {
119        // if EXTRA_PROVISIONING_SKIP_USER_CONSENT is specified, don't allow user to cancel
120        if (mParams.skipUserConsent) {
121            return;
122        }
123
124        showCancelProvisioningDialog();
125    }
126
127    @Override
128    public void preFinalizationCompleted() {
129        ProvisionLogger.logi("ProvisioningActivity pre-finalization completed");
130        setResult(Activity.RESULT_OK);
131        finish();
132    }
133
134    @Override
135    public void provisioningTasksCompleted() {
136        getProvisioningManager().preFinalize();
137    }
138
139    @Override
140    public void progressUpdate(int progressMessage) {
141        mProgressTextView.setText(progressMessage);
142        mProgressTextView.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
143    }
144
145    @Override
146    public void error(int titleId, int messageId, boolean resetRequired) {
147        SimpleDialog.Builder dialogBuilder = new SimpleDialog.Builder()
148                .setTitle(titleId)
149                .setMessage(messageId)
150                .setCancelable(false)
151                .setPositiveButtonMessage(resetRequired
152                        ? R.string.reset : R.string.device_owner_error_ok);
153
154        showDialog(dialogBuilder, resetRequired ? ERROR_DIALOG_RESET : ERROR_DIALOG_OK);
155    }
156
157    @Override
158    protected void showDialog(DialogBuilder builder, String tag) {
159        // Whenever a dialog is shown, stop listening for further updates
160        getProvisioningManager().unregisterListener(this);
161        super.showDialog(builder, tag);
162    }
163
164    @Override
165    protected int getMetricsCategory() {
166        return PROVISIONING_PROVISIONING_ACTIVITY_TIME_MS;
167    }
168
169    private void showCancelProvisioningDialog() {
170        final boolean isDoProvisioning = getUtils().isDeviceOwnerAction(mParams.provisioningAction);
171        final String dialogTag = isDoProvisioning ? CANCEL_PROVISIONING_DIALOG_RESET
172                : CANCEL_PROVISIONING_DIALOG_OK;
173        final int positiveResId = isDoProvisioning ? R.string.reset
174                : R.string.profile_owner_cancel_ok;
175        final int negativeResId = isDoProvisioning ? R.string.device_owner_cancel_cancel
176                : R.string.profile_owner_cancel_cancel;
177        final int dialogMsgResId = isDoProvisioning
178                ? R.string.this_will_reset_take_back_first_screen
179                : R.string.profile_owner_cancel_message;
180
181        SimpleDialog.Builder dialogBuilder = new SimpleDialog.Builder()
182                .setCancelable(false)
183                .setMessage(dialogMsgResId)
184                .setNegativeButtonMessage(negativeResId)
185                .setPositiveButtonMessage(positiveResId);
186        if (isDoProvisioning) {
187            dialogBuilder.setTitle(R.string.stop_setup_reset_device_question);
188        }
189
190        showDialog(dialogBuilder, dialogTag);
191    }
192
193    private void onProvisioningAborted() {
194        setResult(Activity.RESULT_CANCELED);
195        finish();
196    }
197
198    @Override
199    public void onNegativeButtonClick(DialogFragment dialog) {
200        switch (dialog.getTag()) {
201            case CANCEL_PROVISIONING_DIALOG_OK:
202            case CANCEL_PROVISIONING_DIALOG_RESET:
203                dialog.dismiss();
204                break;
205            default:
206                SimpleDialog.throwButtonClickHandlerNotImplemented(dialog);
207        }
208        getProvisioningManager().registerListener(this);
209    }
210
211    @Override
212    public void onPositiveButtonClick(DialogFragment dialog) {
213        switch (dialog.getTag()) {
214            case CANCEL_PROVISIONING_DIALOG_OK:
215                getProvisioningManager().cancelProvisioning();
216                onProvisioningAborted();
217                break;
218            case CANCEL_PROVISIONING_DIALOG_RESET:
219                getUtils().sendFactoryResetBroadcast(this, "DO provisioning cancelled by user");
220                onProvisioningAborted();
221                break;
222            case ERROR_DIALOG_OK:
223                onProvisioningAborted();
224                break;
225            case ERROR_DIALOG_RESET:
226                getUtils().sendFactoryResetBroadcast(this, "Error during DO provisioning");
227                onProvisioningAborted();
228                break;
229            default:
230                SimpleDialog.throwButtonClickHandlerNotImplemented(dialog);
231        }
232    }
233
234    private void initializeUi(ProvisioningParams params) {
235        final boolean isDoProvisioning = getUtils().isDeviceOwnerAction(params.provisioningAction);
236        final int headerResId = isDoProvisioning ? R.string.setup_work_device
237                : R.string.setting_up_workspace;
238        final int titleResId = isDoProvisioning ? R.string.setup_device_progress
239                : R.string.setup_profile_progress;
240
241        initializeLayoutParams(R.layout.progress, headerResId, true,
242                CustomizationParams.createInstance(mParams, this, mUtils).statusBarColor);
243        setTitle(titleResId);
244    }
245}