diff options
-rw-r--r-- | core/java/com/android/internal/app/ShutdownThread.java | 47 | ||||
-rw-r--r-- | core/res/res/values/public.xml | 2 | ||||
-rwxr-xr-x | core/res/res/values/strings.xml | 9 | ||||
-rw-r--r-- | policy/src/com/android/internal/policy/impl/GlobalActions.java | 29 | ||||
-rwxr-xr-x | services/java/com/android/server/wm/WindowManagerService.java | 8 |
5 files changed, 90 insertions, 5 deletions
diff --git a/core/java/com/android/internal/app/ShutdownThread.java b/core/java/com/android/internal/app/ShutdownThread.java index c03694f..d867ff9 100644 --- a/core/java/com/android/internal/app/ShutdownThread.java +++ b/core/java/com/android/internal/app/ShutdownThread.java @@ -64,11 +64,15 @@ public final class ShutdownThread extends Thread { private static boolean sIsStarted = false; private static boolean mReboot; + private static boolean mRebootSafeMode; private static String mRebootReason; // Provides shutdown assurance in case the system_server is killed public static final String SHUTDOWN_ACTION_PROPERTY = "sys.shutdown.requested"; + // Indicates whether we are rebooting into safe mode + public static final String REBOOT_SAFEMODE_PROPERTY = "persist.sys.safemode"; + // static instance of this thread private static final ShutdownThread sInstance = new ShutdownThread(); @@ -92,6 +96,12 @@ public final class ShutdownThread extends Thread { * @param confirm true if user confirmation is needed before shutting down. */ public static void shutdown(final Context context, boolean confirm) { + mReboot = false; + mRebootSafeMode = false; + shutdownInner(context, confirm); + } + + static void shutdownInner(final Context context, boolean confirm) { // ensure that only one thread is trying to power down. // any additional calls are just returned synchronized (sIsStartedGuard) { @@ -103,16 +113,20 @@ public final class ShutdownThread extends Thread { final int longPressBehavior = context.getResources().getInteger( com.android.internal.R.integer.config_longPressOnPowerBehavior); - final int resourceId = longPressBehavior == 2 - ? com.android.internal.R.string.shutdown_confirm_question - : com.android.internal.R.string.shutdown_confirm; + final int resourceId = mRebootSafeMode + ? com.android.internal.R.string.reboot_safemode_confirm + : (longPressBehavior == 2 + ? com.android.internal.R.string.shutdown_confirm_question + : com.android.internal.R.string.shutdown_confirm); Log.d(TAG, "Notifying thread to start shutdown longPressBehavior=" + longPressBehavior); if (confirm) { final CloseDialogReceiver closer = new CloseDialogReceiver(context); final AlertDialog dialog = new AlertDialog.Builder(context) - .setTitle(com.android.internal.R.string.power_off) + .setTitle(mRebootSafeMode + ? com.android.internal.R.string.reboot_safemode_title + : com.android.internal.R.string.power_off) .setMessage(resourceId) .setPositiveButton(com.android.internal.R.string.yes, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { @@ -162,8 +176,23 @@ public final class ShutdownThread extends Thread { */ public static void reboot(final Context context, String reason, boolean confirm) { mReboot = true; + mRebootSafeMode = false; mRebootReason = reason; - shutdown(context, confirm); + shutdownInner(context, confirm); + } + + /** + * Request a reboot into safe mode. 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 rebootSafeMode(final Context context, boolean confirm) { + mReboot = true; + mRebootSafeMode = true; + mRebootReason = null; + shutdownInner(context, confirm); } private static void beginShutdownSequence(Context context) { @@ -254,6 +283,14 @@ public final class ShutdownThread extends Thread { SystemProperties.set(SHUTDOWN_ACTION_PROPERTY, reason); } + /* + * If we are rebooting into safe mode, write a system property + * indicating so. + */ + if (mRebootSafeMode) { + SystemProperties.set(REBOOT_SAFEMODE_PROPERTY, "1"); + } + Log.i(TAG, "Sending shutdown broadcast..."); // First send the high-level shut down broadcast. diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index 57a4b29..505c3f9 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -708,6 +708,8 @@ <java-symbol type="string" name="preposition_for_time" /> <java-symbol type="string" name="progress_erasing" /> <java-symbol type="string" name="progress_unmounting" /> + <java-symbol type="string" name="reboot_safemode_confirm" /> + <java-symbol type="string" name="reboot_safemode_title" /> <java-symbol type="string" name="relationTypeAssistant" /> <java-symbol type="string" name="relationTypeBrother" /> <java-symbol type="string" name="relationTypeChild" /> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 149a78c..f5cea9c 100755 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -315,6 +315,15 @@ power off dialog instead of the global actions menu. --> <string name="shutdown_confirm_question">Do you want to shut down?</string> + <!-- Title of dialog to confirm rebooting into safe mode. [CHAR LIMIT=50] --> + <string name="reboot_safemode_title">Reboot to safe mode</string> + + <!-- Shutdown Confirmation Dialog. Message in the confirmation dialog + when the user asks to reboot into safe mode. [CHAR LIMIT=NONE] --> + <string name="reboot_safemode_confirm">Do you want to reboot into safe mode? + This will disable all third party applications you have installed. + They will be restored when you reboot again.</string> + <!-- Recent Tasks dialog: title TODO: this should move to SystemUI.apk, but the code for the old recent dialog is still in the framework diff --git a/policy/src/com/android/internal/policy/impl/GlobalActions.java b/policy/src/com/android/internal/policy/impl/GlobalActions.java index aeb518c..cd6da85 100644 --- a/policy/src/com/android/internal/policy/impl/GlobalActions.java +++ b/policy/src/com/android/internal/policy/impl/GlobalActions.java @@ -48,6 +48,7 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; +import android.widget.AdapterView; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.TextView; @@ -181,6 +182,11 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac ShutdownThread.shutdown(mContext, true); } + public boolean onLongPress() { + ShutdownThread.rebootSafeMode(mContext, true); + return true; + } + public boolean showDuringKeyguard() { return true; } @@ -242,6 +248,15 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac final AlertDialog dialog = ab.create(); dialog.getListView().setItemsCanFocus(true); + dialog.getListView().setLongClickable(true); + dialog.getListView().setOnItemLongClickListener( + new AdapterView.OnItemLongClickListener() { + @Override + public boolean onItemLongClick(AdapterView<?> parent, View view, int position, + long id) { + return mAdapter.getItem(position).onLongPress(); + } + }); dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG); dialog.setOnDismissListener(this); @@ -365,6 +380,8 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac void onPress(); + public boolean onLongPress(); + /** * @return whether this action should appear in the dialog when the keygaurd * is showing. @@ -406,6 +423,10 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac abstract public void onPress(); + public boolean onLongPress() { + return false; + } + public View create( Context context, View convertView, ViewGroup parent, LayoutInflater inflater) { View v = inflater.inflate(R.layout.global_actions_item, parent, false); @@ -530,6 +551,10 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac changeStateFromPress(nowOn); } + public boolean onLongPress() { + return false; + } + public boolean isEnabled() { return !mState.inTransition(); } @@ -599,6 +624,10 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac public void onPress() { } + public boolean onLongPress() { + return false; + } + public boolean showDuringKeyguard() { return true; } diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java index f698fbc..36a0a67 100755 --- a/services/java/com/android/server/wm/WindowManagerService.java +++ b/services/java/com/android/server/wm/WindowManagerService.java @@ -34,6 +34,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG; import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; import com.android.internal.app.IBatteryStats; +import com.android.internal.app.ShutdownThread; import com.android.internal.policy.PolicyManager; import com.android.internal.policy.impl.PhoneWindowManager; import com.android.internal.view.IInputContext; @@ -6507,6 +6508,13 @@ public class WindowManagerService extends IWindowManager.Stub KeyEvent.KEYCODE_VOLUME_DOWN); mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0 || volumeDownState > 0; + try { + if (SystemProperties.getInt(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, 0) != 0) { + mSafeMode = true; + SystemProperties.set(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, ""); + } + } catch (IllegalArgumentException e) { + } if (mSafeMode) { Log.i(TAG, "SAFE MODE ENABLED (menu=" + menuState + " s=" + sState + " dpad=" + dpadState + " trackball=" + trackballState + ")"); |