diff --git a/api/current.txt b/api/current.txt
index d333277691034..6d311d5ef3534 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -23086,6 +23086,7 @@ package android.os {
field public static final java.lang.String DISALLOW_OUTGOING_BEAM = "no_outgoing_beam";
field public static final java.lang.String DISALLOW_OUTGOING_CALLS = "no_outgoing_calls";
field public static final java.lang.String DISALLOW_REMOVE_USER = "no_remove_user";
+ field public static final java.lang.String DISALLOW_SAFE_BOOT = "no_safe_boot";
field public static final java.lang.String DISALLOW_SHARE_LOCATION = "no_share_location";
field public static final java.lang.String DISALLOW_SMS = "no_sms";
field public static final java.lang.String DISALLOW_UNINSTALL_APPS = "no_uninstall_apps";
diff --git a/api/system-current.txt b/api/system-current.txt
index c87bb9599bcba..1237267edce62 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -24881,6 +24881,7 @@ package android.os {
field public static final java.lang.String DISALLOW_OUTGOING_BEAM = "no_outgoing_beam";
field public static final java.lang.String DISALLOW_OUTGOING_CALLS = "no_outgoing_calls";
field public static final java.lang.String DISALLOW_REMOVE_USER = "no_remove_user";
+ field public static final java.lang.String DISALLOW_SAFE_BOOT = "no_safe_boot";
field public static final java.lang.String DISALLOW_SHARE_LOCATION = "no_share_location";
field public static final java.lang.String DISALLOW_SMS = "no_sms";
field public static final java.lang.String DISALLOW_UNINSTALL_APPS = "no_uninstall_apps";
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 706e0d023b805..3601a1c887444 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -399,6 +399,18 @@ public class UserManager {
*/
public static final String DISALLOW_WALLPAPER = "no_wallpaper";
+ /**
+ * Specifies if the user is not allowed to reboot the device into safe boot mode.
+ * This can only be set by device owners and profile owners on the primary user.
+ * The default value is false.
+ *
+ *
Key for user restrictions.
+ * Type: Boolean
+ * @see #setUserRestrictions(Bundle)
+ * @see #getUserRestrictions()
+ */
+ public static final String DISALLOW_SAFE_BOOT = "no_safe_boot";
+
/**
* Application restriction key that is used to indicate the pending arrival
* of real restrictions for the app.
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index e4f5e7d744ead..26ecb729ab276 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -918,6 +918,7 @@ public class UserManagerService extends IUserManager.Stub {
writeBoolean(serializer, restrictions, UserManager.DISALLOW_CROSS_PROFILE_COPY_PASTE);
writeBoolean(serializer, restrictions, UserManager.DISALLOW_OUTGOING_BEAM);
writeBoolean(serializer, restrictions, UserManager.DISALLOW_WALLPAPER);
+ writeBoolean(serializer, restrictions, UserManager.DISALLOW_SAFE_BOOT);
serializer.endTag(null, TAG_RESTRICTIONS);
}
@@ -1065,6 +1066,7 @@ public class UserManagerService extends IUserManager.Stub {
readBoolean(parser, restrictions, UserManager.DISALLOW_CROSS_PROFILE_COPY_PASTE);
readBoolean(parser, restrictions, UserManager.DISALLOW_OUTGOING_BEAM);
readBoolean(parser, restrictions, UserManager.DISALLOW_WALLPAPER);
+ readBoolean(parser, restrictions, UserManager.DISALLOW_SAFE_BOOT);
}
private void readBoolean(XmlPullParser parser, Bundle restrictions,
diff --git a/services/core/java/com/android/server/policy/GlobalActions.java b/services/core/java/com/android/server/policy/GlobalActions.java
index 6bbcdcd6dec03..b431b33598f4f 100644
--- a/services/core/java/com/android/server/policy/GlobalActions.java
+++ b/services/core/java/com/android/server/policy/GlobalActions.java
@@ -342,8 +342,12 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
@Override
public boolean onLongPress() {
- mWindowManagerFuncs.rebootSafeMode(true);
- return true;
+ UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+ if (!um.hasUserRestriction(UserManager.DISALLOW_SAFE_BOOT)) {
+ mWindowManagerFuncs.rebootSafeMode(true);
+ return true;
+ }
+ return false;
}
@Override
diff --git a/services/core/java/com/android/server/power/ShutdownThread.java b/services/core/java/com/android/server/power/ShutdownThread.java
index da1138771e390..1e0185da0ef62 100644
--- a/services/core/java/com/android/server/power/ShutdownThread.java
+++ b/services/core/java/com/android/server/power/ShutdownThread.java
@@ -39,6 +39,7 @@ import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserHandle;
+import android.os.UserManager;
import android.os.Vibrator;
import android.os.SystemVibrator;
import android.os.storage.IMountService;
@@ -202,6 +203,11 @@ public final class ShutdownThread extends Thread {
* @param confirm true if user confirmation is needed before shutting down.
*/
public static void rebootSafeMode(final Context context, boolean confirm) {
+ UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
+ if (um.hasUserRestriction(UserManager.DISALLOW_SAFE_BOOT)) {
+ return;
+ }
+
mReboot = true;
mRebootSafeMode = true;
mRebootReason = null;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 67d7af17e5a30..663c919e7b4ab 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -179,6 +179,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
DEVICE_OWNER_USER_RESTRICTIONS.add(UserManager.DISALLOW_UNMUTE_MICROPHONE);
DEVICE_OWNER_USER_RESTRICTIONS.add(UserManager.DISALLOW_ADJUST_VOLUME);
DEVICE_OWNER_USER_RESTRICTIONS.add(UserManager.DISALLOW_SMS);
+ DEVICE_OWNER_USER_RESTRICTIONS.add(UserManager.DISALLOW_SAFE_BOOT);
}
// The following user restrictions cannot be changed by any active admin, including device