diff options
25 files changed, 497 insertions, 55 deletions
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index 87d52e4..92cf03e 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -1800,6 +1800,15 @@ public class Intent implements Parcelable, Cloneable { */ public static final String ACTION_CLOSE_SYSTEM_DIALOGS = "android.intent.action.CLOSE_SYSTEM_DIALOGS"; /** + * Broadcast Action: Update preferences for the power menu dialog. This is to provide a + * way for the preferences that need to be enabled/disabled to update because they were + * toggled elsewhere in the settings (ie profiles, immersive desktop, etc) so we don't have + * to do constant lookups while we wait for the menu to be created. Getting the values once + * when necessary is enough. + *@hide + */ + public static final String UPDATE_POWER_MENU = "android.intent.action.UPDATE_POWER_MENU"; + /** * Broadcast Action: Trigger the download and eventual installation * of a package. * <p>Input: {@link #getData} is the URI of the package file to download. diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 7882e29..8a80ddd 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -6127,6 +6127,12 @@ public final class Settings { public static final String LIVE_DISPLAY_COLOR_MATRIX = "live_display_color_matrix"; /** + * Whether to include options in power menu for rebooting into recovery or bootloader + * @hide + */ + public static final String ADVANCED_REBOOT = "advanced_reboot"; + + /** * This are the settings to be backed up. * * NOTE: Settings are backed up and restored in the order they appear @@ -6182,6 +6188,7 @@ public final class Settings { MOUNT_UMS_NOTIFY_ENABLED, SLEEP_TIMEOUT, DOUBLE_TAP_TO_WAKE, + ADVANCED_REBOOT }; /** @@ -6588,6 +6595,12 @@ public final class Settings { public static final String ADB_ENABLED = "adb_enabled"; /** + * String to contain power menu actions + * @hide + */ + public static final String POWER_MENU_ACTIONS = "power_menu_actions"; + + /** * Whether Views are allowed to save their attribute data. * @hide */ diff --git a/core/java/com/android/internal/util/cm/PowerMenuConstants.java b/core/java/com/android/internal/util/cm/PowerMenuConstants.java new file mode 100644 index 0000000..3debd09 --- /dev/null +++ b/core/java/com/android/internal/util/cm/PowerMenuConstants.java @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2015 The CyanogenMod 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.cm; + +/* 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_REBOOT = "reboot"; + 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"; + + private static String[] ALL_ACTIONS = { + GLOBAL_ACTION_KEY_POWER, + GLOBAL_ACTION_KEY_REBOOT, + GLOBAL_ACTION_KEY_SCREENSHOT, + GLOBAL_ACTION_KEY_AIRPLANE, + GLOBAL_ACTION_KEY_USERS, + GLOBAL_ACTION_KEY_SETTINGS, + GLOBAL_ACTION_KEY_LOCKDOWN, + GLOBAL_ACTION_KEY_BUGREPORT, + GLOBAL_ACTION_KEY_SILENT, + GLOBAL_ACTION_KEY_VOICEASSIST, + GLOBAL_ACTION_KEY_ASSIST + }; + + public static String[] getAllActions() { + return ALL_ACTIONS; + } +} diff --git a/core/res/res/drawable-hdpi/ic_lock_power_reboot_alpha.png b/core/res/res/drawable-hdpi/ic_lock_power_reboot_alpha.png Binary files differindex 17b4866..ca00936 100644 --- a/core/res/res/drawable-hdpi/ic_lock_power_reboot_alpha.png +++ b/core/res/res/drawable-hdpi/ic_lock_power_reboot_alpha.png diff --git a/core/res/res/drawable-hdpi/ic_lock_profile_alpha.png b/core/res/res/drawable-hdpi/ic_lock_profile_alpha.png Binary files differnew file mode 100644 index 0000000..7fc4cec --- /dev/null +++ b/core/res/res/drawable-hdpi/ic_lock_profile_alpha.png diff --git a/core/res/res/drawable-mdpi/ic_lock_power_reboot_alpha.png b/core/res/res/drawable-mdpi/ic_lock_power_reboot_alpha.png Binary files differindex 471a41c..2b125b9 100644 --- a/core/res/res/drawable-mdpi/ic_lock_power_reboot_alpha.png +++ b/core/res/res/drawable-mdpi/ic_lock_power_reboot_alpha.png diff --git a/core/res/res/drawable-mdpi/ic_lock_profile_alpha.png b/core/res/res/drawable-mdpi/ic_lock_profile_alpha.png Binary files differnew file mode 100644 index 0000000..d47ba16 --- /dev/null +++ b/core/res/res/drawable-mdpi/ic_lock_profile_alpha.png diff --git a/core/res/res/drawable-xhdpi/ic_lock_power_reboot_alpha.png b/core/res/res/drawable-xhdpi/ic_lock_power_reboot_alpha.png Binary files differindex a786b40..653970f 100644 --- a/core/res/res/drawable-xhdpi/ic_lock_power_reboot_alpha.png +++ b/core/res/res/drawable-xhdpi/ic_lock_power_reboot_alpha.png diff --git a/core/res/res/drawable-xhdpi/ic_lock_profile_alpha.png b/core/res/res/drawable-xhdpi/ic_lock_profile_alpha.png Binary files differnew file mode 100644 index 0000000..4c9472c --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_lock_profile_alpha.png diff --git a/core/res/res/drawable-xxhdpi/ic_lock_power_reboot_alpha.png b/core/res/res/drawable-xxhdpi/ic_lock_power_reboot_alpha.png Binary files differindex 6072387..362bf28 100644 --- a/core/res/res/drawable-xxhdpi/ic_lock_power_reboot_alpha.png +++ b/core/res/res/drawable-xxhdpi/ic_lock_power_reboot_alpha.png diff --git a/core/res/res/drawable-xxhdpi/ic_lock_profile_alpha.png b/core/res/res/drawable-xxhdpi/ic_lock_profile_alpha.png Binary files differnew file mode 100644 index 0000000..e23c484 --- /dev/null +++ b/core/res/res/drawable-xxhdpi/ic_lock_profile_alpha.png diff --git a/core/res/res/drawable/ic_lock_lock.xml b/core/res/res/drawable/ic_lock_lock.xml index 39f268a..6c87b42 100644 --- a/core/res/res/drawable/ic_lock_lock.xml +++ b/core/res/res/drawable/ic_lock_lock.xml @@ -16,4 +16,4 @@ <bitmap xmlns:android="http://schemas.android.com/apk/res/android" android:src="@drawable/ic_lock_lock_alpha" - android:tint="?attr/colorControlActivated" /> + android:tint="?attr/colorControlNormal" /> diff --git a/core/res/res/drawable/ic_lock_profile.xml b/core/res/res/drawable/ic_lock_profile.xml new file mode 100644 index 0000000..393138b --- /dev/null +++ b/core/res/res/drawable/ic_lock_profile.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2015 The CyanogenMod 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. +--> +<bitmap xmlns:android="http://schemas.android.com/apk/res/android" + android:src="@drawable/ic_lock_profile_alpha" + android:tint="?attr/colorControlNormal" /> diff --git a/core/res/res/drawable/ic_lock_screenshot.xml b/core/res/res/drawable/ic_lock_screenshot.xml new file mode 100644 index 0000000..b682f92 --- /dev/null +++ b/core/res/res/drawable/ic_lock_screenshot.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2015 The CyanogenMod 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="32dp" + android:height="32dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0" + android:tint="?attr/colorControlNormal"> + + <path + android:fillColor="@color/white" + android:pathData="M16 1H8C6.34 1 5 2.34 5 4v16c0 1.66 1.34 3 3 3h8c1.66 0 3-1.34 3-3V4c0-1.66-1.34-3-3-3zm-2 20h-4v-1h4v1zm3.25-3H6.75V4h10.5v14z" /> +</vector> diff --git a/core/res/res/drawable/ic_lock_settings.xml b/core/res/res/drawable/ic_lock_settings.xml new file mode 100644 index 0000000..4c6ded2 --- /dev/null +++ b/core/res/res/drawable/ic_lock_settings.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2014 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="32dp" + android:height="32dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0" + android:tint="?attr/colorControlNormal"> + + <path + android:fillColor="@color/white" + android:pathData="M19.4,13.0c0.0,-0.3 0.1,-0.6 0.1,-1.0s0.0,-0.7 -0.1,-1.0l2.1,-1.7c0.2,-0.2 0.2,-0.4 0.1,-0.6l-2.0,-3.5C19.5,5.1 19.3,5.0 19.0,5.1l-2.5,1.0c-0.5,-0.4 -1.1,-0.7 -1.7,-1.0l-0.4,-2.6C14.5,2.2 14.2,2.0 14.0,2.0l-4.0,0.0C9.8,2.0 9.5,2.2 9.5,2.4L9.1,5.1C8.5,5.3 8.0,5.7 7.4,6.1L5.0,5.1C4.7,5.0 4.5,5.1 4.3,5.3l-2.0,3.5C2.2,8.9 2.3,9.2 2.5,9.4L4.6,11.0c0.0,0.3 -0.1,0.6 -0.1,1.0s0.0,0.7 0.1,1.0l-2.1,1.7c-0.2,0.2 -0.2,0.4 -0.1,0.6l2.0,3.5C4.5,18.9 4.7,19.0 5.0,18.9l2.5,-1.0c0.5,0.4 1.1,0.7 1.7,1.0l0.4,2.6c0.0,0.2 0.2,0.4 0.5,0.4l4.0,0.0c0.2,0.0 0.5,-0.2 0.5,-0.4l0.4,-2.6c0.6,-0.3 1.2,-0.6 1.7,-1.0l2.5,1.0c0.2,0.1 0.5,0.0 0.6,-0.2l2.0,-3.5c0.1,-0.2 0.1,-0.5 -0.1,-0.6L19.4,13.0zM12.0,15.5c-1.9,0.0 -3.5,-1.6 -3.5,-3.5s1.6,-3.5 3.5,-3.5s3.5,1.6 3.5,3.5S13.9,15.5 12.0,15.5z" /> +</vector> diff --git a/core/res/res/drawable/ic_lock_user.xml b/core/res/res/drawable/ic_lock_user.xml new file mode 100644 index 0000000..e951319 --- /dev/null +++ b/core/res/res/drawable/ic_lock_user.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2015 The CyanogenMod 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="32dp" + android:height="32dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0" + android:tint="?attr/colorControlNormal"> + + <path + android:fillColor="@color/white" + android:pathData="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z" /> +</vector> diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml index fcfc1ff..5f51235 100644 --- a/core/res/res/values-zh-rCN/strings.xml +++ b/core/res/res/values-zh-rCN/strings.xml @@ -201,9 +201,6 @@ <string name="shutdown_confirm_question" msgid="2906544768881136183">"您要关机吗?"</string> <string name="reboot_safemode_title" msgid="7054509914500140361">"重新启动并进入安全模式"</string> <string name="reboot_safemode_confirm" msgid="55293944502784668">"您要重新启动并进入安全模式吗?这样会停用您已安装的所有第三方应用。再次重新启动将恢复这些应用。"</string> - <string name="reboot_title">"重启"</string> - <string name="reboot_confirm" product="tablet">"您的平板电脑将会重启。"</string> - <string name="reboot_confirm" product="default">"您的手机将会重启。"</string> <string name="recent_tasks_title" msgid="3691764623638127888">"近期任务"</string> <string name="no_recent_tasks" msgid="8794906658732193473">"最近没有运行任何应用"</string> <string name="global_actions" product="tablet" msgid="408477140088053665">"平板电脑选项"</string> @@ -211,7 +208,6 @@ <string name="global_actions" product="default" msgid="2406416831541615258">"手机选项"</string> <string name="global_action_lock" msgid="2844945191792119712">"屏幕锁定"</string> <string name="global_action_power_off" msgid="4471879440839879722">"关机"</string> - <string name="global_action_reboot">"重启"</string> <string name="global_action_bug_report" msgid="7934010578922304799">"错误报告"</string> <string name="bugreport_title" msgid="2667494803742548533">"提交错误报告"</string> <string name="bugreport_message" msgid="398447048750350456">"这会收集有关当前设备状态的信息,并以电子邮件的形式进行发送。从开始生成错误报告到准备好发送需要一点时间,请耐心等待。"</string> diff --git a/core/res/res/values/cm_arrays.xml b/core/res/res/values/cm_arrays.xml index 2f22539..b78fe37 100644 --- a/core/res/res/values/cm_arrays.xml +++ b/core/res/res/values/cm_arrays.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <!-- - Copyright (C) 2013-2014 The CyanogenMod Project + Copyright (C) 2013-2015 The CyanogenMod Project Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -46,4 +46,21 @@ <item>1</item> <item>3</item> </string-array> + + <!-- Defines the shutdown options shown in the reboot dialog. --> + <array name="shutdown_reboot_options" translatable="false"> + <item>@string/reboot_reboot</item> + <item>@string/reboot_soft</item> + <item>@string/reboot_recovery</item> + <item>@string/reboot_bootloader</item> + </array> + + <!-- Do not translate. Defines the shutdown actions passed to the kernel. + The first item should be empty for regular reboot. --> + <string-array name="shutdown_reboot_actions" translatable="false"> + <item></item> + <item>soft_reboot</item> + <item>recovery</item> + <item>bootloader</item> + </string-array> </resources> diff --git a/core/res/res/values/cm_strings.xml b/core/res/res/values/cm_strings.xml index 2589bf4..762e718 100644 --- a/core/res/res/values/cm_strings.xml +++ b/core/res/res/values/cm_strings.xml @@ -31,6 +31,9 @@ <string name="live_display_outdoor_summary">Use outdoor settings only</string> <string name="live_display_hint">LiveDisplay can help reduce eyestrain and help you sleep at night. Click here to try it out!</string> + <!-- label for item that screenshots in phone options dialog --> + <string name="global_action_screenshot">Screenshot</string> + <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. --> <string name="permgrouplab_security">Security</string> <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. --> @@ -50,4 +53,34 @@ <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> <string name="permdesc_preventpower">Allows an app to override the power key.</string> + <!-- label for item that opens the profile choosing dialog --> + <string name="global_action_choose_profile">Profile</string> + + + <!-- label for item that reboots the phone in phone options dialog --> + <string name="global_action_reboot">Reboot</string> + + <!-- Reboot menu --> + <!-- Button to reboot the phone, within the Reboot Options dialog --> + <string name="reboot_reboot">Reboot</string> + <!-- Button to reboot the phone into recovery, within the Reboot Options dialog --> + <string name="reboot_recovery">Recovery</string> + <!-- Button to reboot the phone into bootloader, within the Reboot Options dialog --> + <string name="reboot_bootloader">Bootloader</string> + <!-- Button to reboot the phone into download, within the Reboot Options dialog --> + <string name="reboot_download">Download</string> + <!-- Button to soft reboot the device, within the Reboot Options dialog --> + <string name="reboot_soft">Soft reboot</string> + + <!-- Title of dialog to confirm rebooting. --> + <string name="reboot_title">Reboot</string> + + <!-- Reboot Confirmation Dialog. When the user chooses to reboot the device, there will + be a confirmation dialog. This is the message. --> + <string name="reboot_confirm" product="tablet">Your tablet will reboot.</string> + <string name="reboot_confirm" product="default">Your phone will reboot.</string> + + <!-- Reboot Progress Dialog. This is shown if the user chooses to reboot the phone. --> + <string name="reboot_progress">Rebooting\u2026</string> + </resources> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index bec1600..0b73760 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -457,14 +457,6 @@ This will disable all third party applications you have installed. They will be restored when you reboot again.</string> - <!-- Title of dialog to confirm rebooting. --> - <string name="reboot_title">Reboot</string> - - <!-- Reboot Confirmation Dialog. When the user chooses to reboot the device, there will - be a confirmation dialog. This is the message. --> - <string name="reboot_confirm" product="tablet">Your tablet will reboot.</string> - <string name="reboot_confirm" product="default">Your phone will reboot.</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 @@ -489,9 +481,6 @@ <!-- label for item that turns off power in phone options dialog --> <string name="global_action_power_off">Power off</string> - <!-- label for item that reboots the phone in phone options dialog --> - <string name="global_action_reboot">Reboot</string> - <!-- label for item that generates a bug report in the phone options dialog --> <string name="global_action_bug_report">Bug report</string> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 7407e60..43b504a 100755 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -822,6 +822,7 @@ <java-symbol type="string" name="reboot_safemode_confirm" /> <java-symbol type="string" name="reboot_safemode_title" /> <java-symbol type="string" name="reboot_title" /> + <java-symbol type="string" name="reboot_progress" /> <java-symbol type="string" name="relationTypeAssistant" /> <java-symbol type="string" name="relationTypeBrother" /> <java-symbol type="string" name="relationTypeChild" /> @@ -1456,6 +1457,8 @@ <java-symbol type="array" name="config_safeModeEnabledVibePattern" /> <java-symbol type="array" name="config_contextClickVibePattern" /> <java-symbol type="array" name="config_virtualKeyVibePattern" /> + <java-symbol type="array" name="shutdown_reboot_options" /> + <java-symbol type="array" name="shutdown_reboot_actions" /> <java-symbol type="attr" name="actionModePopupWindowStyle" /> <java-symbol type="attr" name="dialogCustomTitleDecorLayout" /> <java-symbol type="attr" name="dialogTitleDecorLayout" /> @@ -2397,4 +2400,10 @@ <java-symbol type="array" name="notification_light_package_mapping" /> <java-symbol type="array" name="config_notificationNoAlertsVibePattern" /> + <!-- Power menu --> + <java-symbol type="drawable" name="ic_lock_screenshot" /> + <java-symbol type="string" name="global_action_screenshot" /> + <java-symbol type="drawable" name="ic_lock_settings" /> + <java-symbol type="drawable" name="ic_lock_user" /> + </resources> diff --git a/packages/SystemUI/Android.mk b/packages/SystemUI/Android.mk index 51fea2a..51b8af5 100644 --- a/packages/SystemUI/Android.mk +++ b/packages/SystemUI/Android.mk @@ -6,7 +6,9 @@ LOCAL_MODULE_TAGS := optional LOCAL_SRC_FILES := $(call all-java-files-under, src) \ src/com/android/systemui/EventLogTags.logtags -LOCAL_STATIC_JAVA_LIBRARIES := Keyguard +LOCAL_STATIC_JAVA_LIBRARIES := Keyguard \ + org.cyanogenmod.platform.sdk + LOCAL_JAVA_LIBRARIES := telephony-common LOCAL_PACKAGE_NAME := SystemUI diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index a1c8b1a..af24b4a 100644..100755 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -56,6 +56,9 @@ import android.view.WindowManagerPolicy; import android.view.animation.Animation; import android.view.animation.AnimationUtils; +import cyanogenmod.app.Profile; +import cyanogenmod.app.ProfileManager; + import com.android.internal.policy.IKeyguardDrawnCallback; import com.android.internal.policy.IKeyguardExitCallback; import com.android.internal.policy.IKeyguardStateCallback; @@ -188,7 +191,7 @@ public class KeyguardViewMediator extends SystemUI { private AudioManager mAudioManager; private StatusBarManager mStatusBarManager; private boolean mSwitchingUser; - + private ProfileManager mProfileManager; private boolean mSystemReady; private boolean mBootCompleted; private boolean mBootSendUserPresent; @@ -571,7 +574,7 @@ public class KeyguardViewMediator extends SystemUI { mShowKeyguardWakeLock = mPM.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "show keyguard"); mShowKeyguardWakeLock.setReferenceCounted(false); - + mProfileManager = ProfileManager.getInstance(mContext); mContext.registerReceiver(mBroadcastReceiver, new IntentFilter(DELAYED_KEYGUARD_ACTION)); mKeyguardDisplayManager = new KeyguardDisplayManager(mContext); @@ -799,7 +802,7 @@ public class KeyguardViewMediator extends SystemUI { } private void maybeSendUserPresentBroadcast() { - if (mSystemReady && mLockPatternUtils.isLockScreenDisabled( + if (mSystemReady && isKeyguardDisabled( KeyguardUpdateMonitor.getCurrentUser())) { // Lock screen is disabled because the user has set the preference to "None". // In this case, send out ACTION_USER_PRESENT here instead of in @@ -808,6 +811,25 @@ public class KeyguardViewMediator extends SystemUI { } } + private boolean isKeyguardDisabled(int userId) { + if (!mExternallyEnabled) { + if (DEBUG) Log.d(TAG, "isKeyguardDisabled: keyguard is disabled externally"); + return true; + } + if (mLockPatternUtils.isLockScreenDisabled(userId)) { + if (DEBUG) Log.d(TAG, "isKeyguardDisabled: keyguard is disabled by setting"); + return true; + } + Profile profile = mProfileManager.getActiveProfile(); + if (profile != null) { + if (profile.getScreenLockMode().getValue() == Profile.LockMode.DISABLE) { + if (DEBUG) Log.d(TAG, "isKeyguardDisabled: keyguard is disabled by profile"); + return true; + } + } + return false; + } + /** * A dream started. We should lock after the usual screen-off lock timeout but only * if there is a secure lock pattern. @@ -1054,7 +1076,7 @@ public class KeyguardViewMediator extends SystemUI { return; } - if (mLockPatternUtils.isLockScreenDisabled(KeyguardUpdateMonitor.getCurrentUser()) + if (isKeyguardDisabled(KeyguardUpdateMonitor.getCurrentUser()) && !lockedOrMissing) { if (DEBUG) Log.d(TAG, "doKeyguard: not showing because lockscreen is off"); return; diff --git a/services/core/java/com/android/server/policy/GlobalActions.java b/services/core/java/com/android/server/policy/GlobalActions.java index 8e73495..ea22ce6 100644 --- a/services/core/java/com/android/server/policy/GlobalActions.java +++ b/services/core/java/com/android/server/policy/GlobalActions.java @@ -1,5 +1,6 @@ /* * Copyright (C) 2008 The Android Open Source Project + * Copyright (C) 2010-2015 CyanogenMod Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,20 +29,26 @@ import android.app.ActivityManagerNative; import android.app.AlertDialog; import android.app.Dialog; import android.content.BroadcastReceiver; +import android.content.ComponentName; import android.content.Context; +import android.content.ContentResolver; import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.UserInfo; +import android.content.ServiceConnection; import android.database.ContentObserver; import android.graphics.drawable.Drawable; +import android.Manifest; import android.media.AudioManager; import android.net.ConnectivityManager; import android.os.Build; import android.os.Bundle; import android.os.Handler; +import android.os.IBinder; import android.os.IPowerManager; import android.os.Message; +import android.os.Messenger; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; @@ -79,6 +86,9 @@ import android.widget.TextView; import java.util.ArrayList; import java.util.List; +import java.util.UUID; + +import static com.android.internal.util.cm.PowerMenuConstants.*; /** * Helper to show the global actions dialog. Each item is an {@link Action} that @@ -91,19 +101,6 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac private static final boolean SHOW_SILENT_TOGGLE = true; - /* Valid settings for global actions keys. - * see config.xml config_globalActionList */ - private static final String GLOBAL_ACTION_KEY_POWER = "power"; - private static final String GLOBAL_ACTION_KEY_REBOOT = "reboot"; - private static final String GLOBAL_ACTION_KEY_AIRPLANE = "airplane"; - private 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"; - private 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"; - private final Context mContext; private final WindowManagerFuncs mWindowManagerFuncs; private final AudioManager mAudioManager; @@ -125,6 +122,9 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac private boolean mHasVibrator; private final boolean mShowSilentToggle; + // Power menu customizations + String mActions; + /** * @param context everything needs a context :( */ @@ -139,6 +139,7 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); filter.addAction(Intent.ACTION_SCREEN_OFF); + filter.addAction(Intent.UPDATE_POWER_MENU); filter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED); context.registerReceiver(mBroadcastReceiver, filter); @@ -158,6 +159,8 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac mShowSilentToggle = SHOW_SILENT_TOGGLE && !mContext.getResources().getBoolean( com.android.internal.R.bool.config_useFixedVolume); + + updatePowerMenuActions(); } /** @@ -170,9 +173,11 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac if (mDialog != null) { mDialog.dismiss(); mDialog = null; + mDialog = createDialog(); // Show delayed, so that the dismiss of the previous dialog completes mHandler.sendEmptyMessage(MESSAGE_SHOW); } else { + mDialog = createDialog(); handleShow(); } } @@ -191,7 +196,6 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac private void handleShow() { awakenIfNecessary(); - mDialog = createDialog(); prepareDialog(); // If we only have 1 item and it's a simple press action, just do this action. @@ -263,12 +267,18 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac onAirplaneModeChanged(); mItems = new ArrayList<Action>(); - String[] defaultActions = mContext.getResources().getStringArray( - com.android.internal.R.array.config_globalActionsList); + + String[] actionsArray; + if (mActions == null) { + actionsArray = mContext.getResources().getStringArray( + com.android.internal.R.array.config_globalActionsList); + } else { + actionsArray = mActions.split("\\|"); + } ArraySet<String> addedKeys = new ArraySet<String>(); - for (int i = 0; i < defaultActions.length; i++) { - String actionKey = defaultActions[i]; + for (int i = 0; i < actionsArray.length; i++) { + String actionKey = actionsArray[i]; if (addedKeys.contains(actionKey)) { // If we already have added this, don't add it again. continue; @@ -277,6 +287,8 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac mItems.add(new PowerAction()); } else if (GLOBAL_ACTION_KEY_REBOOT.equals(actionKey)) { mItems.add(new RebootAction()); + } else if (GLOBAL_ACTION_KEY_SCREENSHOT.equals(actionKey)) { + mItems.add(getScreenshotAction()); } else if (GLOBAL_ACTION_KEY_AIRPLANE.equals(actionKey)) { mItems.add(mAirplaneModeOn); } else if (GLOBAL_ACTION_KEY_BUGREPORT.equals(actionKey)) { @@ -289,7 +301,9 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac mItems.add(mSilentModeAction); } } else if (GLOBAL_ACTION_KEY_USERS.equals(actionKey)) { - if (SystemProperties.getBoolean("fw.power_user_switcher", false)) { + List<UserInfo> users = ((UserManager) mContext.getSystemService( + Context.USER_SERVICE)).getUsers(); + if (users.size() > 1) { addUsersToMenu(mItems); } } else if (GLOBAL_ACTION_KEY_SETTINGS.equals(actionKey)) { @@ -400,6 +414,24 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac } } + private Action getScreenshotAction() { + return new SinglePressAction(com.android.internal.R.drawable.ic_lock_screenshot, + R.string.global_action_screenshot) { + + public void onPress() { + takeScreenshot(); + } + + public boolean showDuringKeyguard() { + return true; + } + + public boolean showBeforeProvisioning() { + return true; + } + }; + } + private Action getBugReportAction() { return new SinglePressAction(com.android.internal.R.drawable.ic_lock_bugreport, R.string.bugreport_title) { @@ -456,7 +488,7 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac } private Action getSettingsAction() { - return new SinglePressAction(com.android.internal.R.drawable.ic_settings, + return new SinglePressAction(com.android.internal.R.drawable.ic_lock_settings, R.string.global_action_settings) { @Override @@ -573,7 +605,7 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac Drawable icon = user.iconPath != null ? Drawable.createFromPath(user.iconPath) : null; SinglePressAction switchToUser = new SinglePressAction( - com.android.internal.R.drawable.ic_menu_cc, icon, + com.android.internal.R.drawable.ic_lock_user, icon, (user.name != null ? user.name : "Primary") + (isCurrentUser ? " \u2714" : "")) { public void onPress() { @@ -598,6 +630,90 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac } } + /** + * functions needed for taking screenhots. + * This leverages the built in ICS screenshot functionality + */ + final Object mScreenshotLock = new Object(); + ServiceConnection mScreenshotConnection = null; + + final Runnable mScreenshotTimeout = new Runnable() { + @Override public void run() { + synchronized (mScreenshotLock) { + if (mScreenshotConnection != null) { + mContext.unbindService(mScreenshotConnection); + mScreenshotConnection = null; + } + } + } + }; + + private void takeScreenshot() { + synchronized (mScreenshotLock) { + if (mScreenshotConnection != null) { + return; + } + ComponentName cn = new ComponentName("com.android.systemui", + "com.android.systemui.screenshot.TakeScreenshotService"); + Intent intent = new Intent(); + intent.setComponent(cn); + ServiceConnection conn = new ServiceConnection() { + @Override + public void onServiceConnected(ComponentName name, IBinder service) { + synchronized (mScreenshotLock) { + if (mScreenshotConnection != this) { + return; + } + Messenger messenger = new Messenger(service); + Message msg = Message.obtain(null, 1); + final ServiceConnection myConn = this; + Handler h = new Handler(mHandler.getLooper()) { + @Override + public void handleMessage(Message msg) { + synchronized (mScreenshotLock) { + if (mScreenshotConnection == myConn) { + mContext.unbindService(mScreenshotConnection); + mScreenshotConnection = null; + mHandler.removeCallbacks(mScreenshotTimeout); + } + } + } + }; + msg.replyTo = new Messenger(h); + msg.arg1 = msg.arg2 = 0; + + /* remove for the time being + if (mStatusBar != null && mStatusBar.isVisibleLw()) + msg.arg1 = 1; + if (mNavigationBar != null && mNavigationBar.isVisibleLw()) + msg.arg2 = 1; + */ + + /* wait for the dialog box to close */ + try { + Thread.sleep(1000); + } catch (InterruptedException ie) { + // Do nothing + } + + /* take the screenshot */ + try { + messenger.send(msg); + } catch (RemoteException e) { + // Do nothing + } + } + } + @Override + public void onServiceDisconnected(ComponentName name) {} + }; + if (mContext.bindService(intent, conn, Context.BIND_AUTO_CREATE)) { + mScreenshotConnection = conn; + mHandler.postDelayed(mScreenshotTimeout, 10000); + } + } + } + private void prepareDialog() { refreshSilentMode(); mAirplaneModeOn.updateState(mAirplaneState); @@ -1073,10 +1189,18 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac mIsWaitingForEcmExit = false; changeAirplaneModeSystemSetting(true); } + } else if (Intent.UPDATE_POWER_MENU.equals(action)) { + updatePowerMenuActions(); } } }; + protected void updatePowerMenuActions() { + ContentResolver resolver = mContext.getContentResolver(); + mActions = Settings.Global.getStringForUser(resolver, + Settings.Global.POWER_MENU_ACTIONS, UserHandle.USER_CURRENT); + } + PhoneStateListener mPhoneStateListener = new PhoneStateListener() { @Override public void onServiceStateChanged(ServiceState serviceState) { diff --git a/services/core/java/com/android/server/power/ShutdownThread.java b/services/core/java/com/android/server/power/ShutdownThread.java index d5ad30c..596828e 100644 --- a/services/core/java/com/android/server/power/ShutdownThread.java +++ b/services/core/java/com/android/server/power/ShutdownThread.java @@ -1,5 +1,6 @@ /* * Copyright (C) 2008 The Android Open Source Project + * Copyright (C) 2013 The CyanogenMod Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,6 +22,7 @@ import android.app.ActivityManagerNative; import android.app.AlertDialog; import android.app.Dialog; import android.app.IActivityManager; +import android.app.KeyguardManager; import android.app.ProgressDialog; import android.bluetooth.BluetoothAdapter; import android.bluetooth.IBluetoothManager; @@ -44,8 +46,10 @@ import android.os.Vibrator; import android.os.SystemVibrator; import android.os.storage.IMountService; import android.os.storage.IMountShutdownObserver; +import android.provider.Settings; import android.system.ErrnoException; import android.system.Os; +import android.widget.ListView; import com.android.internal.telephony.ITelephony; import com.android.server.pm.PackageManagerService; @@ -76,6 +80,8 @@ public final class ShutdownThread extends Thread { private static final int RADIO_STOP_PERCENT = 18; private static final int MOUNT_SERVICE_STOP_PERCENT = 20; + private static final String SOFT_REBOOT = "soft_reboot"; + // length of vibration before shutting down private static final int SHUTDOWN_VIBRATE_MS = 500; @@ -134,6 +140,16 @@ public final class ShutdownThread extends Thread { shutdownInner(context, confirm); } + private static boolean isAdvancedRebootPossible(final Context context) { + KeyguardManager km = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE); + boolean keyguardLocked = km.inKeyguardRestrictedInputMode() && km.isKeyguardSecure(); + boolean advancedRebootEnabled = Settings.Secure.getInt(context.getContentResolver(), + Settings.Secure.ADVANCED_REBOOT, 0) == 1; + boolean isPrimaryUser = UserHandle.getCallingUserId() == UserHandle.USER_OWNER; + + return advancedRebootEnabled && !keyguardLocked && isPrimaryUser; + } + static void shutdownInner(final Context context, boolean confirm) { // ensure that only one thread is trying to power down. // any additional calls are just returned @@ -145,10 +161,19 @@ public final class ShutdownThread extends Thread { } boolean showRebootOption = false; - String[] defaultActions = context.getResources().getStringArray( - com.android.internal.R.array.config_globalActionsList); - for (int i = 0; i < defaultActions.length; i++) { - if (defaultActions[i].equals("reboot")) { + + String[] actionsArray; + String actions = Settings.Global.getStringForUser(context.getContentResolver(), + Settings.Global.POWER_MENU_ACTIONS, UserHandle.USER_CURRENT); + if (actions == null) { + actionsArray = context.getResources().getStringArray( + com.android.internal.R.array.config_globalActionsList); + } else { + actionsArray = actions.split("\\|"); + } + + for (int i = 0; i < actionsArray.length; i++) { + if (actionsArray[i].equals("reboot")) { showRebootOption = true; break; } @@ -168,23 +193,56 @@ public final class ShutdownThread extends Thread { if (confirm) { final CloseDialogReceiver closer = new CloseDialogReceiver(context); + final boolean advancedReboot = isAdvancedRebootPossible(context); + if (sConfirmDialog != null) { sConfirmDialog.dismiss(); + sConfirmDialog = null; } - sConfirmDialog = new AlertDialog.Builder(context) + AlertDialog.Builder confirmDialogBuilder = new AlertDialog.Builder(context) .setTitle(mRebootSafeMode ? com.android.internal.R.string.reboot_safemode_title : showRebootOption ? com.android.internal.R.string.reboot_title - : com.android.internal.R.string.power_off) - .setMessage(resourceId) - .setPositiveButton(com.android.internal.R.string.yes, new DialogInterface.OnClickListener() { + : com.android.internal.R.string.power_off); + + if (!advancedReboot) { + confirmDialogBuilder.setMessage(resourceId); + } else { + confirmDialogBuilder + .setSingleChoiceItems(com.android.internal.R.array.shutdown_reboot_options, + 0, null); + } + + confirmDialogBuilder.setPositiveButton(com.android.internal.R.string.yes, + new DialogInterface.OnClickListener() { + @Override public void onClick(DialogInterface dialog, int which) { + if (advancedReboot) { + boolean softReboot = false; + ListView reasonsList = ((AlertDialog)dialog).getListView(); + int selected = reasonsList.getCheckedItemPosition(); + if (selected != ListView.INVALID_POSITION) { + String actions[] = context.getResources().getStringArray( + com.android.internal.R.array.shutdown_reboot_actions); + if (selected >= 0 && selected < actions.length) { + mRebootReason = actions[selected]; + if (actions[selected].equals(SOFT_REBOOT)) { + doSoftReboot(); + return; + } + } + } + + mReboot = true; + } beginShutdownSequence(context); - } - }) - .setNegativeButton(com.android.internal.R.string.no, null) - .create(); + } + }); + + confirmDialogBuilder.setNegativeButton(com.android.internal.R.string.no, null); + sConfirmDialog = confirmDialogBuilder.create(); + closer.dialog = sConfirmDialog; sConfirmDialog.setOnDismissListener(closer); sConfirmDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG); @@ -194,6 +252,18 @@ public final class ShutdownThread extends Thread { } } + private static void doSoftReboot() { + try { + final IActivityManager am = + ActivityManagerNative.asInterface(ServiceManager.checkService("activity")); + if (am != null) { + am.restart(); + } + } catch (RemoteException e) { + Log.e(TAG, "failure trying to perform soft reboot", e); + } + } + private static class CloseDialogReceiver extends BroadcastReceiver implements DialogInterface.OnDismissListener { private Context mContext; @@ -295,6 +365,14 @@ public final class ShutdownThread extends Thread { pd.setIndeterminate(true); } } else { + if (mReboot) { + pd.setTitle(context.getText(com.android.internal.R.string.reboot_title)); + pd.setMessage(context.getText(com.android.internal.R.string.reboot_progress)); + } else { + pd.setTitle(context.getText(com.android.internal.R.string.power_off)); + pd.setMessage(context.getText(com.android.internal.R.string.shutdown_progress)); + } + pd.setTitle(context.getText(com.android.internal.R.string.power_off)); pd.setMessage(context.getText(com.android.internal.R.string.shutdown_progress)); pd.setIndeterminate(true); |