1705073f7565ae8509c367808a68aa9c569e13247Geoff Lang/* 2705073f7565ae8509c367808a68aa9c569e13247Geoff Lang * Copyright (C) 2008 The Android Open Source Project 3705073f7565ae8509c367808a68aa9c569e13247Geoff Lang * 4705073f7565ae8509c367808a68aa9c569e13247Geoff Lang * Licensed under the Apache License, Version 2.0 (the "License"); 5705073f7565ae8509c367808a68aa9c569e13247Geoff Lang * you may not use this file except in compliance with the License. 6705073f7565ae8509c367808a68aa9c569e13247Geoff Lang * You may obtain a copy of the License at 7705073f7565ae8509c367808a68aa9c569e13247Geoff Lang * 8705073f7565ae8509c367808a68aa9c569e13247Geoff Lang * http://www.apache.org/licenses/LICENSE-2.0 9705073f7565ae8509c367808a68aa9c569e13247Geoff Lang * 10705073f7565ae8509c367808a68aa9c569e13247Geoff Lang * Unless required by applicable law or agreed to in writing, software 11705073f7565ae8509c367808a68aa9c569e13247Geoff Lang * distributed under the License is distributed on an "AS IS" BASIS, 12705073f7565ae8509c367808a68aa9c569e13247Geoff Lang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13705073f7565ae8509c367808a68aa9c569e13247Geoff Lang * See the License for the specific language governing permissions and 14705073f7565ae8509c367808a68aa9c569e13247Geoff Lang * limitations under the License. 15705073f7565ae8509c367808a68aa9c569e13247Geoff Lang */ 16705073f7565ae8509c367808a68aa9c569e13247Geoff Lang 17705073f7565ae8509c367808a68aa9c569e13247Geoff Langpackage com.android.settings; 18705073f7565ae8509c367808a68aa9c569e13247Geoff Lang 19705073f7565ae8509c367808a68aa9c569e13247Geoff Langimport android.app.Activity; 20705073f7565ae8509c367808a68aa9c569e13247Geoff Langimport android.content.Intent; 21705073f7565ae8509c367808a68aa9c569e13247Geoff Langimport android.os.Bundle; 22705073f7565ae8509c367808a68aa9c569e13247Geoff Langimport android.os.storage.StorageVolume; 23705073f7565ae8509c367808a68aa9c569e13247Geoff Langimport android.view.LayoutInflater; 24705073f7565ae8509c367808a68aa9c569e13247Geoff Langimport android.view.View; 25705073f7565ae8509c367808a68aa9c569e13247Geoff Langimport android.widget.Button; 26705073f7565ae8509c367808a68aa9c569e13247Geoff Lang 27705073f7565ae8509c367808a68aa9c569e13247Geoff Langimport com.android.internal.os.storage.ExternalStorageFormatter; 28705073f7565ae8509c367808a68aa9c569e13247Geoff Lang 29705073f7565ae8509c367808a68aa9c569e13247Geoff Lang/** 30705073f7565ae8509c367808a68aa9c569e13247Geoff Lang * Confirm and execute a format of the sdcard. 31705073f7565ae8509c367808a68aa9c569e13247Geoff Lang * Multiple confirmations are required: first, a general "are you sure 32705073f7565ae8509c367808a68aa9c569e13247Geoff Lang * you want to do this?" prompt, followed by a keyguard pattern trace if the user 33705073f7565ae8509c367808a68aa9c569e13247Geoff Lang * has defined one, followed by a final strongly-worded "THIS WILL ERASE EVERYTHING 34705073f7565ae8509c367808a68aa9c569e13247Geoff Lang * ON THE SD CARD" prompt. If at any time the phone is allowed to go to sleep, is 35705073f7565ae8509c367808a68aa9c569e13247Geoff Lang * locked, et cetera, then the confirmation sequence is abandoned. 36705073f7565ae8509c367808a68aa9c569e13247Geoff Lang */ 37705073f7565ae8509c367808a68aa9c569e13247Geoff Langpublic class MediaFormat extends Activity { 38705073f7565ae8509c367808a68aa9c569e13247Geoff Lang 39705073f7565ae8509c367808a68aa9c569e13247Geoff Lang private static final int KEYGUARD_REQUEST = 55; 40705073f7565ae8509c367808a68aa9c569e13247Geoff Lang 41705073f7565ae8509c367808a68aa9c569e13247Geoff Lang private LayoutInflater mInflater; 42705073f7565ae8509c367808a68aa9c569e13247Geoff Lang 43705073f7565ae8509c367808a68aa9c569e13247Geoff Lang private View mInitialView; 44705073f7565ae8509c367808a68aa9c569e13247Geoff Lang private Button mInitiateButton; 45705073f7565ae8509c367808a68aa9c569e13247Geoff Lang 46705073f7565ae8509c367808a68aa9c569e13247Geoff Lang private View mFinalView; 47705073f7565ae8509c367808a68aa9c569e13247Geoff Lang private Button mFinalButton; 48705073f7565ae8509c367808a68aa9c569e13247Geoff Lang 49705073f7565ae8509c367808a68aa9c569e13247Geoff Lang /** 50705073f7565ae8509c367808a68aa9c569e13247Geoff Lang * The user has gone through the multiple confirmation, so now we go ahead 51f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang * and invoke the Mount Service to format the SD card. 52f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang */ 53f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang private Button.OnClickListener mFinalClickListener = new Button.OnClickListener() { 54f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang public void onClick(View v) { 55f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang 56f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang if (Utils.isMonkeyRunning()) { 57f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang return; 58f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang } 59f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang Intent intent = new Intent(ExternalStorageFormatter.FORMAT_ONLY); 60f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang intent.setComponent(ExternalStorageFormatter.COMPONENT_NAME); 61f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang // Transfer the storage volume to the new intent 62f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang final StorageVolume storageVolume = getIntent().getParcelableExtra( 63f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang StorageVolume.EXTRA_STORAGE_VOLUME); 64f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang intent.putExtra(StorageVolume.EXTRA_STORAGE_VOLUME, storageVolume); 65f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang startService(intent); 66f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang finish(); 67f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang } 68f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang }; 69f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang 70f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang /** 71f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang * Keyguard validation is run using the standard {@link ConfirmLockPattern} 72f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang * component as a subactivity 73f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang */ 74f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang private boolean runKeyguardConfirmation(int request) { 75f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang return new ChooseLockSettingsHelper(this) 76f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang .launchConfirmationActivity(request, 77f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang getText(R.string.media_format_gesture_prompt), 78f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang getText(R.string.media_format_gesture_explanation)); 79f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang } 80f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang 81f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang @Override 82f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang protected void onActivityResult(int requestCode, int resultCode, Intent data) { 83f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang super.onActivityResult(requestCode, resultCode, data); 84f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang 85f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang if (requestCode != KEYGUARD_REQUEST) { 86f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang return; 87f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang } 88f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang 89f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang // If the user entered a valid keyguard trace, present the final 90f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang // confirmation prompt; otherwise, go back to the initial state. 91f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang if (resultCode == Activity.RESULT_OK) { 92f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang establishFinalConfirmationState(); 93f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang } else if (resultCode == Activity.RESULT_CANCELED) { 94f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang finish(); 95f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang } else { 96f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang establishInitialState(); 97f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang } 98f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang } 99f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang 100f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang /** 101f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang * If the user clicks to begin the reset sequence, we next require a 102f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang * keyguard confirmation if the user has currently enabled one. If there 103f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang * is no keyguard available, we simply go to the final confirmation prompt. 104f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang */ 105f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang private Button.OnClickListener mInitiateListener = new Button.OnClickListener() { 106f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang public void onClick(View v) { 107f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang if (!runKeyguardConfirmation(KEYGUARD_REQUEST)) { 108f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang establishFinalConfirmationState(); 109f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang } 110f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang } 111f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang }; 112f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang 113f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang /** 114f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang * Configure the UI for the final confirmation interaction 115f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang */ 116f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang private void establishFinalConfirmationState() { 117f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang if (mFinalView == null) { 118f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang mFinalView = mInflater.inflate(R.layout.media_format_final, null); 119f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang mFinalButton = 120f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang (Button) mFinalView.findViewById(R.id.execute_media_format); 121f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang mFinalButton.setOnClickListener(mFinalClickListener); 122f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang } 123f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang 124f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang setContentView(mFinalView); 125f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang } 126f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang 127f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang /** 128f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang * In its initial state, the activity presents a button for the user to 129f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang * click in order to initiate a confirmation sequence. This method is 130f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang * called from various other points in the code to reset the activity to 131f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang * this base state. 132f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang * 133f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang * <p>Reinflating views from resources is expensive and prevents us from 134f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang * caching widget pointers, so we use a single-inflate pattern: we lazy- 135f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang * inflate each view, caching all of the widget pointers we'll need at the 136f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang * time, then simply reuse the inflated views directly whenever we need 137f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang * to change contents. 138f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang */ 139f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang private void establishInitialState() { 140f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang if (mInitialView == null) { 141f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang mInitialView = mInflater.inflate(R.layout.media_format_primary, null); 142f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang mInitiateButton = 143f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang (Button) mInitialView.findViewById(R.id.initiate_media_format); 144f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang mInitiateButton.setOnClickListener(mInitiateListener); 145f6139359a16220c0e29695b23b3707d3d6f053eaGeoff Lang } 146 147 setContentView(mInitialView); 148 } 149 150 @Override 151 protected void onCreate(Bundle savedState) { 152 super.onCreate(savedState); 153 154 mInitialView = null; 155 mFinalView = null; 156 mInflater = LayoutInflater.from(this); 157 158 establishInitialState(); 159 } 160 161 /** Abandon all progress through the confirmation sequence by returning 162 * to the initial view any time the activity is interrupted (e.g. by 163 * idle timeout). 164 */ 165 @Override 166 public void onPause() { 167 super.onPause(); 168 169 if (!isFinishing()) { 170 establishInitialState(); 171 } 172 } 173} 174