Merge commit '424991704b5fb7a64f6cf0fcc3f4b1aabbf2a2e0' into gingerbread-plus-aosp * commit '424991704b5fb7a64f6cf0fcc3f4b1aabbf2a2e0': Implement issue #3094621 and #3094609 - wipe sd card
This commit is contained in:
@ -31104,6 +31104,17 @@
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="WIPE_EXTERNAL_STORAGE"
|
||||
type="int"
|
||||
transient="false"
|
||||
volatile="false"
|
||||
value="1"
|
||||
static="true"
|
||||
final="true"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
</class>
|
||||
</package>
|
||||
<package name="android.app.backup"
|
||||
|
@ -762,6 +762,13 @@ public class ActivityManager {
|
||||
*/
|
||||
public static final int FLAG_CANT_SAVE_STATE = 1<<0;
|
||||
|
||||
/**
|
||||
* Constant for {@link #flags}: this process is associated with a
|
||||
* persistent system app.
|
||||
* @hide
|
||||
*/
|
||||
public static final int FLAG_PERSISTENT = 1<<1;
|
||||
|
||||
/**
|
||||
* Flags of information. May be any of
|
||||
* {@link #FLAG_CANT_SAVE_STATE}.
|
||||
|
@ -510,6 +510,12 @@ public class DevicePolicyManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Flag for {@link #wipeData(int)}: also erase the device's external
|
||||
* storage.
|
||||
*/
|
||||
public static final int WIPE_EXTERNAL_STORAGE = 0x0001;
|
||||
|
||||
/**
|
||||
* Ask the user date be wiped. This will cause the device to reboot,
|
||||
* erasing all user data while next booting up. External storage such
|
||||
|
@ -0,0 +1,228 @@
|
||||
package com.android.internal.os.storage;
|
||||
|
||||
import android.app.ProgressDialog;
|
||||
import android.app.Service;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.os.Environment;
|
||||
import android.os.IBinder;
|
||||
import android.os.PowerManager;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceManager;
|
||||
import android.os.storage.IMountService;
|
||||
import android.os.storage.StorageEventListener;
|
||||
import android.os.storage.StorageManager;
|
||||
import android.util.Log;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.android.internal.R;
|
||||
|
||||
/**
|
||||
* Takes care of unmounting and formatting external storage.
|
||||
*/
|
||||
public class ExternalStorageFormatter extends Service
|
||||
implements DialogInterface.OnCancelListener {
|
||||
static final String TAG = "ExternalStorageFormatter";
|
||||
|
||||
public static final String FORMAT_ONLY = "com.android.internal.os.storage.FORMAT_ONLY";
|
||||
public static final String FORMAT_AND_FACTORY_RESET = "com.android.internal.os.storage.FORMAT_AND_FACTORY_RESET";
|
||||
|
||||
public static final String EXTRA_ALWAYS_RESET = "always_reset";
|
||||
|
||||
public static final ComponentName COMPONENT_NAME
|
||||
= new ComponentName("android", ExternalStorageFormatter.class.getName());
|
||||
|
||||
// Access using getMountService()
|
||||
private IMountService mMountService = null;
|
||||
|
||||
private StorageManager mStorageManager = null;
|
||||
|
||||
private PowerManager.WakeLock mWakeLock;
|
||||
|
||||
private ProgressDialog mProgressDialog = null;
|
||||
|
||||
private boolean mFactoryReset = false;
|
||||
private boolean mAlwaysReset = false;
|
||||
|
||||
StorageEventListener mStorageListener = new StorageEventListener() {
|
||||
@Override
|
||||
public void onStorageStateChanged(String path, String oldState, String newState) {
|
||||
Log.i(TAG, "Received storage state changed notification that " +
|
||||
path + " changed state from " + oldState +
|
||||
" to " + newState);
|
||||
updateProgressState();
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
|
||||
if (mStorageManager == null) {
|
||||
mStorageManager = (StorageManager) getSystemService(Context.STORAGE_SERVICE);
|
||||
mStorageManager.registerListener(mStorageListener);
|
||||
}
|
||||
|
||||
mWakeLock = ((PowerManager)getSystemService(Context.POWER_SERVICE))
|
||||
.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ExternalStorageFormatter");
|
||||
mWakeLock.acquire();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
if (FORMAT_AND_FACTORY_RESET.equals(intent.getAction())) {
|
||||
mFactoryReset = true;
|
||||
}
|
||||
if (intent.getBooleanExtra(EXTRA_ALWAYS_RESET, false)) {
|
||||
mAlwaysReset = true;
|
||||
}
|
||||
|
||||
if (mProgressDialog == null) {
|
||||
mProgressDialog = new ProgressDialog(this);
|
||||
mProgressDialog.setIndeterminate(true);
|
||||
mProgressDialog.setCancelable(true);
|
||||
mProgressDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
|
||||
if (!mAlwaysReset) {
|
||||
mProgressDialog.setOnCancelListener(this);
|
||||
}
|
||||
updateProgressState();
|
||||
mProgressDialog.show();
|
||||
}
|
||||
|
||||
return Service.START_REDELIVER_INTENT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
if (mStorageManager != null) {
|
||||
mStorageManager.unregisterListener(mStorageListener);
|
||||
}
|
||||
if (mProgressDialog != null) {
|
||||
mProgressDialog.dismiss();
|
||||
}
|
||||
mWakeLock.release();
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel(DialogInterface dialog) {
|
||||
IMountService mountService = getMountService();
|
||||
String extStoragePath = Environment.getExternalStorageDirectory().toString();
|
||||
try {
|
||||
mountService.mountVolume(extStoragePath);
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Failed talking with mount service", e);
|
||||
}
|
||||
stopSelf();
|
||||
}
|
||||
|
||||
void fail(int msg) {
|
||||
Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
|
||||
if (mAlwaysReset) {
|
||||
sendBroadcast(new Intent("android.intent.action.MASTER_CLEAR"));
|
||||
}
|
||||
stopSelf();
|
||||
}
|
||||
|
||||
void updateProgressState() {
|
||||
String status = Environment.getExternalStorageState();
|
||||
if (Environment.MEDIA_MOUNTED.equals(status)
|
||||
|| Environment.MEDIA_MOUNTED_READ_ONLY.equals(status)) {
|
||||
updateProgressDialog(R.string.progress_unmounting);
|
||||
IMountService mountService = getMountService();
|
||||
String extStoragePath = Environment.getExternalStorageDirectory().toString();
|
||||
try {
|
||||
mountService.unmountVolume(extStoragePath, true);
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Failed talking with mount service", e);
|
||||
}
|
||||
} else if (Environment.MEDIA_NOFS.equals(status)
|
||||
|| Environment.MEDIA_UNMOUNTED.equals(status)
|
||||
|| Environment.MEDIA_UNMOUNTABLE.equals(status)) {
|
||||
updateProgressDialog(R.string.progress_erasing);
|
||||
final IMountService mountService = getMountService();
|
||||
final String extStoragePath = Environment.getExternalStorageDirectory().toString();
|
||||
if (mountService != null) {
|
||||
new Thread() {
|
||||
public void run() {
|
||||
boolean success = false;
|
||||
try {
|
||||
mountService.formatVolume(extStoragePath);
|
||||
success = true;
|
||||
} catch (Exception e) {
|
||||
Toast.makeText(ExternalStorageFormatter.this,
|
||||
R.string.format_error, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
if (success) {
|
||||
if (mFactoryReset) {
|
||||
sendBroadcast(new Intent("android.intent.action.MASTER_CLEAR"));
|
||||
// Intent handling is asynchronous -- assume it will happen soon.
|
||||
stopSelf();
|
||||
return;
|
||||
}
|
||||
}
|
||||
// If we didn't succeed, or aren't doing a full factory
|
||||
// reset, then it is time to remount the storage.
|
||||
if (!success && mAlwaysReset) {
|
||||
sendBroadcast(new Intent("android.intent.action.MASTER_CLEAR"));
|
||||
} else {
|
||||
try {
|
||||
mountService.mountVolume(extStoragePath);
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Failed talking with mount service", e);
|
||||
}
|
||||
}
|
||||
stopSelf();
|
||||
return;
|
||||
}
|
||||
}.start();
|
||||
} else {
|
||||
Log.w("MediaFormat", "Unable to locate IMountService");
|
||||
}
|
||||
} else if (Environment.MEDIA_BAD_REMOVAL.equals(status)) {
|
||||
fail(R.string.media_bad_removal);
|
||||
} else if (Environment.MEDIA_CHECKING.equals(status)) {
|
||||
fail(R.string.media_checking);
|
||||
} else if (Environment.MEDIA_REMOVED.equals(status)) {
|
||||
fail(R.string.media_removed);
|
||||
} else if (Environment.MEDIA_SHARED.equals(status)) {
|
||||
fail(R.string.media_shared);
|
||||
} else {
|
||||
fail(R.string.media_unknown_state);
|
||||
Log.w(TAG, "Unknown storage state: " + status);
|
||||
stopSelf();
|
||||
}
|
||||
}
|
||||
|
||||
public void updateProgressDialog(int msg) {
|
||||
if (mProgressDialog == null) {
|
||||
mProgressDialog = new ProgressDialog(this);
|
||||
mProgressDialog.setIndeterminate(true);
|
||||
mProgressDialog.setCancelable(false);
|
||||
mProgressDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
|
||||
mProgressDialog.show();
|
||||
}
|
||||
|
||||
mProgressDialog.setMessage(getText(msg));
|
||||
}
|
||||
|
||||
IMountService getMountService() {
|
||||
if (mMountService == null) {
|
||||
IBinder service = ServiceManager.getService("mount");
|
||||
if (service != null) {
|
||||
mMountService = IMountService.Stub.asInterface(service);
|
||||
} else {
|
||||
Log.e(TAG, "Can't get mount service");
|
||||
}
|
||||
}
|
||||
return mMountService;
|
||||
}
|
||||
}
|
@ -1371,7 +1371,8 @@
|
||||
</receiver>
|
||||
|
||||
<receiver android:name="com.android.server.MasterClearReceiver"
|
||||
android:permission="android.permission.MASTER_CLEAR" >
|
||||
android:permission="android.permission.MASTER_CLEAR"
|
||||
android:priority="100" >
|
||||
<intent-filter>
|
||||
<!-- For Checkin, Settings, etc.: action=MASTER_CLEAR -->
|
||||
<action android:name="android.intent.action.MASTER_CLEAR" />
|
||||
@ -1381,8 +1382,11 @@
|
||||
<category android:name="android.intent.category.MASTER_CLEAR" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<service android:name="com.android.internal.os.storage.ExternalStorageFormatter"
|
||||
android:permission="android.permission.MASTER_CLEAR"
|
||||
android:exported="true" />
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
||||
|
||||
|
@ -2337,4 +2337,33 @@
|
||||
<!-- Shown when the users bandwidth is reduced because of excessive data use -->
|
||||
<string name="throttled_notification_title">Mobile data limit exceeded</string>
|
||||
<string name="throttled_notification_message">Touch to learn more about mobile data use</string>
|
||||
|
||||
<!-- Strings for ExternalStorageFormatter service. -->
|
||||
<!-- Text for progress dialog while unmounting USB storage volume [CHAR LIMIT=NONE] -->
|
||||
<string name="progress_unmounting" product="nosdcard">Unmounting USB storage...</string>
|
||||
<!-- Text for progress dialog while unmounting SD card [CHAR LIMIT=NONE] -->
|
||||
<string name="progress_unmounting" product="default">Unmounting SD card...</string>
|
||||
<!-- Text for progress dialog while erasing USB storage volume [CHAR LIMIT=NONE] -->
|
||||
<string name="progress_erasing" product="nosdcard">Erasing USB storage...</string>
|
||||
<!-- Text for progress dialog while erasing SD card [CHAR LIMIT=NONE] -->
|
||||
<string name="progress_erasing" product="default">Erasing SD card...</string>
|
||||
<!-- Text for message to user that an error happened when formatting USB storage [CHAR LIMIT=NONE] -->
|
||||
<string name="format_error" product="nosdcard">Failed to erase USB storage.</string>
|
||||
<!-- Text for message to user that an error happened when formatting SD card [CHAR LIMIT=NONE] -->
|
||||
<string name="format_error" product="default">Failed to erase SD card.</string>
|
||||
<!-- Text for message to user that SD card has been removed while in use [CHAR LIMIT=NONE] -->
|
||||
<string name="media_bad_removal">SD card was removed before being unmounted.</string>
|
||||
<!-- Text for message to user USB storage is currently being checked [CHAR LIMIT=NONE] -->
|
||||
<string name="media_checking" product="nosdcard">USB storage is currently being checked.</string>
|
||||
<!-- Text for message to user SD card is currently being checked [CHAR LIMIT=NONE] -->
|
||||
<string name="media_checking" product="default">SD card is currently being checked.</string>
|
||||
<!-- Text for message to user SD card has been removed [CHAR LIMIT=NONE] -->
|
||||
<string name="media_removed">SD card has been removed.</string>
|
||||
<!-- Text for message to user USB storage is currently mounted on a computer [CHAR LIMIT=NONE] -->
|
||||
<string name="media_shared" product="nosdcard">USB storage is currently in use by a computer.</string>
|
||||
<!-- Text for message to user SD card is currently mounted on a computer [CHAR LIMIT=NONE] -->
|
||||
<string name="media_shared" product="default">SD card is currently in use by a computer.</string>
|
||||
<!-- Text for message for an unknown external media state [CHAR LIMIT=NONE] -->
|
||||
<string name="media_unknown_state">External media in unknown state.</string>
|
||||
|
||||
</resources>
|
||||
|
@ -17,6 +17,7 @@
|
||||
package com.android.server;
|
||||
|
||||
import com.android.internal.content.PackageMonitor;
|
||||
import com.android.internal.os.storage.ExternalStorageFormatter;
|
||||
import com.android.internal.util.FastXmlSerializer;
|
||||
import com.android.internal.util.JournaledFile;
|
||||
import com.android.internal.util.XmlUtils;
|
||||
@ -41,6 +42,7 @@ import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
import android.os.IPowerManager;
|
||||
import android.os.PowerManager;
|
||||
import android.os.RecoverySystem;
|
||||
import android.os.RemoteCallback;
|
||||
import android.os.RemoteException;
|
||||
@ -71,6 +73,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
|
||||
|
||||
final Context mContext;
|
||||
final MyPackageMonitor mMonitor;
|
||||
final PowerManager.WakeLock mWakeLock;
|
||||
|
||||
IPowerManager mIPowerManager;
|
||||
|
||||
@ -216,6 +219,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
|
||||
mContext = context;
|
||||
mMonitor = new MyPackageMonitor();
|
||||
mMonitor.register(context, true);
|
||||
mWakeLock = ((PowerManager)context.getSystemService(Context.POWER_SERVICE))
|
||||
.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "DPM");
|
||||
}
|
||||
|
||||
private IPowerManager getIPowerManager() {
|
||||
@ -862,10 +867,17 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
|
||||
}
|
||||
|
||||
void wipeDataLocked(int flags) {
|
||||
try {
|
||||
RecoverySystem.rebootWipeUserData(mContext);
|
||||
} catch (IOException e) {
|
||||
Slog.w(TAG, "Failed requesting data wipe", e);
|
||||
if ((flags&DevicePolicyManager.WIPE_EXTERNAL_STORAGE) != 0) {
|
||||
Intent intent = new Intent(ExternalStorageFormatter.FORMAT_AND_FACTORY_RESET);
|
||||
intent.setComponent(ExternalStorageFormatter.COMPONENT_NAME);
|
||||
mWakeLock.acquire(10000);
|
||||
mContext.startService(intent);
|
||||
} else {
|
||||
try {
|
||||
RecoverySystem.rebootWipeUserData(mContext);
|
||||
} catch (IOException e) {
|
||||
Slog.w(TAG, "Failed requesting data wipe", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,7 @@ public class MasterClearReceiver extends BroadcastReceiver {
|
||||
private static final String TAG = "MasterClear";
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
public void onReceive(final Context context, final Intent intent) {
|
||||
if (intent.getAction().equals(Intent.ACTION_REMOTE_INTENT)) {
|
||||
if (!"google.com".equals(intent.getStringExtra("from"))) {
|
||||
Slog.w(TAG, "Ignoring master clear request -- not from trusted server.");
|
||||
@ -37,16 +37,23 @@ public class MasterClearReceiver extends BroadcastReceiver {
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
Slog.w(TAG, "!!! FACTORY RESET !!!");
|
||||
if (intent.hasExtra("enableEFS")) {
|
||||
RecoverySystem.rebootToggleEFS(context, intent.getBooleanExtra("enableEFS", false));
|
||||
} else {
|
||||
RecoverySystem.rebootWipeUserData(context);
|
||||
Slog.w(TAG, "!!! FACTORY RESET !!!");
|
||||
// The reboot call is blocking, so we need to do it on another thread.
|
||||
Thread thr = new Thread("Reboot") {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
if (intent.hasExtra("enableEFS")) {
|
||||
RecoverySystem.rebootToggleEFS(context, intent.getBooleanExtra("enableEFS", false));
|
||||
} else {
|
||||
RecoverySystem.rebootWipeUserData(context);
|
||||
}
|
||||
Log.wtf(TAG, "Still running after master clear?!");
|
||||
} catch (IOException e) {
|
||||
Slog.e(TAG, "Can't perform master clear/factory reset", e);
|
||||
}
|
||||
}
|
||||
Log.wtf(TAG, "Still running after master clear?!");
|
||||
} catch (IOException e) {
|
||||
Slog.e(TAG, "Can't perform master clear/factory reset", e);
|
||||
}
|
||||
};
|
||||
thr.start();
|
||||
}
|
||||
}
|
||||
|
@ -7063,6 +7063,9 @@ public final class ActivityManagerService extends ActivityManagerNative
|
||||
if (mHeavyWeightProcess == app) {
|
||||
currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_CANT_SAVE_STATE;
|
||||
}
|
||||
if (app.persistent) {
|
||||
currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_PERSISTENT;
|
||||
}
|
||||
int adj = app.curAdj;
|
||||
if (adj >= EMPTY_APP_ADJ) {
|
||||
currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
|
||||
|
Reference in New Issue
Block a user