diff options
Diffstat (limited to 'core/java')
| -rw-r--r-- | core/java/android/os/Power.java | 10 | ||||
| -rw-r--r-- | core/java/android/os/storage/IMountService.aidl | 4 | ||||
| -rw-r--r-- | core/java/android/os/storage/IMountShutdownObserver.aidl | 33 | ||||
| -rw-r--r-- | core/java/com/android/internal/app/ShutdownThread.java | 100 |
4 files changed, 113 insertions, 34 deletions
diff --git a/core/java/android/os/Power.java b/core/java/android/os/Power.java index b3df52246f49..5a7921590156 100644 --- a/core/java/android/os/Power.java +++ b/core/java/android/os/Power.java @@ -18,7 +18,6 @@ package android.os; import java.io.IOException; import android.os.ServiceManager; -import android.os.storage.IMountService; /** * Class that provides access to some of the power management functions. @@ -101,15 +100,6 @@ public class Power */ 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); } diff --git a/core/java/android/os/storage/IMountService.aidl b/core/java/android/os/storage/IMountService.aidl index ad4cb105c708..75455ab35b44 100644 --- a/core/java/android/os/storage/IMountService.aidl +++ b/core/java/android/os/storage/IMountService.aidl @@ -18,6 +18,7 @@ package android.os.storage; import android.os.storage.IMountServiceListener; +import android.os.storage.IMountShutdownObserver; /** WARNING! Update IMountService.h and IMountService.cpp if you change this file. * In particular, the ordering of the methods below must match the @@ -142,6 +143,7 @@ interface IMountService /** * Shuts down the MountService and gracefully unmounts all external media. + * Invokes call back once the shutdown is complete. */ - void shutdown(); + void shutdown(IMountShutdownObserver observer); } diff --git a/core/java/android/os/storage/IMountShutdownObserver.aidl b/core/java/android/os/storage/IMountShutdownObserver.aidl new file mode 100644 index 000000000000..0aa8a4592ab6 --- /dev/null +++ b/core/java/android/os/storage/IMountShutdownObserver.aidl @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.os.storage; + +/** + * Callback class for receiving events related + * to shutdown. + * + * @hide - For internal consumption only. + */ +interface IMountShutdownObserver { + /** + * This method is called when the shutdown + * of MountService completed. + * @param statusCode indicates success or failure + * of the shutdown. + */ + void onShutDownComplete(int statusCode); +} diff --git a/core/java/com/android/internal/app/ShutdownThread.java b/core/java/com/android/internal/app/ShutdownThread.java index 37898a1da3d7..51cd0f818ae7 100644 --- a/core/java/com/android/internal/app/ShutdownThread.java +++ b/core/java/com/android/internal/app/ShutdownThread.java @@ -28,12 +28,13 @@ import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.os.Handler; +import android.os.Power; import android.os.PowerManager; import android.os.RemoteException; -import android.os.Power; import android.os.ServiceManager; import android.os.SystemClock; import android.os.storage.IMountService; +import android.os.storage.IMountShutdownObserver; import com.android.internal.telephony.ITelephony; import android.util.Log; @@ -46,16 +47,20 @@ public final class ShutdownThread extends Thread { private static final int PHONE_STATE_POLL_SLEEP_MSEC = 500; // maximum time we wait for the shutdown broadcast before going on. private static final int MAX_BROADCAST_TIME = 10*1000; + private static final int MAX_SHUTDOWN_WAIT_TIME = 20*1000; // state tracking private static Object sIsStartedGuard = new Object(); private static boolean sIsStarted = false; + private static boolean mReboot; + private static String mRebootReason; + // static instance of this thread private static final ShutdownThread sInstance = new ShutdownThread(); - private final Object mBroadcastDoneSync = new Object(); - private boolean mBroadcastDone; + private final Object mActionDoneSync = new Object(); + private boolean mActionDone; private Context mContext; private PowerManager mPowerManager; private PowerManager.WakeLock mWakeLock; @@ -64,12 +69,13 @@ public final class ShutdownThread extends Thread { private ShutdownThread() { } - /** + /** * Request a clean shutdown, waiting for subsystems to clean up their * state etc. Must be called from a Looper thread in which its UI * is shown. - * + * * @param context Context used to display the shutdown progress dialog. + * @param confirm true if user confirmation is needed before shutting down. */ public static void shutdown(final Context context, boolean confirm) { // ensure that only one thread is trying to power down. @@ -106,6 +112,21 @@ public final class ShutdownThread extends Thread { } } + /** + * Request a clean shutdown, waiting for subsystems to clean up their + * state etc. Must be called from a Looper thread in which its UI + * is shown. + * + * @param context Context used to display the shutdown progress dialog. + * @param reason code to pass to the kernel (e.g. "recovery"), or null. + * @param confirm true if user confirmation is needed before shutting down. + */ + public static void reboot(final Context context, String reason, boolean confirm) { + mReboot = true; + mRebootReason = reason; + shutdown(context, confirm); + } + private static void beginShutdownSequence(Context context) { synchronized (sIsStartedGuard) { sIsStarted = true; @@ -145,13 +166,13 @@ public final class ShutdownThread extends Thread { sInstance.start(); } - void broadcastDone() { - synchronized (mBroadcastDoneSync) { - mBroadcastDone = true; - mBroadcastDoneSync.notifyAll(); + void actionDone() { + synchronized (mActionDoneSync) { + mActionDone = true; + mActionDoneSync.notifyAll(); } } - + /** * Makes sure we handle the shutdown gracefully. * Shuts off power regardless of radio and bluetooth state if the alloted time has passed. @@ -163,27 +184,27 @@ public final class ShutdownThread extends Thread { BroadcastReceiver br = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { // We don't allow apps to cancel this, so ignore the result. - broadcastDone(); + actionDone(); } }; Log.i(TAG, "Sending shutdown broadcast..."); // First send the high-level shut down broadcast. - mBroadcastDone = false; + mActionDone = false; mContext.sendOrderedBroadcast(new Intent(Intent.ACTION_SHUTDOWN), null, br, mHandler, 0, null, null); final long endTime = System.currentTimeMillis() + MAX_BROADCAST_TIME; - synchronized (mBroadcastDoneSync) { - while (!mBroadcastDone) { + synchronized (mActionDoneSync) { + while (!mActionDone) { long delay = endTime - System.currentTimeMillis(); if (delay <= 0) { Log.w(TAG, "Shutdown broadcast timed out"); break; } try { - mBroadcastDoneSync.wait(delay); + mActionDoneSync.wait(delay); } catch (InterruptedException e) { } } @@ -262,17 +283,50 @@ public final class ShutdownThread extends Thread { } // Shutdown MountService to ensure media is in a safe state - try { - if (mount != null) { - mount.shutdown(); - } else { - Log.w(TAG, "MountService unavailable for shutdown"); + IMountShutdownObserver observer = new IMountShutdownObserver.Stub() { + public void onShutDownComplete(int statusCode) throws RemoteException { + Log.w(TAG, "Result code " + statusCode + " from MountService.shutdown"); + actionDone(); + } + }; + + Log.i(TAG, "Shutting down MountService"); + // Set initial variables and time out time. + mActionDone = false; + final long endShutTime = System.currentTimeMillis() + MAX_SHUTDOWN_WAIT_TIME; + synchronized (mActionDoneSync) { + try { + if (mount != null) { + mount.shutdown(observer); + } else { + Log.w(TAG, "MountService unavailable for shutdown"); + } + } catch (Exception e) { + Log.e(TAG, "Exception during MountService shutdown", e); + } + while (!mActionDone) { + long delay = endShutTime - System.currentTimeMillis(); + if (delay <= 0) { + Log.w(TAG, "Shutdown wait timed out"); + break; + } + try { + mActionDoneSync.wait(delay); + } catch (InterruptedException e) { + } + } + } + + if (mReboot) { + Log.i(TAG, "Rebooting, reason: " + mRebootReason); + try { + Power.reboot(mRebootReason); + } catch (Exception e) { + Log.e(TAG, "Reboot failed, will attempt shutdown instead", e); } - } catch (Exception e) { - Log.e(TAG, "Exception during MountService shutdown", e); } - //shutdown power + // Shutdown power Log.i(TAG, "Performing low-level shutdown..."); Power.shutdown(); } |
