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 android.app.settings.SettingsEnums;
20 import android.content.Intent;
21 import android.content.pm.PackageManager;
22 import android.content.pm.UserInfo;
23 import android.os.Bundle;
24 import android.os.UserManager;
25 import android.os.storage.DiskInfo;
26 import android.os.storage.StorageManager;
27 import android.os.storage.VolumeInfo;
28 import android.text.TextUtils;
29 import android.util.Log;
30 import android.view.View;
31 import android.widget.Toast;
32 
33 import com.android.internal.widget.LockPatternUtils;
34 import com.android.settings.R;
35 import com.android.settings.overlay.FeatureFactory;
36 import com.android.settings.password.ChooseLockSettingsHelper;
37 
38 import java.util.Objects;
39 
40 public class StorageWizardMigrateConfirm extends StorageWizardBase {
41     private static final String TAG = "StorageWizardMigrateConfirm";
42 
43     private static final int REQUEST_CREDENTIAL = 100;
44 
45     private MigrateEstimateTask mEstimate;
46 
47     @Override
onCreate(Bundle savedInstanceState)48     protected void onCreate(Bundle savedInstanceState) {
49         super.onCreate(savedInstanceState);
50         setContentView(R.layout.storage_wizard_generic);
51 
52         // When called with just disk, find the first private volume
53         if (mVolume == null) {
54             mVolume = findFirstVolume(VolumeInfo.TYPE_PRIVATE);
55         }
56 
57         final VolumeInfo sourceVol = getPackageManager().getPrimaryStorageCurrentVolume();
58         if (sourceVol == null || mVolume == null) {
59             Log.d(TAG, "Missing either source or target volume");
60             finish();
61             return;
62         }
63 
64         setIcon(R.drawable.ic_swap_horiz);
65         setHeaderText(R.string.storage_wizard_migrate_v2_title, getDiskShortDescription());
66         setBodyText(R.string.memory_calculating_size);
67         setAuxChecklist();
68 
69         mEstimate = new MigrateEstimateTask(this) {
70             @Override
71             public void onPostExecute(String size, String time) {
72                 setBodyText(R.string.storage_wizard_migrate_v2_body,
73                         getDiskDescription(), size, time);
74             }
75         };
76 
77         mEstimate.copyFrom(getIntent());
78         mEstimate.execute();
79 
80         setBackButtonText(R.string.storage_wizard_migrate_v2_later);
81         setNextButtonText(R.string.storage_wizard_migrate_v2_now);
82     }
83 
84     @Override
onNavigateBack(View view)85     public void onNavigateBack(View view) {
86         FeatureFactory.getFeatureFactory().getMetricsFeatureProvider().action(this,
87                 SettingsEnums.ACTION_STORAGE_MIGRATE_LATER);
88 
89         if (mDisk != null) {
90             final Intent intent = new Intent(this, StorageWizardReady.class);
91             intent.putExtra(EXTRA_MIGRATE_SKIP, true);
92             startActivity(intent);
93         } else {
94             finishAffinity();
95         }
96     }
97 
98     @Override
onNavigateNext(View view)99     public void onNavigateNext(View view) {
100         // Ensure that all users are unlocked so that we can move their data
101         final LockPatternUtils lpu = new LockPatternUtils(this);
102         if (StorageManager.isFileEncrypted()) {
103             for (UserInfo user : getSystemService(UserManager.class).getUsers()) {
104                 if (StorageManager.isCeStorageUnlocked(user.id)) {
105                     continue;
106                 }
107                 if (!lpu.isSecure(user.id)) {
108                     Log.d(TAG, "Unsecured user " + user.id + " is currently locked; attempting "
109                             + "automatic unlock");
110                     lpu.unlockUserKeyIfUnsecured(user.id);
111                 } else {
112                     Log.d(TAG, "Secured user " + user.id + " is currently locked; requesting "
113                             + "manual unlock");
114                     final CharSequence description = TextUtils.expandTemplate(
115                             getText(R.string.storage_wizard_move_unlock), user.name);
116                     final ChooseLockSettingsHelper.Builder builder =
117                             new ChooseLockSettingsHelper.Builder(this);
118                     builder.setRequestCode(REQUEST_CREDENTIAL)
119                             .setDescription(description)
120                             .setUserId(user.id)
121                             .setAllowAnyUserId(true)
122                             .setForceVerifyPath(true)
123                             .show();
124                     return;
125                 }
126             }
127         }
128 
129         // We only expect exceptions from StorageManagerService#setPrimaryStorageUuid
130         int moveId;
131         try {
132             moveId = getPackageManager().movePrimaryStorage(mVolume);
133         } catch (IllegalArgumentException e) {
134             StorageManager sm = (StorageManager) getSystemService(STORAGE_SERVICE);
135 
136             if (Objects.equals(mVolume.getFsUuid(), sm.getPrimaryStorageVolume().getUuid())) {
137                 final Intent intent = new Intent(this, StorageWizardReady.class);
138                 intent.putExtra(DiskInfo.EXTRA_DISK_ID,
139                         getIntent().getStringExtra(DiskInfo.EXTRA_DISK_ID));
140                 startActivity(intent);
141                 finishAffinity();
142 
143                 return;
144             } else {
145                 throw e;
146             }
147         } catch (IllegalStateException e) {
148             Toast.makeText(this, getString(R.string.another_migration_already_in_progress),
149                     Toast.LENGTH_LONG).show();
150             finishAffinity();
151 
152             return;
153         }
154 
155         FeatureFactory.getFeatureFactory().getMetricsFeatureProvider().action(this,
156                 SettingsEnums.ACTION_STORAGE_MIGRATE_NOW);
157 
158         final Intent intent = new Intent(this, StorageWizardMigrateProgress.class);
159         intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, mVolume.getId());
160         intent.putExtra(PackageManager.EXTRA_MOVE_ID, moveId);
161         startActivity(intent);
162         finishAffinity();
163     }
164 
165     @Override
onActivityResult(int requestCode, int resultCode, Intent data)166     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
167         if (requestCode == REQUEST_CREDENTIAL) {
168             if (resultCode == RESULT_OK) {
169                 // Credentials confirmed, so storage should be unlocked; let's
170                 // go look for the next locked user.
171                 onNavigateNext(null);
172             } else {
173                 // User wasn't able to confirm credentials, so we're okay
174                 // landing back at the wizard page again, where they read
175                 // instructions again and tap "Next" to try again.
176                 Log.w(TAG, "Failed to confirm credentials");
177             }
178         } else {
179             super.onActivityResult(requestCode, resultCode, data);
180         }
181     }
182 }
183