diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl index 05e2332cc00031df448ede123ff1b5a3bca32984..b2f083bf59da9a1e3c4758d1512e86f61b7d7045 100644 --- a/core/java/android/os/IPowerManager.aidl +++ b/core/java/android/os/IPowerManager.aidl @@ -128,5 +128,6 @@ interface IPowerManager const int GO_TO_SLEEP_REASON_MAX = 10; const int GO_TO_SLEEP_FLAG_NO_DOZE = 1 << 0; + void rebootCustom(boolean confirm, String reason, boolean wait); void setKeyboardVisibility(boolean visible); } diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java index 66a6a61c05453da1da384565c4837ca7e864fcc4..f37ff5bfe8c2a507662040cd85e2ec3b27c071ed 100644 --- a/core/java/android/os/PowerManager.java +++ b/core/java/android/os/PowerManager.java @@ -738,6 +738,27 @@ public final class PowerManager { */ public static final String REBOOT_RECOVERY_UPDATE = "recovery-update"; + /** + * The value to pass as the 'reason' argument to reboot() to + * reboot into bootloader mode + * @hide + */ + public static final String REBOOT_BOOTLOADER = "bootloader"; + + /** + * The value to pass as the 'reason' argument to reboot() to + * reboot into download mode + * @hide + */ + public static final String REBOOT_DOWNLOAD = "download"; + + /** + * The value to pass as the 'reason' argument to reboot() to + * reboot into fastboot mode + * @hide + */ + public static final String REBOOT_FASTBOOT = "fastboot"; + /** * The value to pass as the 'reason' argument to reboot() when device owner requests a reboot on * the device. @@ -1740,6 +1761,24 @@ public final class PowerManager { } } + /** + * Reboot the device. Will not return if the reboot is successful. + * <p> + * Requires the {@link android.Manifest.permission#REBOOT} permission. + * </p> + * + * @param reason code to pass to the kernel (e.g., "recovery", "bootloader", "download") to + * request special boot modes, or null. + * @hide + */ + public void rebootCustom(String reason) { + try { + mService.rebootCustom(false, reason, true); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + /** * Reboot the device. Will not return if the reboot is successful. * <p> diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index c64ca28fdd0d5708a94e30d47e7bf2f363fd4239..6f4f59877814d77eaf19625fecff31be2573b3ed 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -10817,6 +10817,12 @@ public final class Settings { */ public static final String KEYBOARD_BRIGHTNESS = "keyboard_brightness"; + /** + * Whether to include options in power menu for rebooting into recovery or bootloader + * @hide + */ + public static final String ADVANCED_REBOOT = "advanced_reboot"; + /** * These entries are considered common between the personal and the managed profile, * since the managed profile doesn't get to change them. diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl index ad4f280b1e8d319bc101428a4e21bc856d94502e..df01cd05269b952cd0f1f41867af994456d4d7df 100644 --- a/core/java/com/android/internal/statusbar/IStatusBar.aidl +++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl @@ -142,7 +142,7 @@ oneway interface IStatusBar void showPinningEnterExitToast(boolean entering); void showPinningEscapeToast(); - void showShutdownUi(boolean isReboot, String reason); + void showShutdownUi(boolean isReboot, String reason, boolean rebootCustom); /** * Used to show the authentication dialog (Biometrics, Device Credential). diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl index fd28d1be8106c5b7138e9346f5c94f3e614de44c..0a62a1eed5e5b5875165b9b5ff3182684007a37e 100644 --- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl +++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl @@ -93,7 +93,7 @@ interface IStatusBarService * These methods are needed for global actions control which the UI is shown in sysui. */ void shutdown(); - void reboot(boolean safeMode); + void reboot(boolean safeMode, String reason); void addTile(in ComponentName tile); void remTile(in ComponentName tile); diff --git a/core/java/com/android/internal/util/libremobileos/PowerMenuConstants.java b/core/java/com/android/internal/util/libremobileos/PowerMenuConstants.java new file mode 100644 index 0000000000000000000000000000000000000000..f8227dd911ba384a81365b504671c5b460b1e194 --- /dev/null +++ b/core/java/com/android/internal/util/libremobileos/PowerMenuConstants.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2015 The CyanogenMod Project + * Copyright (C) 2017-2021 The LineageOS 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 com.android.internal.util.libremobileos; + +/* Master list of all actions for the power menu */ +public class PowerMenuConstants { + public static final String GLOBAL_ACTION_KEY_POWER = "power"; + public static final String GLOBAL_ACTION_KEY_RESTART = "restart"; + public static final String GLOBAL_ACTION_KEY_SCREENSHOT = "screenshot"; + public static final String GLOBAL_ACTION_KEY_AIRPLANE = "airplane"; + public static final String GLOBAL_ACTION_KEY_USERS = "users"; + public static final String GLOBAL_ACTION_KEY_SETTINGS = "settings"; + public static final String GLOBAL_ACTION_KEY_LOCKDOWN = "lockdown"; + public static final String GLOBAL_ACTION_KEY_BUGREPORT = "bugreport"; + public static final String GLOBAL_ACTION_KEY_SILENT = "silent"; + public static final String GLOBAL_ACTION_KEY_VOICEASSIST = "voiceassist"; + public static final String GLOBAL_ACTION_KEY_ASSIST = "assist"; + public static final String GLOBAL_ACTION_KEY_LOGOUT = "logout"; + public static final String GLOBAL_ACTION_KEY_EMERGENCY = "emergency"; + + /** + * Advanced restart menu actions + */ + public static final String GLOBAL_ACTION_KEY_RESTART_RECOVERY = "restart_recovery"; + public static final String GLOBAL_ACTION_KEY_RESTART_BOOTLOADER = "restart_bootloader"; + public static final String GLOBAL_ACTION_KEY_RESTART_DOWNLOAD = "restart_download"; + public static final String GLOBAL_ACTION_KEY_RESTART_FASTBOOT = "restart_fastboot"; + + private static String[] ALL_ACTIONS = { + GLOBAL_ACTION_KEY_EMERGENCY, + GLOBAL_ACTION_KEY_LOCKDOWN, + GLOBAL_ACTION_KEY_POWER, + GLOBAL_ACTION_KEY_RESTART, + GLOBAL_ACTION_KEY_SCREENSHOT, + GLOBAL_ACTION_KEY_AIRPLANE, + GLOBAL_ACTION_KEY_USERS, + GLOBAL_ACTION_KEY_SETTINGS, + GLOBAL_ACTION_KEY_BUGREPORT, + GLOBAL_ACTION_KEY_SILENT, + GLOBAL_ACTION_KEY_VOICEASSIST, + GLOBAL_ACTION_KEY_ASSIST, + GLOBAL_ACTION_KEY_LOGOUT, + }; + + public static String[] getAllActions() { + return ALL_ACTIONS; + } +} diff --git a/core/java/com/android/internal/util/libremobileos/PowerMenuUtils.java b/core/java/com/android/internal/util/libremobileos/PowerMenuUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..3df05169de1ed582e401ed5fc1d9b83ef017d31c --- /dev/null +++ b/core/java/com/android/internal/util/libremobileos/PowerMenuUtils.java @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2017 The LineageOS 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 com.android.internal.util.libremobileos; + +import android.app.KeyguardManager; +import android.content.Context; +import android.os.UserHandle; +import android.provider.Settings; + +public final class PowerMenuUtils { + public static boolean isAdvancedRestartPossible(final Context context) { + KeyguardManager km = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE); + boolean keyguardLocked = km.inKeyguardRestrictedInputMode() && km.isKeyguardSecure(); + boolean advancedRestartEnabled = Settings.Secure.getInt(context.getContentResolver(), + Settings.Secure.ADVANCED_REBOOT, 0) == 1; + boolean isPrimaryUser = UserHandle.getCallingUserId() == UserHandle.USER_OWNER; + + return advancedRestartEnabled && !keyguardLocked && isPrimaryUser; + } +} diff --git a/core/res/res/values/lmodroid_config.xml b/core/res/res/values/lmodroid_config.xml index 4957a5e26388d568e602d488592093714f66dfac..a892460fb57c87b47904260f97c2ab837e5d1d96 100644 --- a/core/res/res/values/lmodroid_config.xml +++ b/core/res/res/values/lmodroid_config.xml @@ -158,4 +158,11 @@ <integer name="config_deviceSupportsKeyboardBrightnessControl">0</integer> <dimen name="config_keyboardBrightnessSettingDefaultFloat">1.0</dimen> + <!-- Defines the actions shown in advanced reboot submenu --> + <string-array name="config_restartActionsList"> + <item>restart</item> + <item>restart_recovery</item> + <item>restart_bootloader</item> + </string-array> + </resources> diff --git a/core/res/res/values/lmodroid_symbols.xml b/core/res/res/values/lmodroid_symbols.xml index 2ee697c22911b532d5271ed86f0188214f64d2d1..5c03f08461793c83b9c880a698fa86b953d88818 100644 --- a/core/res/res/values/lmodroid_symbols.xml +++ b/core/res/res/values/lmodroid_symbols.xml @@ -65,4 +65,7 @@ <java-symbol type="dimen" name="config_buttonBrightnessSettingDefaultFloat" /> <java-symbol type="dimen" name="config_keyboardBrightnessSettingDefaultFloat" /> + <!-- Power menu --> + <java-symbol type="array" name="config_restartActionsList" /> + </resources> diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/GlobalActions.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/GlobalActions.java index 95ff13b45fb9ba1641b3fd84f29c9276d02fff8c..7775551b731a1e9590eaf138d0ec720583d519c6 100644 --- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/GlobalActions.java +++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/GlobalActions.java @@ -26,7 +26,7 @@ public interface GlobalActions extends Plugin { int VERSION = 1; void showGlobalActions(GlobalActionsManager manager); - default void showShutdownUi(boolean isReboot, String reason) { + default void showShutdownUi(boolean isReboot, String reason, boolean rebootCustom) { } default void destroy() { @@ -40,6 +40,6 @@ public interface GlobalActions extends Plugin { void onGlobalActionsHidden(); void shutdown(); - void reboot(boolean safeMode); + void reboot(boolean safeMode, String reason); } } diff --git a/packages/SystemUI/res/drawable/ic_lock_restart_bootloader.xml b/packages/SystemUI/res/drawable/ic_lock_restart_bootloader.xml new file mode 100644 index 0000000000000000000000000000000000000000..ea625b111c87d826ebd707042387455c8e2789e4 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_lock_restart_bootloader.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2018 The LineageOS 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24" + android:tint="?android:attr/colorControlNormal"> + + <path + android:fillColor="#FF000000" + android:pathData="M21,8 L3,8 C2,8,2,9,2,9 L2,21 C2,22,3,22,3,22 L21,22 C22,22,22,21,22,21 L22,9 C22,8,21,8,21,8 Z M17,9 C17.55,9,18,9.45,18,10 S17.55,11,17,11 S16,10.55,16,10 S16.45,9,17,9 Z M14,9 C14.55,9,15,9.45,15,10 S14.55,11,14,11 S13,10.55,13,10 S13.45,9,14,9 Z M20,20 L4,20 L4,12 L20,12 L20,20 Z M20,11 C19.45,11,19,10.55,19,10 S19.45,9,20,9 S21,9.45,21,10 S20.55,11,20,11 Z M21,2 L3,2 C2,2,2,3,2,3 L2,6 L22,6 L22,3 C22,2,21,2,21,2 Z M14,5 C13.45,5,13,4.55,13,4 S13.45,3,14,3 S15,3.45,15,4 S14.55,5,14,5 Z M17,5 C16.45,5,16,4.55,16,4 S16.45,3,17,3 S18,3.45,18,4 S17.55,5,17,5 Z M20,5 C19.45,5,19,4.55,19,4 S19.45,3,20,3 S21,3.45,21,4 S20.55,5,20,5 Z" /> + <path + android:fillColor="#FF000000" + android:pathData="M11,19.414 L8.293,16.707 L9.707,15.293 L11,16.586 L14.293,13.293 L15.707,14.707 Z" /> +</vector> diff --git a/packages/SystemUI/res/drawable/ic_lock_restart_fastboot.xml b/packages/SystemUI/res/drawable/ic_lock_restart_fastboot.xml new file mode 100644 index 0000000000000000000000000000000000000000..560e6254eb2c0b26b7a05e8a4e1e54487d5dc340 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_lock_restart_fastboot.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2019 The LineageOS 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. +--> +<vector + xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:pathData="M 22 9 L 22 7 L 20 7 L 20 5 C 20 4.47 19.789 3.961 19.414 3.586 C 19.039 3.211 18.53 3 18 3 L 4 3 C 3.47 3 2.961 3.211 2.586 3.586 C 2.211 3.961 2 4.47 2 5 L 2 19 C 2 19.53 2.211 20.039 2.586 20.414 C 2.961 20.789 3.47 21 4 21 L 18 21 C 18.53 21 19.039 20.789 19.414 20.414 C 19.789 20.039 20 19.53 20 19 L 20 17 L 22 17 L 22 15 L 20 15 L 20 13 L 22 13 L 22 11 L 20 11 L 20 9 L 22 9 M 18 19 L 4 19 L 4 5 L 18 5 L 18 19 M 6 13 L 11 13 L 11 17 L 6 17 L 6 13 M 12 7 L 16 7 L 16 10 L 12 10 L 12 7 M 6 7 L 11 7 L 11 12 L 6 12 L 6 7 M 12 11 L 16 11 L 16 17 L 12 17 L 12 11 Z" + android:fillColor="#000000" /> +</vector> diff --git a/packages/SystemUI/res/drawable/ic_lock_restart_recovery.xml b/packages/SystemUI/res/drawable/ic_lock_restart_recovery.xml new file mode 100644 index 0000000000000000000000000000000000000000..632802607492c782fc2da0f3cf676073629f7563 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_lock_restart_recovery.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2018 The LineageOS 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24" + android:tint="?android:attr/colorControlNormal"> + + <path + android:fillColor="#FF000000" + android:pathData="M19.43,12.98 C19.47,12.66,19.5,12.34,19.5,12 S19.47,11.34,19.43,11.02 L21.54,9.37 C21.73,9.22,21.78,8.95,21.66,8.73 L19.66,5.27 C19.54,5.05,19.269,4.97,19.05,5.05 L16.56,6.05 C16.04,5.65,15.481,5.32,14.871,5.07 L14.491,2.42 C14.46,2.18,14.25,2,14,2 L10,2 C9.75,2,9.54,2.18,9.51,2.42 L9.13,5.07 C8.52,5.32,7.96,5.66,7.44,6.05 L4.95,5.05 C4.72,4.96,4.46,5.05,4.34,5.27 L2.34,8.73 C2.21,8.95,2.27,9.22,2.46,9.37 L4.57,11.02 C4.53,11.34,4.5,11.67,4.5,12 S4.53,12.66,4.57,12.98 L2.46,14.63 C2.27,14.78,2.22,15.05,2.34,15.27 L4.34,18.731 C4.46,18.951,4.73,19.031,4.95,18.951 L7.44,17.951 C7.96,18.35,8.52,18.68,9.13,18.93 L9.51,21.58 C9.54,21.82,9.75,22,10,22 L14,22 C14.25,22,14.46,21.82,14.49,21.58 L14.87,18.93 C15.48,18.68,16.04,18.34,16.559,17.951 L19.049,18.951 C19.279,19.041,19.539,18.951,19.659,18.731 L21.659,15.27 C21.779,15.05,21.729,14.781,21.539,14.63 L19.43,12.98 Z M9.71,15.71 L8.29,14.29 L14.29,8.29 L15.71,9.71 L9.71,15.71 Z" /> +</vector> diff --git a/packages/SystemUI/res/layout-land/global_actions_power_dialog.xml b/packages/SystemUI/res/layout-land/global_actions_power_dialog.xml new file mode 100644 index 0000000000000000000000000000000000000000..ba9956435f6c0153247f42e39278076fdb30fe8a --- /dev/null +++ b/packages/SystemUI/res/layout-land/global_actions_power_dialog.xml @@ -0,0 +1,24 @@ +<!-- + ~ Copyright (C) 2020 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. + --> +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:orientation="horizontal" + android:divider="@drawable/controls_list_divider" + android:showDividers="middle" +/> + diff --git a/packages/SystemUI/res/layout/global_actions_power_item.xml b/packages/SystemUI/res/layout/global_actions_power_item.xml index 3bf58944423b368950091b3e3af7de85315b2efc..84153a8d0592ff18e3662eddca93c3ed1585077b 100644 --- a/packages/SystemUI/res/layout/global_actions_power_item.xml +++ b/packages/SystemUI/res/layout/global_actions_power_item.xml @@ -37,7 +37,7 @@ android:ellipsize="marquee" android:layout_marginBottom="16dp" android:maxLines="1" - android:textSize="16sp" + android:textSize="12sp" android:gravity="center" android:textColor="@color/control_primary_text" android:textAppearance="?android:attr/textAppearanceSmall" /> diff --git a/packages/SystemUI/res/values-land/dimens.xml b/packages/SystemUI/res/values-land/dimens.xml index fc5edf3ade8fdb39741d741ded42514b586b12d5..e8765190f59dbd92d4c88d08e025fb191c768b16 100644 --- a/packages/SystemUI/res/values-land/dimens.xml +++ b/packages/SystemUI/res/values-land/dimens.xml @@ -51,9 +51,6 @@ <dimen name="biometric_dialog_button_negative_max_width">140dp</dimen> <dimen name="biometric_dialog_button_positive_max_width">116dp</dimen> - <dimen name="global_actions_power_dialog_item_height">130dp</dimen> - <dimen name="global_actions_power_dialog_item_bottom_margin">35dp</dimen> - <dimen name="controls_management_top_padding">12dp</dimen> <dimen name="controls_management_titles_margin">8dp</dimen> <dimen name="controls_management_indicator_top_margin">8dp</dimen> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index 4c4a3bbf55ba70a3c401c78abec24f9b4a9bc3f7..67488ec5bf3ad6a47b243e323e679399955e96ff 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -806,9 +806,9 @@ <dimen name="global_actions_controls_y_translation">20dp</dimen> <!-- Shutdown and restart actions are larger in power options dialog --> - <dimen name="global_actions_power_dialog_item_height">190dp</dimen> - <dimen name="global_actions_power_dialog_item_width">255dp</dimen> - <dimen name="global_actions_power_dialog_item_bottom_margin">45dp</dimen> + <dimen name="global_actions_power_dialog_item_height">128dp</dimen> + <dimen name="global_actions_power_dialog_item_width">128dp</dimen> + <dimen name="global_actions_power_dialog_item_bottom_margin">22dp</dimen> <!-- Power Menu Lite --> <dimen name="global_actions_button_size">96dp</dimen> diff --git a/packages/SystemUI/res/values/lmodroid_strings.xml b/packages/SystemUI/res/values/lmodroid_strings.xml index a278659e9fcb95bb73079fc98ba9fa79b044f8bf..917dbeafe39e6fe18485bc964698c7115806a7a9 100644 --- a/packages/SystemUI/res/values/lmodroid_strings.xml +++ b/packages/SystemUI/res/values/lmodroid_strings.xml @@ -25,6 +25,31 @@ <!-- Name of the clock in status bar [CHAR LIMIT=30] --> <string name="clock">Clock</string> + <!-- Advanced restart menu --> + <!-- Button to indicate more options --> + <string name="global_action_restart_more">Restart\u2026</string> + <!-- Button to restart the device, within the Restart Options dialog --> + <string name="global_action_restart_system">System</string> + <!-- Button to restart the device into recovery mode, within the Restart Options dialog --> + <string name="global_action_restart_recovery">Recovery</string> + <!-- Button to restart the device into bootloader mode, within the Restart Options dialog --> + <string name="global_action_restart_bootloader">Bootloader</string> + <!-- Button to restart the device into download mode, within the Restart Options dialog --> + <string name="global_action_restart_download">Download</string> + <!-- Button to restart the device into fastboot mode, within the Restart Options dialog --> + <string name="global_action_restart_fastboot">Fastbootd</string> + + <!-- Restart progress dialog. This is shown if the user chooses to restart the device. --> + <string name="global_action_restart_progress">Restarting\u2026</string> + <!-- Restart to recovery mode progress dialog. This is shown if the user chooses to restart the device. --> + <string name="global_action_restart_recovery_progress">Restarting to recovery mode\u2026</string> + <!-- Restart to bootloader mode progress dialog. This is shown if the user chooses to restart the device. --> + <string name="global_action_restart_bootloader_progress">Restarting to bootloader mode\u2026</string> + <!-- Restart to download mode progress dialog. This is shown if the user chooses to restart the device. --> + <string name="global_action_restart_download_progress">Restarting to download mode\u2026</string> + <!-- Restart to fastboot mode progress dialog. This is shown if the user chooses to restart the device. --> + <string name="global_action_restart_fastboot_progress">Restarting to fastbootd mode\u2026</string> + <!-- Custom QS tiles --> <!-- Ambient display QS tile --> <string name="quick_settings_ambient_display_label">Ambient display</string> diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsComponent.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsComponent.java index 86c8565bf8efce1be5f65c051453a5133e856c99..f4578e5dc2e67afb04da4f4a9ad0980eafb9c54f 100644 --- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsComponent.java +++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsComponent.java @@ -79,8 +79,8 @@ public class GlobalActionsComponent extends SystemUI implements Callbacks, Globa } @Override - public void handleShowShutdownUi(boolean isReboot, String reason) { - mExtension.get().showShutdownUi(isReboot, reason); + public void handleShowShutdownUi(boolean isReboot, String reason, boolean rebootCustom) { + mExtension.get().showShutdownUi(isReboot, reason, rebootCustom); } @Override @@ -115,9 +115,9 @@ public class GlobalActionsComponent extends SystemUI implements Callbacks, Globa } @Override - public void reboot(boolean safeMode) { + public void reboot(boolean safeMode, String reason) { try { - mBarService.reboot(safeMode); + mBarService.reboot(safeMode, reason); } catch (RemoteException e) { } } diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java index 2ebcd8531128c4e6a20e611f768e5f9d272e1dc2..5a3d339ebd1ad2f423e7e9264d4ee2bf86519d4c 100644 --- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java +++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java @@ -29,6 +29,8 @@ import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STR import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_GLOBAL_ACTIONS_SHOWING; +import static com.android.internal.util.libremobileos.PowerMenuConstants.*; + import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.annotation.Nullable; @@ -58,6 +60,7 @@ import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Message; +import android.os.PowerManager; import android.os.RemoteException; import android.os.SystemProperties; import android.os.UserHandle; @@ -130,6 +133,8 @@ import com.android.systemui.util.RingerModeTracker; import com.android.systemui.util.settings.GlobalSettings; import com.android.systemui.util.settings.SecureSettings; +import com.android.internal.util.libremobileos.PowerMenuUtils; + import java.util.ArrayList; import java.util.List; import java.util.Optional; @@ -155,22 +160,13 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene private static final boolean SHOW_SILENT_TOGGLE = true; - /* Valid settings for global actions keys. - * see config.xml config_globalActionList */ - @VisibleForTesting - static final String GLOBAL_ACTION_KEY_POWER = "power"; - private static final String GLOBAL_ACTION_KEY_AIRPLANE = "airplane"; - static final String GLOBAL_ACTION_KEY_BUGREPORT = "bugreport"; - private static final String GLOBAL_ACTION_KEY_SILENT = "silent"; - private static final String GLOBAL_ACTION_KEY_USERS = "users"; - private static final String GLOBAL_ACTION_KEY_SETTINGS = "settings"; - static final String GLOBAL_ACTION_KEY_LOCKDOWN = "lockdown"; - private static final String GLOBAL_ACTION_KEY_VOICEASSIST = "voiceassist"; - private static final String GLOBAL_ACTION_KEY_ASSIST = "assist"; - static final String GLOBAL_ACTION_KEY_RESTART = "restart"; - private static final String GLOBAL_ACTION_KEY_LOGOUT = "logout"; - static final String GLOBAL_ACTION_KEY_EMERGENCY = "emergency"; - static final String GLOBAL_ACTION_KEY_SCREENSHOT = "screenshot"; + /* Valid settings for restart actions keys. + * see lmodroid config.xml config_restartActionsList */ + private static final String RESTART_ACTION_KEY_RESTART = "restart"; + private static final String RESTART_ACTION_KEY_RESTART_RECOVERY = "restart_recovery"; + private static final String RESTART_ACTION_KEY_RESTART_BOOTLOADER = "restart_bootloader"; + private static final String RESTART_ACTION_KEY_RESTART_DOWNLOAD = "restart_download"; + private static final String RESTART_ACTION_KEY_RESTART_FASTBOOT = "restart_fastboot"; // See NotificationManagerService#scheduleDurationReachedLocked private static final long TOAST_FADE_TIME = 333; @@ -207,6 +203,8 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene protected final ArrayList<Action> mOverflowItems = new ArrayList<>(); @VisibleForTesting protected final ArrayList<Action> mPowerItems = new ArrayList<>(); + @VisibleForTesting + protected final ArrayList<Action> mRestartItems = new ArrayList<>(); @VisibleForTesting protected ActionsDialogLite mDialog; @@ -217,6 +215,7 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene protected MyAdapter mAdapter; protected MyOverflowAdapter mOverflowAdapter; protected MyPowerOptionsAdapter mPowerAdapter; + protected MyRestartOptionsAdapter mRestartAdapter; private boolean mKeyguardShowing = false; private boolean mDeviceProvisioned = false; @@ -411,6 +410,7 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene mScreenshotHelper = new ScreenshotHelper(context); mConfigurationController.addCallback(this); + } /** @@ -522,6 +522,10 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene return action.shouldShow(); } + private boolean shouldShowRestartSubmenu() { + return PowerMenuUtils.isAdvancedRestartPossible(mContext); + } + /** * Returns the maximum number of power menu items to show based on which GlobalActions * layout is being used. @@ -555,6 +559,11 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene } } + @VisibleForTesting + protected String[] getRestartActions() { + return mResources.getStringArray(R.array.config_restartActionsList); + } + @VisibleForTesting protected void createActionItems() { // Simple toggle style if there's no vibrator, otherwise use a tri-state @@ -569,11 +578,19 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene mItems.clear(); mOverflowItems.clear(); mPowerItems.clear(); + mRestartItems.clear(); String[] defaultActions = getDefaultActions(); + String[] restartActions = getRestartActions(); ShutDownAction shutdownAction = new ShutDownAction(); RestartAction restartAction = new RestartAction(); + RestartSystemAction sysAction = new RestartSystemAction(); + RestartRecoveryAction recAction = new RestartRecoveryAction(); + RestartBootloaderAction blAction = new RestartBootloaderAction(); + RestartDownloadAction dlAction = new RestartDownloadAction(); + RestartFastbootAction fbAction = new RestartFastbootAction(); ArraySet<String> addedKeys = new ArraySet<>(); + ArraySet<String> addedRestartKeys = new ArraySet<String>(); List<Action> tempActions = new ArrayList<>(); CurrentUserProvider currentUser = new CurrentUserProvider(); @@ -637,6 +654,27 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene addedKeys.add(actionKey); } + for (int i = 0; i < restartActions.length; i++) { + String actionKey = restartActions[i]; + if (addedRestartKeys.contains(actionKey)) { + // If we already have added this, don't add it again. + continue; + } + if (RESTART_ACTION_KEY_RESTART.equals(actionKey)) { + addIfShouldShowAction(mRestartItems, sysAction); + } else if (RESTART_ACTION_KEY_RESTART_RECOVERY.equals(actionKey)) { + addIfShouldShowAction(mRestartItems, recAction); + } else if (RESTART_ACTION_KEY_RESTART_BOOTLOADER.equals(actionKey)) { + addIfShouldShowAction(mRestartItems, blAction); + } else if (RESTART_ACTION_KEY_RESTART_DOWNLOAD.equals(actionKey)) { + addIfShouldShowAction(mRestartItems, dlAction); + } else if (RESTART_ACTION_KEY_RESTART_FASTBOOT.equals(actionKey)) { + addIfShouldShowAction(mRestartItems, fbAction); + } + // Add here so we don't add more than one. + addedRestartKeys.add(actionKey); + } + // replace power and restart with a single power options action, if needed if (tempActions.contains(shutdownAction) && tempActions.contains(restartAction) && tempActions.size() > getMaxShownPowerItems()) { @@ -666,6 +704,7 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene mAdapter = new MyAdapter(); mOverflowAdapter = new MyOverflowAdapter(); mPowerAdapter = new MyPowerOptionsAdapter(); + mRestartAdapter = new MyRestartOptionsAdapter(); } /** @@ -680,8 +719,8 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene com.android.systemui.R.style.Theme_SystemUI_Dialog_GlobalActionsLite, mAdapter, mOverflowAdapter, mSysuiColorExtractor, mStatusBarService, mNotificationShadeWindowController, - mSysUiState, this::onRefresh, mKeyguardShowing, mPowerAdapter, mUiEventLogger, - mStatusBarOptional, mKeyguardUpdateMonitor, mLockPatternUtils, + mSysUiState, this::onRefresh, mKeyguardShowing, mPowerAdapter, mRestartAdapter, + mUiEventLogger, mStatusBarOptional, mKeyguardUpdateMonitor, mLockPatternUtils, mDialogManager); dialog.setOnDismissListener(this); @@ -769,7 +808,7 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene public boolean onLongPress() { mUiEventLogger.log(GlobalActionsEvent.GA_SHUTDOWN_LONG_PRESS); if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_SAFE_BOOT)) { - mWindowManagerFuncs.reboot(true); + mWindowManagerFuncs.reboot(true, null); return true; } return false; @@ -893,14 +932,16 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene @VisibleForTesting final class RestartAction extends SinglePressAction implements LongPressAction { RestartAction() { - super(R.drawable.ic_restart, R.string.global_action_restart); + super(R.drawable.ic_restart, shouldShowRestartSubmenu() + ? com.android.systemui.R.string.global_action_restart_more + : R.string.global_action_restart); } @Override public boolean onLongPress() { mUiEventLogger.log(GlobalActionsEvent.GA_REBOOT_LONG_PRESS); if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_SAFE_BOOT)) { - mWindowManagerFuncs.reboot(true); + mWindowManagerFuncs.reboot(true, null); return true; } return false; @@ -919,7 +960,130 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene @Override public void onPress() { mUiEventLogger.log(GlobalActionsEvent.GA_REBOOT_PRESS); - mWindowManagerFuncs.reboot(false); + if (mDialog != null && shouldShowRestartSubmenu()) { + mDialog.showRestartOptionsMenu(); + } else { + mWindowManagerFuncs.reboot(false, null); + } + } + } + + private final class RestartSystemAction extends SinglePressAction implements LongPressAction { + public RestartSystemAction() { + super(R.drawable.ic_restart, + com.android.systemui.R.string.global_action_restart_system); + } + + @Override + public boolean onLongPress() { + if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_SAFE_BOOT)) { + mWindowManagerFuncs.reboot(true, null); + return true; + } + return false; + } + + @Override + public boolean showDuringKeyguard() { + return true; + } + + @Override + public boolean showBeforeProvisioning() { + return true; + } + + @Override + public void onPress() { + mWindowManagerFuncs.reboot(false, null); + } + } + + private final class RestartRecoveryAction extends SinglePressAction { + private RestartRecoveryAction() { + super(com.android.systemui.R.drawable.ic_lock_restart_recovery, + com.android.systemui.R.string.global_action_restart_recovery); + } + + @Override + public boolean showDuringKeyguard() { + return true; + } + + @Override + public boolean showBeforeProvisioning() { + return true; + } + + @Override + public void onPress() { + mWindowManagerFuncs.reboot(false, PowerManager.REBOOT_RECOVERY); + } + } + + private final class RestartBootloaderAction extends SinglePressAction { + private RestartBootloaderAction() { + super(com.android.systemui.R.drawable.ic_lock_restart_bootloader, + com.android.systemui.R.string.global_action_restart_bootloader); + } + + @Override + public boolean showDuringKeyguard() { + return true; + } + + @Override + public boolean showBeforeProvisioning() { + return true; + } + + @Override + public void onPress() { + mWindowManagerFuncs.reboot(false, PowerManager.REBOOT_BOOTLOADER); + } + } + + private final class RestartFastbootAction extends SinglePressAction { + private RestartFastbootAction() { + super(com.android.systemui.R.drawable.ic_lock_restart_fastboot, + com.android.systemui.R.string.global_action_restart_fastboot); + } + + @Override + public boolean showDuringKeyguard() { + return true; + } + + @Override + public boolean showBeforeProvisioning() { + return true; + } + + @Override + public void onPress() { + mWindowManagerFuncs.reboot(false, PowerManager.REBOOT_FASTBOOT); + } + } + + private final class RestartDownloadAction extends SinglePressAction { + private RestartDownloadAction() { + super(com.android.systemui.R.drawable.ic_lock_restart_bootloader, + com.android.systemui.R.string.global_action_restart_download); + } + + @Override + public boolean showDuringKeyguard() { + return true; + } + + @Override + public boolean showBeforeProvisioning() { + return true; + } + + @Override + public void onPress() { + mWindowManagerFuncs.reboot(false, PowerManager.REBOOT_DOWNLOAD); } } @@ -1388,8 +1552,9 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene Action item = mAdapter.getItem(position); if (!(item instanceof SilentModeTriStateAction)) { if (mDialog != null) { - // don't dismiss the dialog if we're opening the power options menu - if (!(item instanceof PowerOptionsAction)) { + // don't dismiss the dialog if we're opening the power/restart options menu + if (!(item instanceof PowerOptionsAction || + (item instanceof RestartAction && shouldShowRestartSubmenu()))) { // Usually clicking an item shuts down the phone, locks, or starts an // activity. We don't want to animate back into the power button when that // happens, so we disable the dialog animation before dismissing. @@ -1477,7 +1642,8 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene private void onClickItem(int position) { Action item = getItem(position); if (!(item instanceof SilentModeTriStateAction)) { - if (mDialog != null) { + if (mDialog != null && + !(item instanceof RestartAction && shouldShowRestartSubmenu())) { // Usually clicking an item shuts down the phone, locks, or starts an activity. // We don't want to animate back into the power button when that happens, so we // disable the dialog animation before dismissing. @@ -1491,6 +1657,18 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene } } + public class MyRestartOptionsAdapter extends MyPowerOptionsAdapter { + @Override + public int getCount() { + return mRestartItems.size(); + } + + @Override + public Action getItem(int position) { + return mRestartItems.get(position); + } + } + /** * The adapter used for items in the power options menu, triggered by the PowerOptionsAction. */ @@ -2072,6 +2250,7 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene mAdapter.notifyDataSetChanged(); mOverflowAdapter.notifyDataSetChanged(); mPowerAdapter.notifyDataSetChanged(); + mRestartAdapter.notifyDataSetChanged(); } }; @@ -2154,6 +2333,7 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene protected final MyAdapter mAdapter; protected final MyOverflowAdapter mOverflowAdapter; protected final MyPowerOptionsAdapter mPowerOptionsAdapter; + private final MyRestartOptionsAdapter mRestartOptionsAdapter; protected final IStatusBarService mStatusBarService; protected final IBinder mToken = new Binder(); protected Drawable mBackgroundDrawable; @@ -2164,6 +2344,7 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene protected final SysUiState mSysUiState; private ListPopupWindow mOverflowPopup; private Dialog mPowerOptionsDialog; + private Dialog mRestartOptionsDialog; protected final Runnable mOnRefreshCallback; private UiEventLogger mUiEventLogger; private GestureDetector mGestureDetector; @@ -2222,8 +2403,8 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene SysuiColorExtractor sysuiColorExtractor, IStatusBarService statusBarService, NotificationShadeWindowController notificationShadeWindowController, SysUiState sysuiState, Runnable onRefreshCallback, boolean keyguardShowing, - MyPowerOptionsAdapter powerAdapter, UiEventLogger uiEventLogger, - Optional<StatusBar> statusBarOptional, + MyPowerOptionsAdapter powerAdapter, MyRestartOptionsAdapter restartAdapter, + UiEventLogger uiEventLogger, Optional<StatusBar> statusBarOptional, KeyguardUpdateMonitor keyguardUpdateMonitor, LockPatternUtils lockPatternUtils, SystemUIDialogManager systemUiDialogManager) { // We set dismissOnDeviceLock to false because we have a custom broadcast receiver to @@ -2234,6 +2415,7 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene mAdapter = adapter; mOverflowAdapter = overflowAdapter; mPowerOptionsAdapter = powerAdapter; + mRestartOptionsAdapter = restartAdapter; mColorExtractor = sysuiColorExtractor; mStatusBarService = statusBarService; mNotificationShadeWindowController = notificationShadeWindowController; @@ -2304,6 +2486,12 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene mPowerOptionsDialog.show(); } + public void showRestartOptionsMenu() { + mRestartOptionsDialog = GlobalActionsPowerDialog.create(mContext, + mRestartOptionsAdapter); + mRestartOptionsDialog.show(); + } + protected void showPowerOverflowMenu() { mOverflowPopup = createPowerOverflowPopup(); mOverflowPopup.show(); @@ -2465,6 +2653,7 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene public void dismiss() { dismissOverflow(); dismissPowerOptions(); + dismissRestartOptions(); mNotificationShadeWindowController.setRequestTopUi(false, TAG); mSysUiState.setFlag(SYSUI_STATE_GLOBAL_ACTIONS_SHOWING, false) @@ -2485,6 +2674,12 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene } } + private void dismissRestartOptions() { + if (mRestartOptionsDialog != null) { + mRestartOptionsDialog.dismiss(); + } + } + protected final void setRotationSuggestionsEnabled(boolean enabled) { try { final int userId = Binder.getCallingUserHandle().getIdentifier(); @@ -2522,6 +2717,7 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene // Dismiss the dropdown menus. dismissOverflow(); dismissPowerOptions(); + dismissRestartOptions(); // Update the list as the max number of items per row has probably changed. mGlobalActionsLayout.updateList(); diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java index 96ae646ac7f9a113133db7166f44f4c0130338ba..578700e8c2d087b3eb645e569a2d5873e2e37f63 100644 --- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java +++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java @@ -86,7 +86,7 @@ public class GlobalActionsImpl implements GlobalActions, CommandQueue.Callbacks } @Override - public void showShutdownUi(boolean isReboot, String reason) { + public void showShutdownUi(boolean isReboot, String reason, boolean rebootCustom) { ScrimDrawable background = new ScrimDrawable(); final Dialog d = new Dialog(mContext, @@ -150,8 +150,8 @@ public class GlobalActionsImpl implements GlobalActions, CommandQueue.Callbacks reasonView.setTextColor(color); messageView.setTextColor(color); - messageView.setText(getRebootMessage(isReboot, reason)); - String rebootReasonMessage = getReasonMessage(reason); + messageView.setText(getRebootMessage(isReboot, reason, rebootCustom)); + String rebootReasonMessage = getReasonMessage(reason, rebootCustom); if (rebootReasonMessage != null) { reasonView.setVisibility(View.VISIBLE); reasonView.setText(rebootReasonMessage); @@ -161,23 +161,31 @@ public class GlobalActionsImpl implements GlobalActions, CommandQueue.Callbacks } @StringRes - private int getRebootMessage(boolean isReboot, @Nullable String reason) { + private int getRebootMessage(boolean isReboot, @Nullable String reason, boolean custom) { if (reason != null && reason.startsWith(PowerManager.REBOOT_RECOVERY_UPDATE)) { return R.string.reboot_to_update_reboot; + } else if (reason != null && !custom && reason.equals(PowerManager.REBOOT_RECOVERY)) { + return com.android.systemui.R.string.global_action_restart_progress; } else if (reason != null && reason.equals(PowerManager.REBOOT_RECOVERY)) { - return R.string.reboot_to_reset_message; + return com.android.systemui.R.string.global_action_restart_recovery_progress; + } else if (reason != null && reason.equals(PowerManager.REBOOT_BOOTLOADER)) { + return com.android.systemui.R.string.global_action_restart_bootloader_progress; + } else if (reason != null && reason.equals(PowerManager.REBOOT_DOWNLOAD)) { + return com.android.systemui.R.string.global_action_restart_download_progress; + } else if (reason != null && reason.equals(PowerManager.REBOOT_FASTBOOT)) { + return com.android.systemui.R.string.global_action_restart_fastboot_progress; } else if (isReboot) { - return R.string.reboot_to_reset_message; + return com.android.systemui.R.string.global_action_restart_progress; } else { return R.string.shutdown_progress; } } @Nullable - private String getReasonMessage(@Nullable String reason) { + private String getReasonMessage(@Nullable String reason, boolean custom) { if (reason != null && reason.startsWith(PowerManager.REBOOT_RECOVERY_UPDATE)) { return mContext.getString(R.string.reboot_to_update_title); - } else if (reason != null && reason.equals(PowerManager.REBOOT_RECOVERY)) { + } else if (reason != null && !custom && reason.equals(PowerManager.REBOOT_RECOVERY)) { return mContext.getString(R.string.reboot_to_reset_title); } else { return null; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java index 0b06b35b75d6fb273e2afebed4222a78497b2c02..0fe8268db48678402fb30d48523d3c29a928b6d5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java @@ -283,7 +283,7 @@ public class CommandQueue extends IStatusBar.Stub implements default void showPinningEnterExitToast(boolean entering) { } default void showPinningEscapeToast() { } default void handleShowGlobalActionsMenu() { } - default void handleShowShutdownUi(boolean isReboot, String reason) { } + default void handleShowShutdownUi(boolean isReboot, String reason, boolean rebootCustom) { } default void showWirelessChargingAnimation(int batteryLevel) { } @@ -831,11 +831,11 @@ public class CommandQueue extends IStatusBar.Stub implements } @Override - public void showShutdownUi(boolean isReboot, String reason) { + public void showShutdownUi(boolean isReboot, String reason, boolean rebootCustom) { synchronized (mLock) { mHandler.removeMessages(MSG_SHOW_SHUTDOWN_UI); - mHandler.obtainMessage(MSG_SHOW_SHUTDOWN_UI, isReboot ? 1 : 0, 0, reason) - .sendToTarget(); + mHandler.obtainMessage(MSG_SHOW_SHUTDOWN_UI, isReboot ? 1 : 0, + rebootCustom ? 1 : 0, reason).sendToTarget(); } } @@ -1304,7 +1304,8 @@ public class CommandQueue extends IStatusBar.Stub implements break; case MSG_SHOW_SHUTDOWN_UI: for (int i = 0; i < mCallbacks.size(); i++) { - mCallbacks.get(i).handleShowShutdownUi(msg.arg1 != 0, (String) msg.obj); + mCallbacks.get(i).handleShowShutdownUi(msg.arg1 != 0, (String) msg.obj, + msg.arg2 != 0); } break; case MSG_SET_TOP_APP_HIDES_STATUS_BAR: diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java index 0a2666e62bc3c71f4c5e30fe1af21490f550cf16..6920f45f6cc308410c2fbb35ba8a5fcb38043ae5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java @@ -261,9 +261,9 @@ public class PhoneStatusBarView extends FrameLayout { LayoutParams centeredAreaParams = (LayoutParams) findViewById(R.id.centered_area).getLayoutParams(); centeredAreaParams.leftMargin = - winRotation == Surface.ROTATION_0 ? -contentRect.left : 0; + winRotation == Surface.ROTATION_0 ? -insets.first : 0; centeredAreaParams.rightMargin = - winRotation == Surface.ROTATION_0 ? -(size.x - contentRect.right) : 0; + winRotation == Surface.ROTATION_0 ? -insets.second : 0; } /** diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java index 2f2f94d3b5deddb41864e22ee637ab0ee9c86732..feeef69683163284f0bd09d0e8352932414a48e7 100644 --- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java +++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java @@ -286,6 +286,7 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants { public void shutdown(boolean confirm); public void reboot(boolean confirm); + public void reboot(boolean confirm, String reason); public void rebootSafeMode(boolean confirm); /** diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java index 124ec6f5d7c1091d7eac7ba51b457bc457568a3a..d8a6f16fb6aeaf5521ff1ed4d99adc532d5eb666 100644 --- a/services/core/java/com/android/server/power/PowerManagerService.java +++ b/services/core/java/com/android/server/power/PowerManagerService.java @@ -3779,7 +3779,7 @@ public final class PowerManagerService extends SystemService } private void shutdownOrRebootInternal(final @HaltMode int haltMode, final boolean confirm, - @Nullable final String reason, boolean wait) { + @Nullable final String reason, boolean wait, boolean custom) { if (PowerManager.REBOOT_USERSPACE.equals(reason)) { if (!PowerManager.isRebootingUserspaceSupportedImpl()) { throw new UnsupportedOperationException( @@ -3806,7 +3806,11 @@ public final class PowerManagerService extends SystemService if (haltMode == HALT_MODE_REBOOT_SAFE_MODE) { ShutdownThread.rebootSafeMode(getUiContext(), confirm); } else if (haltMode == HALT_MODE_REBOOT) { - ShutdownThread.reboot(getUiContext(), reason, confirm); + if (custom) { + ShutdownThread.rebootCustom(getUiContext(), reason, confirm); + } else { + ShutdownThread.reboot(getUiContext(), reason, confirm); + } } else { ShutdownThread.shutdown(getUiContext(), reason, confirm); } @@ -5929,7 +5933,7 @@ public final class PowerManagerService extends SystemService ShutdownCheckPoints.recordCheckPoint(Binder.getCallingPid(), reason); final long ident = Binder.clearCallingIdentity(); try { - shutdownOrRebootInternal(HALT_MODE_REBOOT, confirm, reason, wait); + shutdownOrRebootInternal(HALT_MODE_REBOOT, confirm, reason, wait, false); } finally { Binder.restoreCallingIdentity(ident); } @@ -5949,7 +5953,29 @@ public final class PowerManagerService extends SystemService ShutdownCheckPoints.recordCheckPoint(Binder.getCallingPid(), reason); final long ident = Binder.clearCallingIdentity(); try { - shutdownOrRebootInternal(HALT_MODE_REBOOT_SAFE_MODE, confirm, reason, wait); + shutdownOrRebootInternal(HALT_MODE_REBOOT_SAFE_MODE, confirm, reason, wait, false); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + /** + * Reboots the device. + * + * @param confirm If true, shows a reboot confirmation dialog. + * @param reason The reason for the reboot, or null if none. + * @param wait If true, this call waits for the reboot to complete and does not return. + */ + @Override // Binder call + public void rebootCustom(boolean confirm, String reason, boolean wait) { + mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null); + if (PowerManager.REBOOT_RECOVERY.equals(reason)) { + mContext.enforceCallingOrSelfPermission(android.Manifest.permission.RECOVERY, null); + } + + final long ident = Binder.clearCallingIdentity(); + try { + shutdownOrRebootInternal(HALT_MODE_REBOOT, confirm, reason, wait, true); } finally { Binder.restoreCallingIdentity(ident); } @@ -5968,7 +5994,7 @@ public final class PowerManagerService extends SystemService ShutdownCheckPoints.recordCheckPoint(Binder.getCallingPid(), reason); final long ident = Binder.clearCallingIdentity(); try { - shutdownOrRebootInternal(HALT_MODE_SHUTDOWN, confirm, reason, wait); + shutdownOrRebootInternal(HALT_MODE_SHUTDOWN, confirm, reason, wait, false); } finally { Binder.restoreCallingIdentity(ident); } diff --git a/services/core/java/com/android/server/power/ShutdownThread.java b/services/core/java/com/android/server/power/ShutdownThread.java index e94575c4336306b37a7d0bdb69e827df7e270b58..98345dd23e7b6f68f6d3ec8cea485b3a29117b26 100644 --- a/services/core/java/com/android/server/power/ShutdownThread.java +++ b/services/core/java/com/android/server/power/ShutdownThread.java @@ -83,6 +83,7 @@ public final class ShutdownThread extends Thread { private static boolean sIsStarted = false; private static boolean mReboot; + private static boolean mRebootCustom; private static boolean mRebootSafeMode; private static boolean mRebootHasProgressBar; private static String mReason; @@ -146,6 +147,7 @@ public final class ShutdownThread extends Thread { */ public static void shutdown(final Context context, String reason, boolean confirm) { mReboot = false; + mRebootCustom = false; mRebootSafeMode = false; mReason = reason; shutdownInner(context, confirm); @@ -238,6 +240,26 @@ public final class ShutdownThread extends Thread { */ public static void reboot(final Context context, String reason, boolean confirm) { mReboot = true; + mRebootCustom = false; + mRebootSafeMode = false; + mRebootHasProgressBar = false; + mReason = reason; + shutdownInner(context, confirm); + } + + /** + * 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. This must be a context + * suitable for displaying UI (aka Themable). + * @param reason code to pass to the kernel (e.g. "recovery", "bootloader"), or null. + * @param confirm true if user confirmation is needed before shutting down. + */ + public static void rebootCustom(final Context context, String reason, boolean confirm) { + mReboot = true; + mRebootCustom = true; mRebootSafeMode = false; mRebootHasProgressBar = false; mReason = reason; @@ -259,6 +281,7 @@ public final class ShutdownThread extends Thread { } mReboot = true; + mRebootCustom = false; mRebootSafeMode = true; mRebootHasProgressBar = false; mReason = null; @@ -315,7 +338,7 @@ public final class ShutdownThread extends Thread { com.android.internal.R.string.reboot_to_update_reboot)); } } else if (mReason != null && mReason.equals(PowerManager.REBOOT_RECOVERY)) { - if (showSysuiReboot()) { + if (mRebootCustom && showSysuiReboot()) { return null; } else if (RescueParty.isAttemptingFactoryReset()) { // We're not actually doing a factory reset yet; we're rebooting @@ -351,7 +374,7 @@ public final class ShutdownThread extends Thread { try { StatusBarManagerInternal service = LocalServices.getService( StatusBarManagerInternal.class); - if (service.showShutdownUi(mReboot, mReason)) { + if (service.showShutdownUi(mReboot, mReason, mRebootCustom)) { // Sysui will handle shutdown UI. Log.d(TAG, "SysUI handling shutdown UI"); return true; diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java index 411f3dcc1eb6eda7fad7d0e993e4ad76ac8c6a3c..ae1f5fee2065d044d8ec61e22ca06a2f05da9dc5 100644 --- a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java +++ b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java @@ -109,7 +109,7 @@ public interface StatusBarManagerInternal { */ void setTopAppHidesStatusBar(boolean hidesStatusBar); - boolean showShutdownUi(boolean isReboot, String requestString); + boolean showShutdownUi(boolean isReboot, String requestString, boolean rebootCustom); /** * Show a rotation suggestion that a user may approve to rotate the screen. diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java index 2624f38ef5540bbb9eeb1b7c4ad3a0d065506674..5dd1d0e9ecb586eae6d31997340ce544f72669df 100644 --- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java +++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java @@ -482,13 +482,13 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D } @Override - public boolean showShutdownUi(boolean isReboot, String reason) { + public boolean showShutdownUi(boolean isReboot, String reason, boolean rebootCustom) { if (!mContext.getResources().getBoolean(R.bool.config_showSysuiShutdown)) { return false; } if (mBar != null) { try { - mBar.showShutdownUi(isReboot, reason); + mBar.showShutdownUi(isReboot, reason, rebootCustom); return true; } catch (RemoteException ex) {} } @@ -1331,11 +1331,8 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D * Allows the status bar to reboot the device. */ @Override - public void reboot(boolean safeMode) { + public void reboot(boolean safeMode, String reason) { enforceStatusBarService(); - String reason = safeMode - ? PowerManager.REBOOT_SAFE_MODE - : PowerManager.SHUTDOWN_USER_REQUESTED; ShutdownCheckPoints.recordCheckPoint(Binder.getCallingPid(), reason); final long identity = Binder.clearCallingIdentity(); try { @@ -1345,7 +1342,7 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D if (safeMode) { ShutdownThread.rebootSafeMode(getUiContext(), true); } else { - ShutdownThread.reboot(getUiContext(), reason, false); + ShutdownThread.rebootCustom(getUiContext(), reason, false); } }); } finally { diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 2d9ef16e158029a61ad64148a8b619d77a5869ce..a1df549cbaa5d64e056069f61855275b99965c57 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -3489,6 +3489,14 @@ public class WindowManagerService extends IWindowManager.Stub PowerManager.SHUTDOWN_USER_REQUESTED, confirm); } + // Called by window manager policy. Not exposed externally. + @Override + public void reboot(boolean confirm, String reason) { + // Pass in the UI context, since ShutdownThread requires it (to show UI). + ShutdownThread.rebootCustom(ActivityThread.currentActivityThread().getSystemUiContext(), + reason, confirm); + } + // Called by window manager policy. Not exposed externally. @Override public void rebootSafeMode(boolean confirm) {