am c93c70c4
: Merge "framework: storage: Ensure that filesystems are unmounted before shutdown/reboot" into eclair
Merge commit 'c93c70c4b849d31ff1b5e5cf2fb9462fd60e5da0' into eclair-plus-aosp * commit 'c93c70c4b849d31ff1b5e5cf2fb9462fd60e5da0': framework: storage: Ensure that filesystems are unmounted before shutdown/reboot
This commit is contained in:
@ -75,4 +75,9 @@ interface IMountService
|
|||||||
* when a UMS host is detected.
|
* when a UMS host is detected.
|
||||||
*/
|
*/
|
||||||
void setAutoStartUms(boolean value);
|
void setAutoStartUms(boolean value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shuts down the MountService and gracefully unmounts all external media.
|
||||||
|
*/
|
||||||
|
void shutdown();
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,8 @@
|
|||||||
package android.os;
|
package android.os;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import android.os.ServiceManager;
|
||||||
|
import android.os.IMountService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class that provides access to some of the power management functions.
|
* Class that provides access to some of the power management functions.
|
||||||
@ -97,5 +99,19 @@ public class Power
|
|||||||
* @throws IOException if reboot fails for some reason (eg, lack of
|
* @throws IOException if reboot fails for some reason (eg, lack of
|
||||||
* permission)
|
* permission)
|
||||||
*/
|
*/
|
||||||
public static native void reboot(String reason) throws IOException;
|
public static void reboot(String reason) throws IOException
|
||||||
|
{
|
||||||
|
IMountService mSvc = IMountService.Stub.asInterface(
|
||||||
|
ServiceManager.getService("mount"));
|
||||||
|
|
||||||
|
if (mSvc != null) {
|
||||||
|
try {
|
||||||
|
mSvc.shutdown();
|
||||||
|
} catch (Exception e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rebootNative(reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static native void rebootNative(String reason) throws IOException ;
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,7 @@ import android.os.RemoteException;
|
|||||||
import android.os.Power;
|
import android.os.Power;
|
||||||
import android.os.ServiceManager;
|
import android.os.ServiceManager;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
|
import android.os.IMountService;
|
||||||
|
|
||||||
import com.android.internal.telephony.ITelephony;
|
import com.android.internal.telephony.ITelephony;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
@ -189,6 +190,10 @@ public final class ShutdownThread extends Thread {
|
|||||||
final IBluetooth bluetooth =
|
final IBluetooth bluetooth =
|
||||||
IBluetooth.Stub.asInterface(ServiceManager.checkService(
|
IBluetooth.Stub.asInterface(ServiceManager.checkService(
|
||||||
BluetoothAdapter.BLUETOOTH_SERVICE));
|
BluetoothAdapter.BLUETOOTH_SERVICE));
|
||||||
|
|
||||||
|
final IMountService mount =
|
||||||
|
IMountService.Stub.asInterface(
|
||||||
|
ServiceManager.checkService("mount"));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
bluetoothOff = bluetooth == null ||
|
bluetoothOff = bluetooth == null ||
|
||||||
@ -241,6 +246,17 @@ public final class ShutdownThread extends Thread {
|
|||||||
SystemClock.sleep(PHONE_STATE_POLL_SLEEP_MSEC);
|
SystemClock.sleep(PHONE_STATE_POLL_SLEEP_MSEC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Shutdown MountService to ensure media is in a safe state
|
||||||
|
try {
|
||||||
|
if (mount != null) {
|
||||||
|
mount.shutdown();
|
||||||
|
} else {
|
||||||
|
Log.w(TAG, "MountService unavailable for shutdown");
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "Exception during MountService shutdown", e);
|
||||||
|
}
|
||||||
|
|
||||||
//shutdown power
|
//shutdown power
|
||||||
Log.i(TAG, "Performing low-level shutdown...");
|
Log.i(TAG, "Performing low-level shutdown...");
|
||||||
Power.shutdown();
|
Power.shutdown();
|
||||||
|
@ -105,7 +105,7 @@ static JNINativeMethod method_table[] = {
|
|||||||
{ "setLastUserActivityTimeout", "(J)I", (void*)setLastUserActivityTimeout },
|
{ "setLastUserActivityTimeout", "(J)I", (void*)setLastUserActivityTimeout },
|
||||||
{ "setScreenState", "(Z)I", (void*)setScreenState },
|
{ "setScreenState", "(Z)I", (void*)setScreenState },
|
||||||
{ "shutdown", "()V", (void*)android_os_Power_shutdown },
|
{ "shutdown", "()V", (void*)android_os_Power_shutdown },
|
||||||
{ "reboot", "(Ljava/lang/String;)V", (void*)android_os_Power_reboot },
|
{ "rebootNative", "(Ljava/lang/String;)V", (void*)android_os_Power_reboot },
|
||||||
};
|
};
|
||||||
|
|
||||||
int register_android_os_Power(JNIEnv *env)
|
int register_android_os_Power(JNIEnv *env)
|
||||||
|
@ -108,13 +108,86 @@ class MountService extends IMountService.Stub {
|
|||||||
|
|
||||||
BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
|
BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
|
String action = intent.getAction();
|
||||||
|
|
||||||
|
if (action.equals(Intent.ACTION_BOOT_COMPLETED)) {
|
||||||
Thread thread = new Thread(mListener, MountListener.class.getName());
|
Thread thread = new Thread(mListener, MountListener.class.getName());
|
||||||
thread.start();
|
thread.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public void shutdown() {
|
||||||
|
if (mContext.checkCallingOrSelfPermission(
|
||||||
|
android.Manifest.permission.SHUTDOWN)
|
||||||
|
!= PackageManager.PERMISSION_GRANTED) {
|
||||||
|
throw new SecurityException("Requires SHUTDOWN permission");
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.d(TAG, "Shutting down");
|
||||||
|
String state = Environment.getExternalStorageState();
|
||||||
|
|
||||||
|
if (state.equals(Environment.MEDIA_SHARED)) {
|
||||||
|
/*
|
||||||
|
* If the media is currently shared, unshare it.
|
||||||
|
* XXX: This is still dangerous!. We should not
|
||||||
|
* be rebooting at *all* if UMS is enabled, since
|
||||||
|
* the UMS host could have dirty FAT cache entries
|
||||||
|
* yet to flush.
|
||||||
|
*/
|
||||||
|
try {
|
||||||
|
setMassStorageEnabled(false);
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "ums disable failed", e);
|
||||||
|
}
|
||||||
|
} else if (state.equals(Environment.MEDIA_CHECKING)) {
|
||||||
|
/*
|
||||||
|
* If the media is being checked, then we need to wait for
|
||||||
|
* it to complete before being able to proceed.
|
||||||
|
*/
|
||||||
|
// XXX: @hackbod - Should we disable the ANR timer here?
|
||||||
|
int retries = 30;
|
||||||
|
while (state.equals(Environment.MEDIA_CHECKING) && (retries-- >=0)) {
|
||||||
|
try {
|
||||||
|
Thread.sleep(1000);
|
||||||
|
} catch (InterruptedException iex) {
|
||||||
|
Log.e(TAG, "Interrupted while waiting for media", iex);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
state = Environment.getExternalStorageState();
|
||||||
|
}
|
||||||
|
if (retries == 0) {
|
||||||
|
Log.e(TAG, "Timed out waiting for media to check");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state.equals(Environment.MEDIA_MOUNTED)) {
|
||||||
|
/*
|
||||||
|
* If the media is mounted, then gracefully unmount it.
|
||||||
|
*/
|
||||||
|
try {
|
||||||
|
String m = Environment.getExternalStorageDirectory().toString();
|
||||||
|
unmountMedia(m);
|
||||||
|
|
||||||
|
int retries = 12;
|
||||||
|
while (!state.equals(Environment.MEDIA_UNMOUNTED) && (retries-- >=0)) {
|
||||||
|
try {
|
||||||
|
Thread.sleep(1000);
|
||||||
|
} catch (InterruptedException iex) {
|
||||||
|
Log.e(TAG, "Interrupted while waiting for media", iex);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
state = Environment.getExternalStorageState();
|
||||||
|
}
|
||||||
|
if (retries == 0) {
|
||||||
|
Log.e(TAG, "Timed out waiting for media to unmount");
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "external storage unmount failed", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return true if USB mass storage support is enabled.
|
* @return true if USB mass storage support is enabled.
|
||||||
*/
|
*/
|
||||||
|
Reference in New Issue
Block a user