OSDN Git Service

Refresh after clearing, tweak warn threshold.
[android-x86/packages-apps-Settings.git] / src / com / android / settings / deviceinfo / StorageWizardFormatProgress.java
1 /*
2  * Copyright (C) 2015 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.settings.deviceinfo;
18
19 import static com.android.settings.deviceinfo.StorageSettings.TAG;
20
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;
37
38 import com.android.settings.R;
39
40 import java.util.Objects;
41
42 public class StorageWizardFormatProgress extends StorageWizardBase {
43     private static final String TAG_SLOW_WARNING = "slow_warning";
44
45     private boolean mFormatPrivate;
46
47     private PartitionTask mTask;
48
49     @Override
50     protected void onCreate(Bundle savedInstanceState) {
51         super.onCreate(savedInstanceState);
52         if (mDisk == null) {
53             finish();
54             return;
55         }
56         setContentView(R.layout.storage_wizard_progress);
57         setKeepScreenOn(true);
58
59         mFormatPrivate = getIntent().getBooleanExtra(
60                 StorageWizardFormatConfirm.EXTRA_FORMAT_PRIVATE, false);
61         setIllustrationInternal(mFormatPrivate);
62
63         setHeaderText(R.string.storage_wizard_format_progress_title, mDisk.getDescription());
64         setBodyText(R.string.storage_wizard_format_progress_body, mDisk.getDescription());
65
66         getNextButton().setVisibility(View.GONE);
67
68         mTask = (PartitionTask) getLastNonConfigurationInstance();
69         if (mTask == null) {
70             mTask = new PartitionTask();
71             mTask.setActivity(this);
72             mTask.execute();
73         } else {
74             mTask.setActivity(this);
75         }
76     }
77
78     @Override
79     public Object onRetainNonConfigurationInstance() {
80         return mTask;
81     }
82
83     public static class PartitionTask extends AsyncTask<Void, Integer, Exception> {
84         public StorageWizardFormatProgress mActivity;
85
86         private volatile int mProgress = 20;
87
88         private volatile long mInternalBench;
89         private volatile long mPrivateBench;
90
91         @Override
92         protected Exception doInBackground(Void... params) {
93             final StorageWizardFormatProgress activity = mActivity;
94             final StorageManager storage = mActivity.mStorage;
95             try {
96                 if (activity.mFormatPrivate) {
97                     storage.partitionPrivate(activity.mDisk.getId());
98                     publishProgress(40);
99
100                     mInternalBench = storage.benchmark(null);
101                     publishProgress(60);
102
103                     final VolumeInfo privateVol = activity.findFirstVolume(VolumeInfo.TYPE_PRIVATE);
104                     mPrivateBench = storage.benchmark(privateVol.getId());
105
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());
115                     }
116
117                 } else {
118                     storage.partitionPublic(activity.mDisk.getId());
119                 }
120                 return null;
121             } catch (Exception e) {
122                 return e;
123             }
124         }
125
126         @Override
127         protected void onProgressUpdate(Integer... progress) {
128             mProgress = progress[0];
129             mActivity.setCurrentProgress(mProgress);
130         }
131
132         public void setActivity(StorageWizardFormatProgress activity) {
133             mActivity = activity;
134             mActivity.setCurrentProgress(mProgress);
135         }
136
137         @Override
138         protected void onPostExecute(Exception e) {
139             final StorageWizardFormatProgress activity = mActivity;
140             if (e != null) {
141                 Log.e(TAG, "Failed to partition", e);
142                 Toast.makeText(activity, e.getMessage(), Toast.LENGTH_LONG).show();
143                 activity.finishAffinity();
144                 return;
145             }
146
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");
150
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);
157                 } else {
158                     activity.onFormatFinished();
159                 }
160             } else {
161                 activity.onFormatFinished();
162             }
163         }
164     }
165
166     public static class SlowWarningFragment extends DialogFragment {
167         @Override
168         public Dialog onCreateDialog(Bundle savedInstanceState) {
169             final Context context = getActivity();
170
171             final AlertDialog.Builder builder = new AlertDialog.Builder(context);
172
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));
179
180             builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
181                 @Override
182                 public void onClick(DialogInterface dialog, int which) {
183                     final StorageWizardFormatProgress target =
184                             (StorageWizardFormatProgress) getActivity();
185                     target.onFormatFinished();
186                 }
187             });
188
189             return builder.create();
190         }
191     }
192
193     private String getDiskDescription() {
194         return mDisk.getDescription();
195     }
196
197     private String getGenericDiskDescription() {
198         // TODO: move this directly to DiskInfo
199         if (mDisk.isSd()) {
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);
203         } else {
204             return null;
205         }
206     }
207
208     private void onFormatFinished() {
209         final String forgetUuid = getIntent().getStringExtra(
210                 StorageWizardFormatConfirm.EXTRA_FORGET_UUID);
211         if (!TextUtils.isEmpty(forgetUuid)) {
212             mStorage.forgetVolume(forgetUuid);
213         }
214
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()));
222         } else {
223             offerMigrate = false;
224         }
225
226         if (offerMigrate) {
227             final Intent intent = new Intent(this, StorageWizardMigrate.class);
228             intent.putExtra(DiskInfo.EXTRA_DISK_ID, mDisk.getId());
229             startActivity(intent);
230         } else {
231             final Intent intent = new Intent(this, StorageWizardReady.class);
232             intent.putExtra(DiskInfo.EXTRA_DISK_ID, mDisk.getId());
233             startActivity(intent);
234         }
235         finishAffinity();
236     }
237
238     private static class SilentObserver extends IPackageMoveObserver.Stub {
239         @Override
240         public void onCreated(int moveId, Bundle extras) {
241             // Ignored
242         }
243
244         @Override
245         public void onStatusChanged(int moveId, int status, long estMillis) {
246             // Ignored
247         }
248     }
249 }