2 * Copyright (C) 2015 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.android.settings.deviceinfo;
19 import static com.android.settings.deviceinfo.StorageSettings.TAG;
21 import android.app.AlertDialog;
22 import android.app.Dialog;
23 import android.app.DialogFragment;
24 import android.content.Context;
25 import android.content.DialogInterface;
26 import android.content.Intent;
27 import android.content.pm.IPackageMoveObserver;
28 import android.os.AsyncTask;
29 import android.os.Bundle;
30 import android.os.storage.DiskInfo;
31 import android.os.storage.StorageManager;
32 import android.os.storage.VolumeInfo;
33 import android.text.TextUtils;
34 import android.util.Log;
35 import android.view.View;
36 import android.widget.Toast;
38 import com.android.settings.R;
40 import java.util.Objects;
42 public class StorageWizardFormatProgress extends StorageWizardBase {
43 private static final String TAG_SLOW_WARNING = "slow_warning";
45 private boolean mFormatPrivate;
47 private PartitionTask mTask;
50 protected void onCreate(Bundle savedInstanceState) {
51 super.onCreate(savedInstanceState);
56 setContentView(R.layout.storage_wizard_progress);
57 setKeepScreenOn(true);
59 mFormatPrivate = getIntent().getBooleanExtra(
60 StorageWizardFormatConfirm.EXTRA_FORMAT_PRIVATE, false);
61 setIllustrationInternal(mFormatPrivate);
63 setHeaderText(R.string.storage_wizard_format_progress_title, mDisk.getDescription());
64 setBodyText(R.string.storage_wizard_format_progress_body, mDisk.getDescription());
66 getNextButton().setVisibility(View.GONE);
68 mTask = (PartitionTask) getLastNonConfigurationInstance();
70 mTask = new PartitionTask();
71 mTask.setActivity(this);
74 mTask.setActivity(this);
79 public Object onRetainNonConfigurationInstance() {
83 public static class PartitionTask extends AsyncTask<Void, Integer, Exception> {
84 public StorageWizardFormatProgress mActivity;
86 private volatile int mProgress = 20;
88 private volatile long mInternalBench;
89 private volatile long mPrivateBench;
92 protected Exception doInBackground(Void... params) {
93 final StorageWizardFormatProgress activity = mActivity;
94 final StorageManager storage = mActivity.mStorage;
96 if (activity.mFormatPrivate) {
97 storage.partitionPrivate(activity.mDisk.getId());
100 mInternalBench = storage.benchmark(null);
103 final VolumeInfo privateVol = activity.findFirstVolume(VolumeInfo.TYPE_PRIVATE);
104 mPrivateBench = storage.benchmark(privateVol.getId());
106 // If we just adopted the device that had been providing
107 // physical storage, then automatically move storage to the
108 // new emulated volume.
109 if (activity.mDisk.isDefaultPrimary()
110 && Objects.equals(storage.getPrimaryStorageUuid(),
111 StorageManager.UUID_PRIMARY_PHYSICAL)) {
112 Log.d(TAG, "Just formatted primary physical; silently moving "
113 + "storage to new emulated volume");
114 storage.setPrimaryStorageUuid(privateVol.getFsUuid(), new SilentObserver());
118 storage.partitionPublic(activity.mDisk.getId());
121 } catch (Exception e) {
127 protected void onProgressUpdate(Integer... progress) {
128 mProgress = progress[0];
129 mActivity.setCurrentProgress(mProgress);
132 public void setActivity(StorageWizardFormatProgress activity) {
133 mActivity = activity;
134 mActivity.setCurrentProgress(mProgress);
138 protected void onPostExecute(Exception e) {
139 final StorageWizardFormatProgress activity = mActivity;
141 Log.e(TAG, "Failed to partition", e);
142 Toast.makeText(activity, e.getMessage(), Toast.LENGTH_LONG).show();
143 activity.finishAffinity();
147 if (activity.mFormatPrivate) {
148 final float pct = (float) mInternalBench / (float) mPrivateBench;
149 Log.d(TAG, "New volume is " + pct + "x the speed of internal");
151 // To help set user expectations around device performance, we
152 // warn if the adopted media is 0.25x the speed of internal
153 // storage or slower.
154 if (Float.isNaN(pct) || pct < 0.25) {
155 final SlowWarningFragment dialog = new SlowWarningFragment();
156 dialog.show(activity.getFragmentManager(), TAG_SLOW_WARNING);
158 activity.onFormatFinished();
161 activity.onFormatFinished();
166 public static class SlowWarningFragment extends DialogFragment {
168 public Dialog onCreateDialog(Bundle savedInstanceState) {
169 final Context context = getActivity();
171 final AlertDialog.Builder builder = new AlertDialog.Builder(context);
173 final StorageWizardFormatProgress target =
174 (StorageWizardFormatProgress) getActivity();
175 final String descrip = target.getDiskDescription();
176 final String genericDescip = target.getGenericDiskDescription();
177 builder.setMessage(TextUtils.expandTemplate(getText(R.string.storage_wizard_slow_body),
178 descrip, genericDescip));
180 builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
182 public void onClick(DialogInterface dialog, int which) {
183 final StorageWizardFormatProgress target =
184 (StorageWizardFormatProgress) getActivity();
185 target.onFormatFinished();
189 return builder.create();
193 private String getDiskDescription() {
194 return mDisk.getDescription();
197 private String getGenericDiskDescription() {
198 // TODO: move this directly to DiskInfo
200 return getString(com.android.internal.R.string.storage_sd_card);
201 } else if (mDisk.isUsb()) {
202 return getString(com.android.internal.R.string.storage_usb_drive);
208 private void onFormatFinished() {
209 final String forgetUuid = getIntent().getStringExtra(
210 StorageWizardFormatConfirm.EXTRA_FORGET_UUID);
211 if (!TextUtils.isEmpty(forgetUuid)) {
212 mStorage.forgetVolume(forgetUuid);
215 final boolean offerMigrate;
216 if (mFormatPrivate) {
217 // Offer to migrate only if storage is currently internal
218 final VolumeInfo privateVol = getPackageManager()
219 .getPrimaryStorageCurrentVolume();
220 offerMigrate = (privateVol != null
221 && VolumeInfo.ID_PRIVATE_INTERNAL.equals(privateVol.getId()));
223 offerMigrate = false;
227 final Intent intent = new Intent(this, StorageWizardMigrate.class);
228 intent.putExtra(DiskInfo.EXTRA_DISK_ID, mDisk.getId());
229 startActivity(intent);
231 final Intent intent = new Intent(this, StorageWizardReady.class);
232 intent.putExtra(DiskInfo.EXTRA_DISK_ID, mDisk.getId());
233 startActivity(intent);
238 private static class SilentObserver extends IPackageMoveObserver.Stub {
240 public void onCreated(int moveId, Bundle extras) {
245 public void onStatusChanged(int moveId, int status, long estMillis) {