You can now long press on the power off menu to reboot to safe mode.
Change-Id: I3aa575285058cf5a3d89486d6b944f6ea13d645c
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 @@
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 @@
* @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 @@
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 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 @@
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.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 @@
ShutdownThread.shutdown(mContext, true);
}
+ public boolean onLongPress() {
+ ShutdownThread.rebootSafeMode(mContext, true);
+ return true;
+ }
+
public boolean showDuringKeyguard() {
return true;
}
@@ -242,6 +248,15 @@
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 @@
void onPress();
+ public boolean onLongPress();
+
/**
* @return whether this action should appear in the dialog when the keygaurd
* is showing.
@@ -406,6 +423,10 @@
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 @@
changeStateFromPress(nowOn);
}
+ public boolean onLongPress() {
+ return false;
+ }
+
public boolean isEnabled() {
return !mState.inTransition();
}
@@ -599,6 +624,10 @@
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_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 @@
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 + ")");