diff options
Diffstat (limited to 'packages')
56 files changed, 1047 insertions, 311 deletions
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardConstants.java b/packages/Keyguard/src/com/android/keyguard/KeyguardConstants.java index e5f3dc9..3927122 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardConstants.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardConstants.java @@ -27,4 +27,5 @@ public class KeyguardConstants { */ public static final boolean DEBUG = false; public static final boolean DEBUG_SIM_STATES = false; + public static final boolean DEBUG_FP_WAKELOCK = true; } diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java index 23bd238..85da298 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java @@ -308,7 +308,8 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe boolean showNextSecurityScreenOrFinish(boolean authenticated) { if (DEBUG) Log.d(TAG, "showNextSecurityScreenOrFinish(" + authenticated + ")"); boolean finish = false; - if (mUpdateMonitor.getUserHasTrust(KeyguardUpdateMonitor.getCurrentUser())) { + if (mUpdateMonitor.getUserCanSkipBouncer( + KeyguardUpdateMonitor.getCurrentUser())) { finish = true; } else if (SecurityMode.None == mCurrentSecuritySelection) { SecurityMode securityMode = mSecurityModel.getSecurityMode(); diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java index 6574e4e..b098258 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -44,7 +44,9 @@ import android.os.CancellationSignal; import android.os.Handler; import android.os.IRemoteCallback; import android.os.Message; +import android.os.PowerManager; import android.os.RemoteException; +import android.os.SystemClock; import android.os.UserHandle; import android.provider.Settings; @@ -90,12 +92,15 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { private static final String TAG = "KeyguardUpdateMonitor"; private static final boolean DEBUG = KeyguardConstants.DEBUG; private static final boolean DEBUG_SIM_STATES = KeyguardConstants.DEBUG_SIM_STATES; + private static final boolean DEBUG_FP_WAKELOCK = KeyguardConstants.DEBUG_FP_WAKELOCK; private static final int LOW_BATTERY_THRESHOLD = 20; + private static final long FINGERPRINT_WAKELOCK_TIMEOUT_MS = 15 * 1000; private static final String ACTION_FACE_UNLOCK_STARTED = "com.android.facelock.FACE_UNLOCK_STARTED"; private static final String ACTION_FACE_UNLOCK_STOPPED = "com.android.facelock.FACE_UNLOCK_STOPPED"; + private static final String FINGERPRINT_WAKE_LOCK_NAME = "wake-and-unlock wakelock"; // Callback messages private static final int MSG_TIME_UPDATE = 301; @@ -114,10 +119,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { private static final int MSG_SCREEN_TURNED_ON = 319; private static final int MSG_SCREEN_TURNED_OFF = 320; private static final int MSG_KEYGUARD_BOUNCER_CHANGED = 322; - private static final int MSG_FINGERPRINT_AUTHENTICATED = 323; - private static final int MSG_FINGERPRINT_ERROR = 324; - private static final int MSG_FINGERPRINT_HELP = 325; - private static final int MSG_FINGERPRINT_AUTH_FAILED = 326; private static final int MSG_FACE_UNLOCK_STATE_CHANGED = 327; private static final int MSG_SIM_SUBSCRIPTION_INFO_CHANGED = 328; private static final int MSG_AIRPLANE_MODE_CHANGED = 329; @@ -157,6 +158,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { private List<SubscriptionInfo> mSubscriptionInfo; private boolean mFingerprintDetectionRunning; private TrustManager mTrustManager; + private PowerManager mPowerManager; private final Handler mHandler = new Handler() { @Override @@ -210,18 +212,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { case MSG_SCREEN_TURNED_ON: handleScreenTurnedOn(); break; - case MSG_FINGERPRINT_AUTHENTICATED: - handleFingerprintAuthenticated(); - break; - case MSG_FINGERPRINT_HELP: - handleFingerprintHelp(msg.arg1 /* msgId */, (String) msg.obj /* errString */); - break; - case MSG_FINGERPRINT_ERROR: - handleFingerprintError(msg.arg1 /* msgId */, (String) msg.obj /* errString */); - break; - case MSG_FINGERPRINT_AUTH_FAILED: - handleFingerprintAuthFailed(); - break; case MSG_FACE_UNLOCK_STATE_CHANGED: handleFaceUnlockStateChanged(msg.arg1 != 0, msg.arg2); break; @@ -253,6 +243,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { private static int sCurrentUser; + private boolean mWakeAndUnlocking; + public synchronized static void setCurrentUser(int currentUser) { sCurrentUser = currentUser; } @@ -353,23 +345,72 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { } } - private void onFingerprintAuthenticated(int userId) { + private void onFingerprintAuthenticated(int userId, boolean wakeAndUnlocking) { mUserFingerprintAuthenticated.put(userId, true); for (int i = 0; i < mCallbacks.size(); i++) { KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); if (cb != null) { - cb.onFingerprintAuthenticated(userId); + cb.onFingerprintAuthenticated(userId, wakeAndUnlocking); } } } private void handleFingerprintAuthFailed() { + releaseFingerprintWakeLock(); stopListeningForFingerprint(); handleFingerprintHelp(-1, mContext.getString(R.string.fingerprint_not_recognized)); updateFingerprintListeningState(); } + private void handleFingerprintAcquired(int acquireInfo) { + if (acquireInfo != FingerprintManager.FINGERPRINT_ACQUIRED_GOOD) { + return; + } + if (!mScreenOn) { + releaseFingerprintWakeLock(); + mWakeLock = mPowerManager.newWakeLock( + PowerManager.PARTIAL_WAKE_LOCK, FINGERPRINT_WAKE_LOCK_NAME); + mWakeLock.acquire(); + mWakeAndUnlocking = true; + if (DEBUG_FP_WAKELOCK) { + Log.i(TAG, "fingerprint acquired, grabbing fp wakelock"); + } + mHandler.postDelayed(mReleaseFingerprintWakeLockRunnable, + FINGERPRINT_WAKELOCK_TIMEOUT_MS); + } else { + mWakeAndUnlocking = false; + } + } + + private final Runnable mReleaseFingerprintWakeLockRunnable = new Runnable() { + @Override + public void run() { + if (DEBUG_FP_WAKELOCK) { + Log.i(TAG, "fp wakelock: TIMEOUT!!"); + } + releaseFingerprintWakeLock(); + } + }; + + private void releaseFingerprintWakeLock() { + if (mWakeLock != null) { + mHandler.removeCallbacks(mReleaseFingerprintWakeLockRunnable); + if (DEBUG_FP_WAKELOCK) { + Log.i(TAG, "releasing fp wakelock"); + } + mWakeLock.release(); + mWakeLock = null; + } + } + private void handleFingerprintAuthenticated() { + if (mWakeAndUnlocking) { + if (DEBUG_FP_WAKELOCK) { + Log.i(TAG, "fp wakelock: Authenticated, waking up..."); + } + mPowerManager.wakeUp(SystemClock.uptimeMillis()); + } + releaseFingerprintWakeLock(); try { final int userId; try { @@ -382,7 +423,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { Log.d(TAG, "Fingerprint disabled by DPM for userId: " + userId); return; } - onFingerprintAuthenticated(userId); + onFingerprintAuthenticated(userId, mWakeAndUnlocking); } finally { setFingerprintRunningDetectionRunning(false); } @@ -455,9 +496,12 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { & DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT) != 0; } + public boolean getUserCanSkipBouncer(int userId) { + return getUserHasTrust(userId) || mUserFingerprintAuthenticated.get(userId); + } + public boolean getUserHasTrust(int userId) { - return !isTrustDisabled(userId) && mUserHasTrust.get(userId) - || mUserFingerprintAuthenticated.get(userId); + return !isTrustDisabled(userId) && mUserHasTrust.get(userId); } public boolean getUserTrustIsManaged(int userId) { @@ -552,26 +596,32 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { @Override public void onAuthenticationFailed() { - mHandler.obtainMessage(MSG_FINGERPRINT_AUTH_FAILED).sendToTarget(); + handleFingerprintAuthFailed(); }; @Override public void onAuthenticationSucceeded(AuthenticationResult result) { - mHandler.obtainMessage(MSG_FINGERPRINT_AUTHENTICATED).sendToTarget(); + handleFingerprintAuthenticated(); } @Override public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) { - mHandler.obtainMessage(MSG_FINGERPRINT_HELP, helpMsgId, 0, helpString).sendToTarget(); + handleFingerprintHelp(helpMsgId, helpString.toString()); } @Override public void onAuthenticationError(int errMsgId, CharSequence errString) { - mHandler.obtainMessage(MSG_FINGERPRINT_ERROR, errMsgId, 0, errString).sendToTarget(); + handleFingerprintError(errMsgId, errString.toString()); + } + + @Override + public void onAuthenticationAcquired(int acquireInfo) { + handleFingerprintAcquired(acquireInfo); } }; private CancellationSignal mFingerprintCancelSignal; private FingerprintManager mFpm; + private PowerManager.WakeLock mWakeLock; /** * When we receive a @@ -738,6 +788,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { private KeyguardUpdateMonitor(Context context) { mContext = context; mSubscriptionManager = SubscriptionManager.from(context); + mPowerManager = context.getSystemService(PowerManager.class); mDeviceProvisioned = isDeviceProvisionedInSettingsDb(); // Since device can't be un-provisioned, we only need to register a content observer // to update mDeviceProvisioned when we are... @@ -816,7 +867,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { } private boolean shouldListenForFingerprint() { - return mScreenOn && mKeyguardIsVisible && !mSwitchingUser + return mKeyguardIsVisible && !mSwitchingUser && mTrustManager.hasUserAuthenticatedSinceBoot(ActivityManager.getCurrentUser()); } diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java index 26e6973..9fd8d30 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java @@ -178,8 +178,10 @@ public class KeyguardUpdateMonitorCallback { /** * Called when a fingerprint is recognized. * @param userId the user id for which the fingerprint was authenticated + * @param wakeAndUnlocking whether the authentication woke the device up and thus we'd like to + * dismiss the lockscreen before turning on the screen */ - public void onFingerprintAuthenticated(int userId) { } + public void onFingerprintAuthenticated(int userId, boolean wakeAndUnlocking) { } /** * Called when fingerprint provides help string (e.g. "Try again") diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml index 9832b45..c00fdf3 100644 --- a/packages/Shell/AndroidManifest.xml +++ b/packages/Shell/AndroidManifest.xml @@ -76,7 +76,9 @@ <uses-permission android:name="android.permission.FORCE_STOP_PACKAGES" /> <uses-permission android:name="android.permission.STOP_APP_SWITCHES" /> <uses-permission android:name="android.permission.ACCESS_CONTENT_PROVIDERS_EXTERNALLY" /> - <uses-permission android:name="android.permission.GRANT_REVOKE_PERMISSIONS" /> + <uses-permission android:name="android.permission.GRANT_RUNTIME_PERMISSIONS" /> + <uses-permission android:name="android.permission.REVOKE_RUNTIME_PERMISSIONS" /> + <uses-permission android:name="android.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS" /> <uses-permission android:name="android.permission.SET_KEYBOARD_LAYOUT" /> <uses-permission android:name="android.permission.GET_DETAILED_TASKS" /> <uses-permission android:name="android.permission.SET_SCREEN_COMPATIBILITY" /> diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml index 6e5dc3f..fea7f94 100644 --- a/packages/SystemUI/AndroidManifest.xml +++ b/packages/SystemUI/AndroidManifest.xml @@ -405,5 +405,13 @@ android:exported="true" android:singleUser="true" android:permission="android.permission.BIND_DREAM_SERVICE" /> + + <receiver + android:name=".tuner.TunerService$ClearReceiver" + android:exported="false"> + <intent-filter> + <action android:name="com.android.systemui.action.CLEAR_TUNER" /> + </intent-filter> + </receiver> </application> </manifest> diff --git a/packages/SystemUI/res/drawable-nodpi/tuner.xml b/packages/SystemUI/res/drawable-nodpi/tuner.xml index e27423f..0596aa4 100644 --- a/packages/SystemUI/res/drawable-nodpi/tuner.xml +++ b/packages/SystemUI/res/drawable-nodpi/tuner.xml @@ -1,7 +1,7 @@ <!-- - Copyright (C) 2015 The Android Open Source Project + Copyright (C) 2015 The Android Open Source Project - Licensed under the Apache License, Version 2.0 (the "License"); + 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 @@ -14,14 +14,11 @@ limitations under the License. --> <vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="48.0dp" - android:height="48.0dp" - android:viewportWidth="48.0" - android:viewportHeight="48.0"> + android:width="24.0dp" + android:height="24.0dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> <path - android:fillColor="#FF000000" - android:pathData="M29.9,24.8c0.0,-0.3 0.1,-0.5 0.1,-0.8s0.0,-0.5 -0.1,-0.8l1.7,-1.3c0.2,-0.1 0.2,-0.3 0.1,-0.5l-1.6,-2.8c-0.1,-0.2 -0.3,-0.2 -0.5,-0.2l-2.0,0.8c-0.4,-0.3 -0.9,-0.6 -1.4,-0.8L26.0,16.3c0.0,-0.2 -0.2,-0.3 -0.4,-0.3l-3.2,0.0c-0.2,0.0 -0.4,0.1 -0.4,0.3l-0.3,2.1c-0.5,0.2 -0.9,0.5 -1.4,0.8l-2.0,-0.8c-0.2,-0.1 -0.4,0.0 -0.5,0.2l-1.6,2.8c-0.1,0.2 -0.1,0.4 0.1,0.5l1.7,1.3c0.0,0.3 -0.1,0.5 -0.1,0.8s0.0,0.5 0.1,0.8l-1.7,1.3c-0.2,0.1 -0.2,0.3 -0.1,0.5l1.6,2.8c0.1,0.2 0.3,0.2 0.5,0.2l2.0,-0.8c0.4,0.3 0.9,0.6 1.4,0.8l0.3,2.1c0.0,0.2 0.2,0.3 0.4,0.3l3.2,0.0c0.2,0.0 0.4,-0.1 0.4,-0.3l0.3,-2.1c0.5,-0.2 0.9,-0.5 1.4,-0.8l2.0,0.8c0.2,0.1 0.4,0.0 0.5,-0.2l1.6,-2.8c0.1,-0.2 0.1,-0.4 -0.1,-0.5L29.9,24.8zM24.0,26.8c-1.5,0.0 -2.8,-1.3 -2.8,-2.8s1.3,-2.8 2.8,-2.8s2.8,1.3 2.8,2.8S25.5,26.8 24.0,26.8z"/> - <path - android:fillColor="#FF000000" - android:pathData="M18.0,38.0c-0.6,0.0 -1.0,-0.4 -1.0,-1.0s0.4,-1.0 1.0,-1.0s1.0,0.4 1.0,1.0S18.6,38.0 18.0,38.0zM24.0,38.0c-0.6,0.0 -1.0,-0.4 -1.0,-1.0s0.4,-1.0 1.0,-1.0s1.0,0.4 1.0,1.0S24.6,38.0 24.0,38.0zM30.0,38.0c-0.6,0.0 -1.0,-0.4 -1.0,-1.0s0.4,-1.0 1.0,-1.0s1.0,0.4 1.0,1.0S30.6,38.0 30.0,38.0zM42.0,6.0L6.0,6.0c-2.2,0.0 -4.0,1.8 -4.0,4.0l0.0,28.0c0.0,2.2 1.8,4.0 4.0,4.0l36.0,0.0c2.2,0.0 4.0,-1.8 4.0,-4.0L46.0,10.0C46.0,7.8 44.2,6.0 42.0,6.0zM42.0,34.0L6.0,34.0L6.0,14.0l36.0,0.0L42.0,34.0zM9.0,12.0L7.0,12.0l0.0,-2.0l2.0,0.0L9.0,12.0zM13.0,12.0l-2.0,0.0l0.0,-2.0l2.0,0.0L13.0,12.0zM17.0,12.0l-2.0,0.0l0.0,-2.0l2.0,0.0L17.0,12.0z"/> + android:fillColor="#FFFFFFFF" + android:pathData="M22.7,19.0l-9.1,-9.1c0.9,-2.0 0.4,-5.0 -1.5,-6.9 -2.0,-2.0 -5.0,-2.4 -7.4,-1.3L9.0,6.0 6.0,9.0 1.6,4.7C0.4,7.0 0.9,10.1 2.9,12.1c1.9,1.9 4.6,2.4 6.9,1.5l9.1,9.1c0.4,0.4 1.0,0.4 1.4,0.0l2.3,-2.3c0.5,-0.4 0.5,-1.0 0.1,-1.4z"/> </vector> diff --git a/packages/SystemUI/res/layout/keyguard_bottom_area.xml b/packages/SystemUI/res/layout/keyguard_bottom_area.xml index 1488ad6..444f0f0 100644 --- a/packages/SystemUI/res/layout/keyguard_bottom_area.xml +++ b/packages/SystemUI/res/layout/keyguard_bottom_area.xml @@ -26,7 +26,7 @@ <com.android.systemui.statusbar.phone.KeyguardIndicationTextView android:id="@+id/keyguard_indication_text" - android:layout_width="wrap_content" + android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="@dimen/keyguard_indication_margin_bottom" android:layout_gravity="bottom|center_horizontal" diff --git a/packages/SystemUI/res/layout/qs_detail_item.xml b/packages/SystemUI/res/layout/qs_detail_item.xml index a519d3f..6facb71 100644 --- a/packages/SystemUI/res/layout/qs_detail_item.xml +++ b/packages/SystemUI/res/layout/qs_detail_item.xml @@ -20,6 +20,7 @@ android:minHeight="@dimen/qs_detail_item_height" android:background="@drawable/btn_borderless_rect" android:clickable="true" + android:focusable="true" android:gravity="center_vertical" android:orientation="horizontal" > @@ -57,6 +58,7 @@ android:layout_width="48dp" android:layout_height="48dp" android:clickable="true" + android:focusable="true" android:scaleType="center" android:src="@drawable/ic_qs_cancel" /> diff --git a/packages/SystemUI/res/layout/status_bar.xml b/packages/SystemUI/res/layout/status_bar.xml index 3118d08..a5b3a83 100644 --- a/packages/SystemUI/res/layout/status_bar.xml +++ b/packages/SystemUI/res/layout/status_bar.xml @@ -25,7 +25,7 @@ android:id="@+id/status_bar" android:background="@drawable/system_bar_background" android:orientation="vertical" - android:focusable="true" + android:focusable="false" android:descendantFocusability="afterDescendants" > diff --git a/packages/SystemUI/res/layout/status_bar_expanded_header.xml b/packages/SystemUI/res/layout/status_bar_expanded_header.xml index 7262ed2..8c8a3dd 100644 --- a/packages/SystemUI/res/layout/status_bar_expanded_header.xml +++ b/packages/SystemUI/res/layout/status_bar_expanded_header.xml @@ -44,14 +44,31 @@ android:scaleType="centerInside"/> </com.android.systemui.statusbar.phone.MultiUserSwitch> - <com.android.keyguard.AlphaOptimizedImageButton android:id="@+id/settings_button" - style="@android:style/Widget.Material.Button.Borderless" - android:layout_toStartOf="@id/multi_user_switch" + <com.android.keyguard.AlphaOptimizedLinearLayout + android:id="@+id/settings_button_container" android:layout_width="48dp" android:layout_height="@dimen/status_bar_header_height" - android:background="@drawable/ripple_drawable" - android:src="@drawable/ic_settings" - android:contentDescription="@string/accessibility_desc_settings" /> + android:paddingStart="12dp" + android:clipChildren="false" + android:clipToPadding="false" + android:layout_toStartOf="@id/multi_user_switch"> + + <com.android.systemui.statusbar.phone.SettingsButton android:id="@+id/settings_button" + style="@android:style/Widget.Material.Button.Borderless" + android:layout_width="24dp" + android:layout_height="@dimen/status_bar_header_height" + android:background="@drawable/ripple_drawable" + android:src="@drawable/ic_settings" + android:contentDescription="@string/accessibility_desc_settings" /> + <com.android.systemui.statusbar.AlphaOptimizedImageView android:id="@+id/tuner_icon" + android:layout_width="12dp" + android:layout_height="@dimen/status_bar_header_height" + android:tint="#4DFFFFFF" + android:tintMode="src_in" + android:visibility="invisible" + android:src="@drawable/tuner" /> + + </com.android.keyguard.AlphaOptimizedLinearLayout> <LinearLayout android:id="@+id/system_icons_super_container" android:layout_width="wrap_content" diff --git a/packages/SystemUI/res/layout/status_bar_notification_dismiss_all.xml b/packages/SystemUI/res/layout/status_bar_notification_dismiss_all.xml index 6a000fd..dc7577a 100644 --- a/packages/SystemUI/res/layout/status_bar_notification_dismiss_all.xml +++ b/packages/SystemUI/res/layout/status_bar_notification_dismiss_all.xml @@ -27,6 +27,7 @@ android:layout_width="48dp" android:layout_height="48dp" android:layout_gravity="end" + android:focusable="true" android:background="@drawable/ripple_drawable" android:contentDescription="@string/accessibility_clear_all"/> </com.android.systemui.statusbar.DismissView> diff --git a/packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml b/packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml index 4526af5..f699fce 100644 --- a/packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml +++ b/packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml @@ -31,7 +31,7 @@ android:layout_height="match_parent" /> - <LinearLayout + <com.android.keyguard.AlphaOptimizedLinearLayout android:id="@+id/content" android:layout_width="match_parent" android:layout_height="match_parent"> @@ -63,6 +63,6 @@ android:layout_width="match_parent" android:layout_height="wrap_content" /> - </LinearLayout> + </com.android.keyguard.AlphaOptimizedLinearLayout> </com.android.systemui.statusbar.NotificationOverflowContainer> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index 3210a24..03ea73c 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -562,7 +562,7 @@ <!-- Padding to be used on the bottom of the fingerprint icon on Keyguard so it better aligns with the other icons. --> - <dimen name="fingerprint_icon_additional_padding">12dp</dimen> + <dimen name="fingerprint_icon_additional_padding">4dp</dimen> <!-- Minimum margin of the notification panel on the side, when being positioned dynamically --> <dimen name="notification_panel_min_side_margin">48dp</dimen> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index fcf7e3e..3eac84f 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -1032,7 +1032,7 @@ <string name="volume_stream_vibrate_dnd" translatable="false">%s vibrate — Priority only</string> <!-- Name of special SystemUI debug settings --> - <string name="system_ui_tuner">System UI tuner</string> + <string name="system_ui_tuner">System UI Tuner</string> <!-- Preference to show/hide embedded battery percentage [CHAR LIMIT=50] --> <string name="show_battery_percentage">Show embedded battery percentage</string> @@ -1099,4 +1099,25 @@ <!-- Accessibility label for managed profile icon (not shown on screen) [CHAR LIMIT=NONE] --> <string name="accessibility_managed_profile">Work profile</string> + <!-- Title of warning when entering System UI tuner for first time [CHAR LIMIT=NONE] --> + <string name="tuner_warning_title">Fun for some but not for all</string> + + <!-- Warning for users entering the System UI tuner for the first time [CHAR LIMIT=NONE]--> + <string name="tuner_warning">System UI Tuner gives you extra ways to tweak and customize the Android user interface. These experimental features may change, break, or disappear in future releases. Proceed with caution.</string> + + <!-- Warning for users entering the System UI tuner [CHAR LIMIT=NONE]--> + <string name="tuner_persistent_warning">These experimental features may change, break, or disappear in future releases. Proceed with caution.</string> + + <!-- Generic "got it" acceptance of dialog or cling [CHAR LIMIT=NONE] --> + <string name="got_it">Got it</string> + + <!-- Toast describing tuner has been enabled [CHAR LIMIT=NONE] --> + <string name="tuner_toast">Congrats! System UI Tuner has been added to Settings</string> + + <!-- Option to remove the tuner from settings [CHAR LIMIT=NONE] --> + <string name="remove_from_settings">Remove from Settings</string> + + <!-- Dialog asking if the tuner should really be removed from settings [CHAR LIMIT=NONE]--> + <string name="remove_from_settings_prompt">Remove System UI Tuner from Settings and stop using all of its features?"</string> + </resources> diff --git a/packages/SystemUI/res/xml/tuner_prefs.xml b/packages/SystemUI/res/xml/tuner_prefs.xml index 8c1acc3..3a41c3c 100644 --- a/packages/SystemUI/res/xml/tuner_prefs.xml +++ b/packages/SystemUI/res/xml/tuner_prefs.xml @@ -76,4 +76,8 @@ android:key="demo_mode" android:title="@string/demo_mode" /> + <Preference + android:summary="@string/tuner_persistent_warning" + android:selectable="false" /> + </PreferenceScreen> diff --git a/packages/SystemUI/src/com/android/systemui/DejankUtils.java b/packages/SystemUI/src/com/android/systemui/DejankUtils.java new file mode 100644 index 0000000..fc98ec4 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/DejankUtils.java @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2015 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 + */ + +package com.android.systemui; + +import android.os.Handler; +import android.os.Looper; +import android.os.StrictMode; +import android.view.Choreographer; + +import java.util.ArrayList; + +/** + * Utility class for methods used to dejank the UI. + */ +public class DejankUtils { + + private static final Choreographer sChoreographer = Choreographer.getInstance(); + private static final Handler sHandler = new Handler(); + + private static final ArrayList<Runnable> sPendingRunnables = new ArrayList<>(); + + private static final Runnable sAnimationCallbackRunnable = new Runnable() { + @Override + public void run() { + for (int i = 0; i < sPendingRunnables.size(); i++) { + sHandler.post(sPendingRunnables.get(i)); + } + sPendingRunnables.clear(); + } + }; + + /** + * Executes {@code r} after performTraversals. Use this do to CPU heavy work for which the + * timing is not critical for animation. The work is then scheduled at the same time + * RenderThread is doing its thing, leading to better parallelization. + * + * <p>Needs to be called from the main thread. + */ + public static void postAfterTraversal(Runnable r) { + throwIfNotCalledOnMainThread(); + sPendingRunnables.add(r); + postAnimationCallback(); + } + + /** + * Removes a previously scheduled runnable. + * + * <p>Needs to be called from the main thread. + */ + public static void removeCallbacks(Runnable r) { + throwIfNotCalledOnMainThread(); + sPendingRunnables.remove(r); + sHandler.removeCallbacks(r); + } + + private static void postAnimationCallback() { + sChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION, sAnimationCallbackRunnable, + null); + } + + private static void throwIfNotCalledOnMainThread() { + if (!Looper.getMainLooper().isCurrentThread()) { + throw new IllegalStateException("should be called from the main thread."); + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/DemoMode.java b/packages/SystemUI/src/com/android/systemui/DemoMode.java index d406f5b..11996d0 100644 --- a/packages/SystemUI/src/com/android/systemui/DemoMode.java +++ b/packages/SystemUI/src/com/android/systemui/DemoMode.java @@ -20,6 +20,8 @@ import android.os.Bundle; public interface DemoMode { + public static final String DEMO_MODE_ALLOWED = "sysui_demo_allowed"; + void dispatchDemoCommand(String command, Bundle args); public static final String ACTION_DEMO = "com.android.systemui.demo"; diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java index 9f6d8df..8556afc 100644 --- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java +++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java @@ -116,7 +116,6 @@ public class ImageWallpaper extends WallpaperService { private final DisplayInfo mTmpDisplayInfo = new DisplayInfo(); boolean mVisible = true; - boolean mRedrawNeeded; boolean mOffsetsChanged; int mLastXTranslation; int mLastYTranslation; @@ -153,6 +152,9 @@ public class ImageWallpaper extends WallpaperService { private int mDisplayWidthAtLastSurfaceSizeUpdate = -1; private int mDisplayHeightAtLastSurfaceSizeUpdate = -1; + private int mLastRequestedWidth = -1; + private int mLastRequestedHeight = -1; + public DrawableEngine() { super(); setFixedSizeAllowed(true); @@ -211,21 +213,13 @@ public class ImageWallpaper extends WallpaperService { int surfaceWidth = Math.max(displayInfo.logicalWidth, mBackgroundWidth); int surfaceHeight = Math.max(displayInfo.logicalHeight, mBackgroundHeight); - // If the surface dimensions haven't changed, then just return - final Rect frame = surfaceHolder.getSurfaceFrame(); - if (frame != null) { - final int dw = frame.width(); - final int dh = frame.height(); - if (surfaceWidth == dw && surfaceHeight == dh) { - return; - } - } - if (FIXED_SIZED_SURFACE) { // Used a fixed size surface, because we are special. We can do // this because we know the current design of window animations doesn't // cause this to break. surfaceHolder.setFixedSize(surfaceWidth, surfaceHeight); + mLastRequestedWidth = surfaceWidth; + mLastRequestedHeight = surfaceHeight; } else { surfaceHolder.setSizeFromLayout(); } @@ -387,7 +381,6 @@ public class ImageWallpaper extends WallpaperService { yPixels += (int) (availhUnscaled * (mYOffset - .5f) + .5f); mOffsetsChanged = false; - mRedrawNeeded = false; if (surfaceDimensionsChanged) { mLastSurfaceWidth = dw; mLastSurfaceHeight = dh; @@ -475,13 +468,15 @@ public class ImageWallpaper extends WallpaperService { out.print(" mYOffset="); out.println(mYOffset); out.print(prefix); out.print(" mVisible="); out.print(mVisible); - out.print(" mRedrawNeeded="); out.print(mRedrawNeeded); out.print(" mOffsetsChanged="); out.println(mOffsetsChanged); out.print(prefix); out.print(" mLastXTranslation="); out.print(mLastXTranslation); out.print(" mLastYTranslation="); out.print(mLastYTranslation); out.print(" mScale="); out.println(mScale); + out.print(prefix); out.print(" mLastRequestedWidth="); out.print(mLastRequestedWidth); + out.print(" mLastRequestedHeight="); out.println(mLastRequestedHeight); + out.print(prefix); out.println(" DisplayInfo at last updateSurfaceSize:"); out.print(prefix); out.print(" rotation="); out.print(mRotationAtLastSurfaceSizeUpdate); diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java index 0daa5c9..9265b63 100644 --- a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java +++ b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java @@ -18,6 +18,7 @@ import android.os.Handler; import android.os.RemoteException; import android.os.UserHandle; import android.provider.Settings; +import android.service.voice.VoiceInteractionSession; import android.util.Log; import android.view.Gravity; import android.view.HapticFeedbackConstants; @@ -218,7 +219,8 @@ public class AssistManager { } private void startVoiceInteractor(Bundle args) { - mAssistUtils.showSessionForActiveService(args, mShowCallback); + mAssistUtils.showSessionForActiveService(args, + VoiceInteractionSession.SHOW_SOURCE_ASSIST_GESTURE, mShowCallback, null); } public void launchVoiceAssistFromKeyguard() { @@ -302,4 +304,8 @@ public class AssistManager { public void onUserSwitched(int newUserId) { updateAssistInfo(); } + + public void onLockscreenShown() { + mAssistUtils.onLockscreenShown(); + } } diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java index 5d46712..887391c 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java @@ -136,7 +136,7 @@ public class DozeService extends DreamService { mDozeParameters.getPulseOnPickup(), mDozeParameters.getVibrateOnPickup(), DozeLog.PULSE_REASON_SENSOR_PICKUP); mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); - mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, mTag); + mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG); mWakeLock.setReferenceCounted(true); mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE); mDisplayStateSupported = mDozeParameters.getDisplayStateSupported(); diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java index 98558b4..9f21dbe 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java @@ -25,9 +25,9 @@ import android.os.IBinder; import android.os.Process; import android.util.Log; +import com.android.internal.policy.IKeyguardDrawnCallback; import com.android.internal.policy.IKeyguardExitCallback; import com.android.internal.policy.IKeyguardService; -import com.android.internal.policy.IKeyguardShowCallback; import com.android.internal.policy.IKeyguardStateCallback; import com.android.systemui.SystemUIApplication; @@ -120,9 +120,15 @@ public class KeyguardService extends Service { } @Override // Binder interface - public void onStartedWakingUp(IKeyguardShowCallback callback) { + public void onStartedWakingUp() { checkPermission(); - mKeyguardViewMediator.onStartedWakingUp(callback); + mKeyguardViewMediator.onStartedWakingUp(); + } + + @Override // Binder interface + public void onScreenTurningOn(IKeyguardDrawnCallback callback) { + checkPermission(); + mKeyguardViewMediator.onScreenTurningOn(callback); } @Override // Binder interface diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index 009a0d6..c01a485 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -41,6 +41,7 @@ import android.os.PowerManager; import android.os.RemoteException; import android.os.SystemClock; import android.os.SystemProperties; +import android.os.Trace; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; @@ -55,8 +56,9 @@ import android.view.WindowManagerGlobal; import android.view.WindowManagerPolicy; import android.view.animation.Animation; import android.view.animation.AnimationUtils; + +import com.android.internal.policy.IKeyguardDrawnCallback; import com.android.internal.policy.IKeyguardExitCallback; -import com.android.internal.policy.IKeyguardShowCallback; import com.android.internal.policy.IKeyguardStateCallback; import com.android.internal.telephony.IccCardConstants; import com.android.internal.widget.LockPatternUtils; @@ -77,7 +79,6 @@ import java.util.List; import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT; - /** * Mediates requests related to the keyguard. This includes queries about the * state of the keyguard, power management events that effect whether the keyguard @@ -138,7 +139,7 @@ public class KeyguardViewMediator extends SystemUI { private static final int RESET = 4; private static final int VERIFY_UNLOCK = 5; private static final int NOTIFY_SCREEN_OFF = 6; - private static final int NOTIFY_SCREEN_ON = 7; + private static final int NOTIFY_SCREEN_TURNING_ON = 7; private static final int KEYGUARD_DONE = 9; private static final int KEYGUARD_DONE_DRAWING = 10; private static final int KEYGUARD_DONE_AUTHENTICATING = 11; @@ -148,6 +149,7 @@ public class KeyguardViewMediator extends SystemUI { private static final int START_KEYGUARD_EXIT_ANIM = 18; private static final int ON_ACTIVITY_DRAWN = 19; private static final int KEYGUARD_DONE_PENDING_TIMEOUT = 20; + private static final int NOTIFY_STARTED_WAKING_UP = 21; /** * The default amount of time we stay awake (used for all key input) @@ -311,11 +313,14 @@ public class KeyguardViewMediator extends SystemUI { private boolean mPendingReset; /** - * When starting goign to sleep, we figured out that we need to lock Keyguard and this should be + * When starting going to sleep, we figured out that we need to lock Keyguard and this should be * committed when finished going to sleep. */ private boolean mPendingLock; + private boolean mWakeAndUnlocking; + private IKeyguardDrawnCallback mDrawnCallback; + KeyguardUpdateMonitorCallback mUpdateCallback = new KeyguardUpdateMonitorCallback() { @Override @@ -454,12 +459,17 @@ public class KeyguardViewMediator extends SystemUI { } @Override - public void onFingerprintAuthenticated(int userId) { + public void onFingerprintAuthenticated(int userId, boolean wakeAndUnlocking) { if (mStatusBarKeyguardViewManager.isBouncerShowing()) { mStatusBarKeyguardViewManager.notifyKeyguardAuthenticated(); } else { - mStatusBarKeyguardViewManager.animateCollapsePanels( - FINGERPRINT_COLLAPSE_SPEEDUP_FACTOR); + if (wakeAndUnlocking) { + mWakeAndUnlocking = true; + keyguardDone(true, true); + } else { + mStatusBarKeyguardViewManager.animateCollapsePanels( + FINGERPRINT_COLLAPSE_SPEEDUP_FACTOR); + } } }; @@ -752,21 +762,23 @@ public class KeyguardViewMediator extends SystemUI { /** * Let's us know when the device is waking up. */ - public void onStartedWakingUp(IKeyguardShowCallback callback) { + public void onStartedWakingUp() { // TODO: Rename all screen off/on references to interactive/sleeping synchronized (this) { mDeviceInteractive = true; cancelDoKeyguardLaterLocked(); if (DEBUG) Log.d(TAG, "onStartedWakingUp, seq = " + mDelayedShowingSequence); - if (callback != null) { - notifyScreenOnLocked(callback); - } + notifyStartedWakingUp(); } KeyguardUpdateMonitor.getInstance(mContext).dispatchScreenTurnedOn(); maybeSendUserPresentBroadcast(); } + public void onScreenTurningOn(IKeyguardDrawnCallback callback) { + notifyScreenOnLocked(callback); + } + private void maybeSendUserPresentBroadcast() { if (mSystemReady && mLockPatternUtils.isLockScreenDisabled( KeyguardUpdateMonitor.getCurrentUser())) { @@ -1093,14 +1105,14 @@ public class KeyguardViewMediator extends SystemUI { mHandler.sendEmptyMessage(NOTIFY_SCREEN_OFF); } - /** - * Send a message to keyguard telling it the screen just turned on. - * @see #onScreenTurnedOn - * @see #handleNotifyScreenOn - */ - private void notifyScreenOnLocked(IKeyguardShowCallback result) { + private void notifyStartedWakingUp() { + if (DEBUG) Log.d(TAG, "notifyStartedWakingUp"); + mHandler.sendEmptyMessage(NOTIFY_STARTED_WAKING_UP); + } + + private void notifyScreenOnLocked(IKeyguardDrawnCallback callback) { if (DEBUG) Log.d(TAG, "notifyScreenOnLocked"); - Message msg = mHandler.obtainMessage(NOTIFY_SCREEN_ON, result); + Message msg = mHandler.obtainMessage(NOTIFY_SCREEN_TURNING_ON, callback); mHandler.sendMessage(msg); } @@ -1190,8 +1202,11 @@ public class KeyguardViewMediator extends SystemUI { case NOTIFY_SCREEN_OFF: handleNotifyScreenOff(); break; - case NOTIFY_SCREEN_ON: - handleNotifyScreenOn((IKeyguardShowCallback) msg.obj); + case NOTIFY_SCREEN_TURNING_ON: + handleNotifyScreenTurningOn((IKeyguardDrawnCallback) msg.obj); + break; + case NOTIFY_STARTED_WAKING_UP: + handleNotifyStartedWakingUp(); break; case KEYGUARD_DONE: handleKeyguardDone(msg.arg1 != 0, msg.arg2 != 0); @@ -1354,6 +1369,7 @@ public class KeyguardViewMediator extends SystemUI { setShowingLocked(true); mStatusBarKeyguardViewManager.show(options); mHiding = false; + mWakeAndUnlocking = false; resetKeyguardDonePendingLocked(); mHideAnimationRun = false; updateActivityLockScreenState(); @@ -1375,7 +1391,8 @@ public class KeyguardViewMediator extends SystemUI { // manager until it tells us it's safe to do so with // startKeyguardExitAnimation. ActivityManagerNative.getDefault().keyguardGoingAway( - mStatusBarKeyguardViewManager.shouldDisableWindowAnimationsForUnlock(), + mStatusBarKeyguardViewManager.shouldDisableWindowAnimationsForUnlock() + || mWakeAndUnlocking, mStatusBarKeyguardViewManager.isGoingToNotificationShade()); } catch (RemoteException e) { Log.e(TAG, "Error while calling WindowManager", e); @@ -1437,6 +1454,9 @@ public class KeyguardViewMediator extends SystemUI { updateActivityLockScreenState(); adjustStatusBarLocked(); sendUserPresentBroadcast(); + if (mWakeAndUnlocking && mDrawnCallback != null) { + notifyDrawn(mDrawnCallback); + } } } @@ -1508,14 +1528,31 @@ public class KeyguardViewMediator extends SystemUI { } } - /** - * Handle message sent by {@link #notifyScreenOnLocked} - * @see #NOTIFY_SCREEN_ON - */ - private void handleNotifyScreenOn(IKeyguardShowCallback callback) { + private void handleNotifyStartedWakingUp() { + synchronized (KeyguardViewMediator.this) { + if (DEBUG) Log.d(TAG, "handleNotifyWakingUp"); + mStatusBarKeyguardViewManager.onScreenTurnedOn(); + } + } + + private void handleNotifyScreenTurningOn(IKeyguardDrawnCallback callback) { synchronized (KeyguardViewMediator.this) { - if (DEBUG) Log.d(TAG, "handleNotifyScreenOn"); - mStatusBarKeyguardViewManager.onScreenTurnedOn(callback); + if (DEBUG) Log.d(TAG, "handleNotifyScreenTurningOn"); + if (callback != null) { + if (mWakeAndUnlocking) { + mDrawnCallback = callback; + } else { + notifyDrawn(callback); + } + } + } + } + + private void notifyDrawn(final IKeyguardDrawnCallback callback) { + try { + callback.onDrawn(); + } catch (RemoteException e) { + Slog.w(TAG, "Exception calling onDrawn():", e); } } diff --git a/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java b/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java index e9a256c..fe876d7 100644 --- a/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java +++ b/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java @@ -171,6 +171,13 @@ public class RingtonePlayer extends SystemUI { } mAsyncPlayer.stop(); } + + @Override + public String getTitle(Uri uri) { + final UserHandle user = Binder.getCallingUserHandle(); + return Ringtone.getTitle(getContextForUser(user), uri, + false /*followSettingsUri*/, false /*allowRemote*/); + } }; private Context getContextForUser(UserHandle user) { diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java index 937615a..61695b2 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java @@ -92,7 +92,8 @@ public class CastTile extends QSTile<QSTile.BooleanState> { @Override protected void handleUpdateState(BooleanState state, Object arg) { - state.visible = !(mKeyguard.isSecure() && mKeyguard.isShowing() && !mKeyguard.isTrusted()); + state.visible = !mKeyguard.isSecure() || !mKeyguard.isShowing() + || mKeyguard.canSkipBouncer(); state.label = mContext.getString(R.string.quick_settings_cast_title); state.value = false; state.autoMirrorDrawable = false; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java index 07406b9..f3ad9d8 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java @@ -45,6 +45,8 @@ public class CellularTile extends QSTile<QSTile.SignalState> { private final MobileDataController mDataController; private final CellularDetailAdapter mDetailAdapter; + private final CellSignalCallback mSignalCallback = new CellSignalCallback(); + public CellularTile(Host host) { super(host); mController = host.getNetworkController(); @@ -90,8 +92,10 @@ public class CellularTile extends QSTile<QSTile.SignalState> { protected void handleUpdateState(SignalState state, Object arg) { state.visible = mController.hasMobileDataFeature(); if (!state.visible) return; - final CallbackInfo cb = (CallbackInfo) arg; - if (cb == null) return; + CallbackInfo cb = (CallbackInfo) arg; + if (cb == null) { + cb = mSignalCallback.mInfo; + } final Resources r = mContext.getResources(); final int iconId = cb.noSim ? R.drawable.ic_qs_no_sim @@ -152,7 +156,7 @@ public class CellularTile extends QSTile<QSTile.SignalState> { boolean isDataTypeIconWide; } - private final SignalCallback mSignalCallback = new SignalCallbackAdapter() { + private final class CellSignalCallback extends SignalCallbackAdapter { private final CallbackInfo mInfo = new CallbackInfo(); @Override public void setWifiIndicators(boolean enabled, IconState statusIcon, IconState qsIcon, diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java index ddde106..7b83e6a 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java @@ -23,10 +23,9 @@ import android.content.Intent; import com.android.internal.logging.MetricsLogger; import com.android.systemui.Prefs; import com.android.systemui.R; -import com.android.systemui.qs.UsageTracker; import com.android.systemui.qs.QSTile; +import com.android.systemui.qs.UsageTracker; import com.android.systemui.statusbar.policy.HotspotController; -import com.android.systemui.statusbar.policy.KeyguardMonitor; /** Quick settings tile: Hotspot **/ public class HotspotTile extends QSTile<QSTile.BooleanState> { @@ -37,14 +36,12 @@ public class HotspotTile extends QSTile<QSTile.BooleanState> { private final HotspotController mController; private final Callback mCallback = new Callback(); private final UsageTracker mUsageTracker; - private final KeyguardMonitor mKeyguard; public HotspotTile(Host host) { super(host); mController = host.getHotspotController(); mUsageTracker = newUsageTracker(host.getContext()); mUsageTracker.setListening(true); - mKeyguard = host.getKeyguardMonitor(); } @Override @@ -97,7 +94,7 @@ public class HotspotTile extends QSTile<QSTile.BooleanState> { if (arg instanceof Boolean) { state.value = (boolean) arg; } else { - mController.isHotspotEnabled(); + state.value = mController.isHotspotEnabled(); } state.icon = state.visible && state.value ? mEnable : mDisable; } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java index f7f7acb..3d0dc7b 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java @@ -45,6 +45,8 @@ public class IntentTile extends QSTile<QSTile.State> { private int mCurrentUserId; private String mIntentPackage; + private Intent mLastIntent; + private IntentTile(Host host, String action) { super(host); mContext.registerReceiver(mReceiver, new IntentFilter(action)); @@ -112,8 +114,16 @@ public class IntentTile extends QSTile<QSTile.State> { @Override protected void handleUpdateState(State state, Object arg) { - if (!(arg instanceof Intent)) return; - final Intent intent = (Intent) arg; + Intent intent = (Intent) arg; + if (intent == null) { + if (mLastIntent == null) { + return; + } + // No intent but need to refresh state, just use the last one. + intent = mLastIntent; + } + // Save the last one in case we need it later. + mLastIntent = intent; state.visible = intent.getBooleanExtra("visible", true); state.contentDescription = intent.getStringExtra("contentDescription"); state.label = intent.getStringExtra("label"); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java index 3bfff2f..e654efd 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java @@ -35,7 +35,6 @@ import com.android.systemui.qs.SignalTileView; import com.android.systemui.statusbar.policy.NetworkController; import com.android.systemui.statusbar.policy.NetworkController.AccessPointController; import com.android.systemui.statusbar.policy.NetworkController.IconState; -import com.android.systemui.statusbar.policy.NetworkController.SignalCallback; import com.android.systemui.statusbar.policy.SignalCallbackAdapter; import java.util.List; @@ -49,6 +48,8 @@ public class WifiTile extends QSTile<QSTile.SignalState> { private final WifiDetailAdapter mDetailAdapter; private final QSTile.SignalState mStateBeforeClick = newTileState(); + private final WifiSignalCallback mSignalCallback = new WifiSignalCallback(); + public WifiTile(Host host) { super(host); mController = host.getNetworkController(); @@ -118,8 +119,10 @@ public class WifiTile extends QSTile<QSTile.SignalState> { protected void handleUpdateState(SignalState state, Object arg) { state.visible = true; if (DEBUG) Log.d(TAG, "handleUpdateState arg=" + arg); - if (arg == null) return; CallbackInfo cb = (CallbackInfo) arg; + if (cb == null) { + cb = mSignalCallback.mInfo; + } boolean wifiConnected = cb.enabled && (cb.wifiSignalIconId > 0) && (cb.enabledDesc != null); boolean wifiNotConnected = (cb.wifiSignalIconId > 0) && (cb.enabledDesc == null); @@ -213,20 +216,21 @@ public class WifiTile extends QSTile<QSTile.SignalState> { } } - private final SignalCallback mSignalCallback = new SignalCallbackAdapter() { + private final class WifiSignalCallback extends SignalCallbackAdapter { + final CallbackInfo mInfo = new CallbackInfo(); + @Override public void setWifiIndicators(boolean enabled, IconState statusIcon, IconState qsIcon, boolean activityIn, boolean activityOut, String description) { if (DEBUG) Log.d(TAG, "onWifiSignalChanged enabled=" + enabled); - final CallbackInfo info = new CallbackInfo(); - info.enabled = enabled; - info.connected = qsIcon.visible; - info.wifiSignalIconId = qsIcon.icon; - info.enabledDesc = description; - info.activityIn = activityIn; - info.activityOut = activityOut; - info.wifiSignalContentDescription = qsIcon.contentDescription; - refreshState(info); + mInfo.enabled = enabled; + mInfo.connected = qsIcon.visible; + mInfo.wifiSignalIconId = qsIcon.icon; + mInfo.enabledDesc = description; + mInfo.activityIn = activityIn; + mInfo.activityOut = activityOut; + mInfo.wifiSignalContentDescription = qsIcon.contentDescription; + refreshState(mInfo); } }; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java index 7cde44c..403af70 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java @@ -656,12 +656,14 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView } private void setContentAlpha(float contentAlpha) { - int layerType = contentAlpha == 0.0f || contentAlpha == 1.0f ? LAYER_TYPE_NONE - : LAYER_TYPE_HARDWARE; View contentView = getContentView(); - int currentLayerType = contentView.getLayerType(); - if (currentLayerType != layerType) { - contentView.setLayerType(layerType, null); + if (contentView.hasOverlappingRendering()) { + int layerType = contentAlpha == 0.0f || contentAlpha == 1.0f ? LAYER_TYPE_NONE + : LAYER_TYPE_HARDWARE; + int currentLayerType = contentView.getLayerType(); + if (currentLayerType != layerType) { + contentView.setLayerType(layerType, null); + } } contentView.setAlpha(contentAlpha); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java index f62dc59..a2e6632 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java @@ -729,11 +729,15 @@ public abstract class BaseStatusBar extends SystemUI implements } protected void setNotificationShown(StatusBarNotification n) { - mNotificationListener.setNotificationsShown(new String[] { n.getKey() }); + setNotificationsShown(new String[]{n.getKey()}); } protected void setNotificationsShown(String[] keys) { - mNotificationListener.setNotificationsShown(keys); + try { + mNotificationListener.setNotificationsShown(keys); + } catch (RuntimeException e) { + Log.d(TAG, "failed setNotificationsShown: ", e); + } } protected boolean isCurrentProfile(int userId) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java index da1f03e..f7c3c67 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java @@ -478,7 +478,6 @@ public class SignalClusterView } private void setTint(ImageView v, int tint) { - v.setImageTintMode(PorterDuff.Mode.SRC_ATOP); v.setImageTintList(ColorStateList.valueOf(tint)); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java index fd459c6..4558288 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java @@ -18,7 +18,6 @@ package com.android.systemui.statusbar.phone; import android.app.ActivityManager; import android.app.ActivityManagerNative; -import android.app.Application; import android.app.admin.DevicePolicyManager; import android.content.BroadcastReceiver; import android.content.ComponentName; @@ -30,8 +29,6 @@ import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.res.Configuration; -import android.graphics.drawable.Drawable; -import android.graphics.drawable.InsetDrawable; import android.os.AsyncTask; import android.os.Bundle; import android.os.IBinder; @@ -262,10 +259,10 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL private Intent getCameraIntent() { KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext); - boolean currentUserHasTrust = updateMonitor.getUserHasTrust( + boolean canSkipBouncer = updateMonitor.getUserCanSkipBouncer( KeyguardUpdateMonitor.getCurrentUser()); boolean secure = mLockPatternUtils.isSecure(KeyguardUpdateMonitor.getCurrentUser()); - return (secure && !currentUserHasTrust) ? SECURE_CAMERA_INTENT : INSECURE_CAMERA_INTENT; + return (secure && !canSkipBouncer) ? SECURE_CAMERA_INTENT : INSECURE_CAMERA_INTENT; } private void updateCameraVisibility() { @@ -652,7 +649,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL } @Override - public void onFingerprintAuthenticated(int userId) { + public void onFingerprintAuthenticated(int userId, boolean wakeAndUnlocking) { } @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java index a7afec4..e9b2c61 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java @@ -29,6 +29,7 @@ import com.android.keyguard.KeyguardHostView; import com.android.keyguard.KeyguardSecurityView; import com.android.keyguard.R; import com.android.keyguard.ViewMediatorCallback; +import com.android.systemui.DejankUtils; import static com.android.keyguard.KeyguardHostView.OnDismissAction; import static com.android.keyguard.KeyguardSecurityModel.SecurityMode; @@ -46,7 +47,6 @@ public class KeyguardBouncer { private KeyguardHostView mKeyguardView; private ViewGroup mRoot; private boolean mShowingSoon; - private Choreographer mChoreographer = Choreographer.getInstance(); private int mBouncerPromptReason; public KeyguardBouncer(Context context, ViewMediatorCallback callback, @@ -70,16 +70,13 @@ public class KeyguardBouncer { return; } - mBouncerPromptReason = mCallback.getBouncerPromptReason(); - // Try to dismiss the Keyguard. If no security pattern is set, this will dismiss the whole // Keyguard. If we need to authenticate, show the bouncer. if (!mKeyguardView.dismiss()) { mShowingSoon = true; // Split up the work over multiple frames. - mChoreographer.postCallbackDelayed(Choreographer.CALLBACK_ANIMATION, mShowRunnable, - null, 16); + DejankUtils.postAfterTraversal(mShowRunnable); } } @@ -107,7 +104,7 @@ public class KeyguardBouncer { } private void cancelShowRunnable() { - mChoreographer.removeCallbacks(Choreographer.CALLBACK_ANIMATION, mShowRunnable, null); + DejankUtils.removeCallbacks(mShowRunnable); mShowingSoon = false; } @@ -165,6 +162,7 @@ public class KeyguardBouncer { if (wasInitialized) { mKeyguardView.showPrimarySecurityScreen(); } + mBouncerPromptReason = mCallback.getBouncerPromptReason(); } private void ensureView() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java index 6bcb766..9e2ce15 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java @@ -214,7 +214,7 @@ public class LockIcon extends KeyguardAffordanceView { } else if (oldState == STATE_FINGERPRINT_ERROR && newState == STATE_FINGERPRINT) { return R.drawable.lockscreen_fingerprint_error_state_to_fp_animation; } else if (oldState == STATE_FINGERPRINT && newState == STATE_LOCK_OPEN - && !mUnlockMethodCache.isCurrentlyInsecure()) { + && !mUnlockMethodCache.isTrusted()) { return R.drawable.lockscreen_fingerprint_draw_off_animation; } else if (newState == STATE_FINGERPRINT && !oldScreenOn && screenOn) { return R.drawable.lockscreen_fingerprint_draw_on_animation; @@ -226,7 +226,7 @@ public class LockIcon extends KeyguardAffordanceView { private int getState() { boolean fingerprintRunning = KeyguardUpdateMonitor.getInstance(mContext).isFingerprintDetectionRunning(); - if (mUnlockMethodCache.isCurrentlyInsecure()) { + if (mUnlockMethodCache.canSkipBouncer()) { return STATE_LOCK_OPEN; } else if (mTransientFpError) { return STATE_FINGERPRINT_ERROR; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java index f40f501..416fb36 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java @@ -40,6 +40,7 @@ import android.view.MotionEvent; import android.view.Surface; import android.view.View; import android.view.ViewGroup; +import android.view.ViewRootImpl; import android.view.WindowManager; import android.view.inputmethod.InputMethodManager; import android.widget.FrameLayout; @@ -184,6 +185,15 @@ public class NavigationBarView extends LinearLayout { mBarTransitions = new NavigationBarTransitions(this); } + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + ViewRootImpl root = getViewRootImpl(); + if (root != null) { + root.setDrawDuringWindowsAnimating(true); + } + } + public BarTransitions getBarTransitions() { return mBarTransitions; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java index 094b9b5..03bdf97 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java @@ -773,14 +773,7 @@ public class NotificationPanelView extends PanelView implements && mQsExpansionEnabled) { mTwoFingerQsExpandPossible = true; } - final int pointerCount = event.getPointerCount(); - final boolean twoFingerDrag = action == MotionEvent.ACTION_POINTER_DOWN - && pointerCount == 2; - final boolean stylusClickDrag = action == MotionEvent.ACTION_DOWN - && pointerCount == 1 && event.getToolType(0) == MotionEvent.TOOL_TYPE_STYLUS - && (event.isButtonPressed(MotionEvent.BUTTON_SECONDARY) - || event.isButtonPressed(MotionEvent.BUTTON_TERTIARY)); - if (mTwoFingerQsExpandPossible && (twoFingerDrag || stylusClickDrag) + if (mTwoFingerQsExpandPossible && isOpenQsEvent(event) && event.getY(event.getActionIndex()) < mStatusBarMinHeight) { MetricsLogger.count(mContext, COUNTER_PANEL_OPEN_QS, 1); mQsExpandImmediate = true; @@ -799,6 +792,24 @@ public class NotificationPanelView extends PanelView implements || y <= mQsContainer.getY() + mQsContainer.getHeight()); } + private boolean isOpenQsEvent(MotionEvent event) { + final int pointerCount = event.getPointerCount(); + final int action = event.getActionMasked(); + + final boolean twoFingerDrag = action == MotionEvent.ACTION_POINTER_DOWN + && pointerCount == 2; + + final boolean stylusButtonClickDrag = action == MotionEvent.ACTION_DOWN + && (event.isButtonPressed(MotionEvent.BUTTON_STYLUS_PRIMARY) + || event.isButtonPressed(MotionEvent.BUTTON_STYLUS_SECONDARY)); + + final boolean mouseButtonClickDrag = action == MotionEvent.ACTION_DOWN + && (event.isButtonPressed(MotionEvent.BUTTON_SECONDARY) + || event.isButtonPressed(MotionEvent.BUTTON_TERTIARY)); + + return twoFingerDrag || stylusButtonClickDrag || mouseButtonClickDrag; + } + private void handleQsDown(MotionEvent event) { if (event.getActionMasked() == MotionEvent.ACTION_DOWN && shouldQuickSettingsIntercept(event.getX(), event.getY(), -1)) { @@ -954,6 +965,7 @@ public class NotificationPanelView extends PanelView implements private void onQsExpansionStarted(int overscrollAmount) { cancelQsAnimation(); cancelHeightAnimator(); + notifyExpandingFinished(); // Reset scroll position and apply that position to the expanded height. float height = mQsExpansionHeight - mScrollView.getScrollY() - overscrollAmount; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java index 889160d..0d20d52 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java @@ -111,7 +111,7 @@ public abstract class PanelView extends FrameLayout { */ private float mNextCollapseSpeedUpFactor = 1.0f; - private boolean mExpanding; + protected boolean mExpanding; private boolean mGestureWaitForTouchSlop; private boolean mIgnoreXTouchSlop; private Runnable mPeekRunnable = new Runnable() { @@ -137,7 +137,7 @@ public abstract class PanelView extends FrameLayout { } } - private void notifyExpandingFinished() { + protected final void notifyExpandingFinished() { if (mExpanding) { mExpanding = false; onExpandingFinished(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index 4619abf..a67e77a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -198,6 +198,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, public static final boolean SHOW_LOCKSCREEN_MEDIA_ARTWORK = true; + public static final String ACTION_FAKE_ARTWORK = "fake_artwork"; + private static final int MSG_OPEN_NOTIFICATION_PANEL = 1000; private static final int MSG_CLOSE_PANELS = 1001; private static final int MSG_OPEN_SETTINGS_PANEL = 1002; @@ -437,6 +439,12 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, public void onPlaybackStateChanged(PlaybackState state) { super.onPlaybackStateChanged(state); if (DEBUG_MEDIA) Log.v(TAG, "DEBUG_MEDIA: onPlaybackStateChanged: " + state); + if (state != null) { + if (!isPlaybackActive(state.getState())) { + clearCurrentMediaNotification(); + updateMediaMetaData(true); + } + } } @Override @@ -894,11 +902,15 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); filter.addAction(Intent.ACTION_SCREEN_OFF); filter.addAction(Intent.ACTION_SCREEN_ON); + context.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null, null); + + IntentFilter demoFilter = new IntentFilter(); if (DEBUG_MEDIA_FAKE_ARTWORK) { - filter.addAction("fake_artwork"); + demoFilter.addAction(ACTION_FAKE_ARTWORK); } - filter.addAction(ACTION_DEMO); - context.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null, null); + demoFilter.addAction(ACTION_DEMO); + context.registerReceiverAsUser(mDemoReceiver, UserHandle.ALL, demoFilter, + android.Manifest.permission.DUMP, null); // listen for USER_SETUP_COMPLETE setting (per-user) resetUserSetupObserver(); @@ -1197,6 +1209,10 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, if (mHeadsUpManager.isHeadsUp(key)) { deferRemoval = !mHeadsUpManager.removeNotification(key); } + if (key.equals(mMediaNotificationKey)) { + clearCurrentMediaNotification(); + updateMediaMetaData(true); + } if (deferRemoval) { mLatestRankingMap = ranking; mHeadsUpEntriesToRemoveOnSwitch.add(mHeadsUpManager.getEntry(key)); @@ -1490,23 +1506,31 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, synchronized (mNotificationData) { ArrayList<Entry> activeNotifications = mNotificationData.getActiveNotifications(); final int N = activeNotifications.size(); + + // Promote the media notification with a controller in 'playing' state, if any. Entry mediaNotification = null; MediaController controller = null; for (int i = 0; i < N; i++) { final Entry entry = activeNotifications.get(i); if (isMediaNotification(entry)) { - final MediaSession.Token token = entry.notification.getNotification().extras + final MediaSession.Token token = + entry.notification.getNotification().extras .getParcelable(Notification.EXTRA_MEDIA_SESSION); if (token != null) { - controller = new MediaController(mContext, token); - if (controller != null) { - // we've got a live one, here + MediaController aController = new MediaController(mContext, token); + if (PlaybackState.STATE_PLAYING == + getMediaControllerPlaybackState(aController)) { + if (DEBUG_MEDIA) { + Log.v(TAG, "DEBUG_MEDIA: found mediastyle controller matching " + + entry.notification.getKey()); + } mediaNotification = entry; + controller = aController; + break; } } } } - if (mediaNotification == null) { // Still nothing? OK, let's just look for live media sessions and see if they match // one of our notifications. This will catch apps that aren't (yet!) using media @@ -1519,83 +1543,88 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, UserHandle.USER_ALL); for (MediaController aController : sessions) { - if (aController == null) continue; - final PlaybackState state = aController.getPlaybackState(); - if (state == null) continue; - switch (state.getState()) { - case PlaybackState.STATE_STOPPED: - case PlaybackState.STATE_ERROR: - continue; - default: - // now to see if we have one like this - final String pkg = aController.getPackageName(); - - for (int i = 0; i < N; i++) { - final Entry entry = activeNotifications.get(i); - if (entry.notification.getPackageName().equals(pkg)) { - if (DEBUG_MEDIA) { - Log.v(TAG, "DEBUG_MEDIA: found controller matching " - + entry.notification.getKey()); - } - controller = aController; - mediaNotification = entry; - break; + if (PlaybackState.STATE_PLAYING == + getMediaControllerPlaybackState(aController)) { + // now to see if we have one like this + final String pkg = aController.getPackageName(); + + for (int i = 0; i < N; i++) { + final Entry entry = activeNotifications.get(i); + if (entry.notification.getPackageName().equals(pkg)) { + if (DEBUG_MEDIA) { + Log.v(TAG, "DEBUG_MEDIA: found controller matching " + + entry.notification.getKey()); } + controller = aController; + mediaNotification = entry; + break; } + } } } } } - if (!sameSessions(mMediaController, controller)) { + if (controller != null && !sameSessions(mMediaController, controller)) { // We have a new media session - - if (mMediaController != null) { - // something old was playing - Log.v(TAG, "DEBUG_MEDIA: Disconnecting from old controller: " - + mMediaController); - mMediaController.unregisterCallback(mMediaListener); - } + clearCurrentMediaNotification(); mMediaController = controller; + mMediaController.registerCallback(mMediaListener); + mMediaMetadata = mMediaController.getMetadata(); + if (DEBUG_MEDIA) { + Log.v(TAG, "DEBUG_MEDIA: insert listener, receive metadata: " + + mMediaMetadata); + } - if (mMediaController != null) { - mMediaController.registerCallback(mMediaListener); - mMediaMetadata = mMediaController.getMetadata(); + if (mediaNotification != null) { + mMediaNotificationKey = mediaNotification.notification.getKey(); if (DEBUG_MEDIA) { - Log.v(TAG, "DEBUG_MEDIA: insert listener, receive metadata: " - + mMediaMetadata); + Log.v(TAG, "DEBUG_MEDIA: Found new media notification: key=" + + mMediaNotificationKey + " controller=" + mMediaController); } - - final String notificationKey = mediaNotification == null - ? null - : mediaNotification.notification.getKey(); - - if (notificationKey == null || !notificationKey.equals(mMediaNotificationKey)) { - // we have a new notification! - if (DEBUG_MEDIA) { - Log.v(TAG, "DEBUG_MEDIA: Found new media notification: key=" - + notificationKey + " controller=" + controller); - } - mMediaNotificationKey = notificationKey; - } - } else { - mMediaMetadata = null; - mMediaNotificationKey = null; } - metaDataChanged = true; - } else { - // Media session unchanged - - if (DEBUG_MEDIA) { - Log.v(TAG, "DEBUG_MEDIA: Continuing media notification: key=" + mMediaNotificationKey); - } } } + if (metaDataChanged) { + updateNotifications(); + } updateMediaMetaData(metaDataChanged); } + private int getMediaControllerPlaybackState(MediaController controller) { + if (controller != null) { + final PlaybackState playbackState = controller.getPlaybackState(); + if (playbackState != null) { + return playbackState.getState(); + } + } + return PlaybackState.STATE_NONE; + } + + private boolean isPlaybackActive(int state) { + if (state != PlaybackState.STATE_STOPPED + && state != PlaybackState.STATE_ERROR + && state != PlaybackState.STATE_NONE) { + return true; + } + return false; + } + + private void clearCurrentMediaNotification() { + mMediaNotificationKey = null; + mMediaMetadata = null; + if (mMediaController != null) { + if (DEBUG_MEDIA) { + Log.v(TAG, "DEBUG_MEDIA: Disconnecting from old controller: " + + mMediaController.getPackageName()); + } + mMediaController.unregisterCallback(mMediaListener); + } + mMediaController = null; + } + private boolean sameSessions(MediaController a, MediaController b) { if (a == b) return true; if (a == null) return false; @@ -1734,7 +1763,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } private int adjustDisableFlags(int state) { - if (!mLaunchTransitionFadingAway + if (!mLaunchTransitionFadingAway && !mKeyguardFadingAway && (mExpandedVisible || mBouncerShowing || mWaitingForKeyguardExit)) { state |= StatusBarManager.DISABLE_NOTIFICATION_ICONS; state |= StatusBarManager.DISABLE_SYSTEM_INFO; @@ -2005,7 +2034,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } public boolean isKeyguardCurrentlySecure() { - return !mUnlockMethodCache.isCurrentlyInsecure(); + return !mUnlockMethodCache.canSkipBouncer(); } public void setPanelExpanded(boolean isExpanded) { @@ -2074,7 +2103,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, // Expand the window to encompass the full screen in anticipation of the drag. // This is only possible to do atomically because the status bar is at the top of the screen! mStatusBarWindowManager.setPanelVisible(true); - mStatusBarView.setFocusable(false); visibilityChanged(true); mWaitingForKeyguardExit = false; @@ -2206,7 +2234,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, // Shrink the window to the size of the status bar only mStatusBarWindowManager.setPanelVisible(false); mStatusBarWindowManager.setForceStatusBarVisible(false); - mStatusBarView.setFocusable(true); // Close any "App info" popups that might have snuck on-screen dismissPopups(); @@ -2683,6 +2710,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, if (mBluetoothController != null) { mBluetoothController.dump(fd, pw, args); } + if (mHotspotController != null) { + mHotspotController.dump(fd, pw, args); + } if (mCastController != null) { mCastController.dump(fd, pw, args); } @@ -2855,7 +2885,14 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, mScreenOn = true; notifyNavigationBarScreenOn(true); } - else if (ACTION_DEMO.equals(action)) { + } + }; + + private BroadcastReceiver mDemoReceiver = new BroadcastReceiver() { + public void onReceive(Context context, Intent intent) { + if (DEBUG) Log.v(TAG, "onReceive: " + intent); + String action = intent.getAction(); + if (ACTION_DEMO.equals(action)) { Bundle bundle = intent.getExtras(); if (bundle != null) { String command = bundle.getString("command", "").trim().toLowerCase(); @@ -2867,7 +2904,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } } } - } else if ("fake_artwork".equals(action)) { + } else if (ACTION_FAKE_ARTWORK.equals(action)) { if (DEBUG_MEDIA_FAKE_ARTWORK) { updateMediaMetaData(true); } @@ -2916,7 +2953,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, updateRowStates(); mIconController.updateResources(); mScreenPinningRequest.onConfigurationChanged(); - mNetworkController.handleConfigurationChanged(); + mNetworkController.onConfigurationChanged(); } @Override @@ -3055,20 +3092,20 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, boolean isOccluded = mStatusBarKeyguardViewManager.isOccluded(); boolean isBouncerShowing = mStatusBarKeyguardViewManager.isBouncerShowing(); boolean isSecure = mUnlockMethodCache.isMethodSecure(); - boolean isCurrentlyInsecure = mUnlockMethodCache.isCurrentlyInsecure(); + boolean canSkipBouncer = mUnlockMethodCache.canSkipBouncer(); int stateFingerprint = getLoggingFingerprint(mState, isShowing, isOccluded, isBouncerShowing, isSecure, - isCurrentlyInsecure); + canSkipBouncer); if (stateFingerprint != mLastLoggedStateFingerprint) { EventLogTags.writeSysuiStatusBarState(mState, isShowing ? 1 : 0, isOccluded ? 1 : 0, isBouncerShowing ? 1 : 0, isSecure ? 1 : 0, - isCurrentlyInsecure ? 1 : 0); + canSkipBouncer ? 1 : 0); mLastLoggedStateFingerprint = stateFingerprint; } } @@ -3191,6 +3228,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, mHandlerThread = null; } mContext.unregisterReceiver(mBroadcastReceiver); + mContext.unregisterReceiver(mDemoReceiver); mAssistManager.destroy(); final SignalClusterView signalCluster = @@ -3214,7 +3252,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, public void dispatchDemoCommand(String command, Bundle args) { if (!mDemoModeAllowed) { mDemoModeAllowed = Settings.Global.getInt(mContext.getContentResolver(), - "sysui_demo_allowed", 0) != 0; + DEMO_MODE_ALLOWED, 0) != 0; } if (!mDemoModeAllowed) return; if (command.equals(COMMAND_ENTER)) { @@ -3314,6 +3352,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, mDraggedDownRow.notifyHeightChanged(false /* needsAnimation */); mDraggedDownRow = null; } + mAssistManager.onLockscreenShown(); } private void onLaunchTransitionFadingEnded() { @@ -3463,7 +3502,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, startTime + fadeoutDuration - StatusBarIconController.DEFAULT_TINT_ANIMATION_DURATION, StatusBarIconController.DEFAULT_TINT_ANIMATION_DURATION); - disable(mDisabledUnmodified1, mDisabledUnmodified2, true /* animate */); + disable(mDisabledUnmodified1, mDisabledUnmodified2, fadeoutDuration > 0 /* animate */); } public boolean isKeyguardFadingAway() { @@ -3672,7 +3711,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, public void onTrackingStopped(boolean expand) { if (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED) { - if (!expand && !mUnlockMethodCache.isCurrentlyInsecure()) { + if (!expand && !mUnlockMethodCache.canSkipBouncer()) { showBouncer(); } } 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 6d04b28..c0887ca 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java @@ -24,6 +24,7 @@ import android.view.MotionEvent; import android.view.View; import android.view.accessibility.AccessibilityEvent; +import com.android.systemui.DejankUtils; import com.android.systemui.EventLogTags; import com.android.systemui.R; @@ -117,12 +118,12 @@ public class PhoneStatusBarView extends PanelBar { public void onAllPanelsCollapsed() { super.onAllPanelsCollapsed(); // Close the status bar in the next frame so we can show the end of the animation. - postOnAnimation(mHideExpandedRunnable); + DejankUtils.postAfterTraversal(mHideExpandedRunnable); mLastFullyOpenedPanel = null; } public void removePendingHideExpandedRunnables() { - removeCallbacks(mHideExpandedRunnable); + DejankUtils.removeCallbacks(mHideExpandedRunnable); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java index bacf890..6816399 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java @@ -105,7 +105,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, public void onTrackingStarted() { mExpanding = true; - mDarkenWhileDragging = !mUnlockMethodCache.isCurrentlyInsecure(); + mDarkenWhileDragging = !mUnlockMethodCache.canSkipBouncer(); } public void onExpandingFinished() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsButton.java new file mode 100644 index 0000000..a1e9ece --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsButton.java @@ -0,0 +1,174 @@ +/* + * Copyright (C) 2015 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. + */ +package com.android.systemui.statusbar.phone; + +import android.animation.Animator; +import android.animation.Animator.AnimatorListener; +import android.animation.ObjectAnimator; +import android.content.Context; +import android.os.Handler; +import android.os.Message; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewConfiguration; +import android.view.animation.Animation; +import android.view.animation.AnimationUtils; + +import com.android.keyguard.AlphaOptimizedImageButton; + +public class SettingsButton extends AlphaOptimizedImageButton { + + private static final long LONG_PRESS_LENGTH = 1000; + private static final long ACCEL_LENGTH = 750; + private static final long FULL_SPEED_LENGTH = 375; + private static final long RUN_DURATION = 350; + + private boolean mUpToSpeed; + private ObjectAnimator mAnimator; + + private float mSlop; + + public SettingsButton(Context context, AttributeSet attrs) { + super(context, attrs); + mSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop(); + } + + public boolean isAnimating() { + return mAnimator != null && mAnimator.isRunning(); + } + + public boolean isTunerClick() { + return mUpToSpeed; + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + switch (event.getActionMasked()) { + case MotionEvent.ACTION_DOWN: + postDelayed(mLongPressCallback, LONG_PRESS_LENGTH); + break; + case MotionEvent.ACTION_UP: + if (mUpToSpeed) { + startExitAnimation(); + } else { + cancelLongClick(); + } + break; + case MotionEvent.ACTION_CANCEL: + cancelLongClick(); + break; + case MotionEvent.ACTION_MOVE: + float x = event.getX(); + float y = event.getY(); + if ((x < -mSlop) || (y < -mSlop) || (x > getWidth() + mSlop) + || (y > getHeight() + mSlop)) { + cancelLongClick(); + } + break; + } + return super.onTouchEvent(event); + } + + private void cancelLongClick() { + cancelAnimation(); + mUpToSpeed = false; + removeCallbacks(mLongPressCallback); + } + + private void cancelAnimation() { + if (mAnimator != null) { + mAnimator.removeAllListeners(); + mAnimator.cancel(); + mAnimator = null; + } + } + + private void startExitAnimation() { + animate() + .translationX(((View) getParent().getParent()).getWidth() - getX()) + .alpha(0) + .setDuration(RUN_DURATION) + .setInterpolator(AnimationUtils.loadInterpolator(mContext, + android.R.interpolator.accelerate_cubic)) + .setListener(new AnimatorListener() { + @Override + public void onAnimationStart(Animator animation) { + } + + @Override + public void onAnimationRepeat(Animator animation) { + } + + @Override + public void onAnimationEnd(Animator animation) { + setAlpha(1f); + setTranslationX(0); + cancelLongClick(); + } + + @Override + public void onAnimationCancel(Animator animation) { + } + }) + .start(); + } + + protected void startAccelSpin() { + cancelAnimation(); + mAnimator = ObjectAnimator.ofFloat(this, View.ROTATION, 0, 360); + mAnimator.setInterpolator(AnimationUtils.loadInterpolator(mContext, + android.R.interpolator.accelerate_quad)); + mAnimator.setDuration(ACCEL_LENGTH); + mAnimator.addListener(new AnimatorListener() { + @Override + public void onAnimationStart(Animator animation) { + } + + @Override + public void onAnimationRepeat(Animator animation) { + } + + @Override + public void onAnimationEnd(Animator animation) { + startContinuousSpin(); + } + + @Override + public void onAnimationCancel(Animator animation) { + } + }); + mAnimator.start(); + } + + protected void startContinuousSpin() { + cancelAnimation(); + mUpToSpeed = true; + mAnimator = ObjectAnimator.ofFloat(this, View.ROTATION, 0, 360); + mAnimator.setInterpolator(AnimationUtils.loadInterpolator(mContext, + android.R.interpolator.linear)); + mAnimator.setDuration(FULL_SPEED_LENGTH); + mAnimator.setRepeatCount(Animation.INFINITE); + mAnimator.start(); + } + + private final Runnable mLongPressCallback = new Runnable() { + @Override + public void run() { + startAccelSpin(); + } + }; +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java index a81f06e..5d58cd0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java @@ -37,6 +37,7 @@ import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.widget.Switch; import android.widget.TextView; +import android.widget.Toast; import com.android.keyguard.KeyguardStatusView; import com.android.systemui.BatteryMeterView; @@ -48,6 +49,7 @@ import com.android.systemui.statusbar.policy.BatteryController; import com.android.systemui.statusbar.policy.NetworkControllerImpl.EmergencyListener; import com.android.systemui.statusbar.policy.NextAlarmController; import com.android.systemui.statusbar.policy.UserInfoController; +import com.android.systemui.tuner.TunerService; import java.text.NumberFormat; @@ -73,7 +75,8 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL private TextView mDateExpanded; private LinearLayout mSystemIcons; private View mSignalCluster; - private View mSettingsButton; + private SettingsButton mSettingsButton; + private View mSettingsContainer; private View mQsDetailHeader; private TextView mQsDetailHeaderTitle; private Switch mQsDetailHeaderSwitch; @@ -142,7 +145,8 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL mMultiUserAvatar = (ImageView) findViewById(R.id.multi_user_avatar); mDateCollapsed = (TextView) findViewById(R.id.date_collapsed); mDateExpanded = (TextView) findViewById(R.id.date_expanded); - mSettingsButton = findViewById(R.id.settings_button); + mSettingsButton = (SettingsButton) findViewById(R.id.settings_button); + mSettingsContainer = findViewById(R.id.settings_button_container); mSettingsButton.setOnClickListener(this); mQsDetailHeader = findViewById(R.id.qs_detail_header); mQsDetailHeader.setAlpha(0); @@ -323,13 +327,15 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL mDateCollapsed.setVisibility(mExpanded && mAlarmShowing ? View.VISIBLE : View.INVISIBLE); mDateExpanded.setVisibility(mExpanded && mAlarmShowing ? View.INVISIBLE : View.VISIBLE); mAlarmStatus.setVisibility(mExpanded && mAlarmShowing ? View.VISIBLE : View.INVISIBLE); - mSettingsButton.setVisibility(mExpanded ? View.VISIBLE : View.INVISIBLE); + mSettingsContainer.setVisibility(mExpanded ? View.VISIBLE : View.INVISIBLE); mQsDetailHeader.setVisibility(mExpanded && mShowingDetail? View.VISIBLE : View.INVISIBLE); if (mSignalCluster != null) { updateSignalClusterDetachment(); } mEmergencyCallsOnly.setVisibility(mExpanded && mShowEmergencyCallsOnly ? VISIBLE : GONE); mBatteryLevel.setVisibility(mExpanded ? View.VISIBLE : View.GONE); + mSettingsContainer.findViewById(R.id.tuner_icon).setVisibility( + TunerService.isTunerEnabled(mContext) ? View.VISIBLE : View.INVISIBLE); } private void updateSignalClusterDetachment() { @@ -352,7 +358,7 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL private void updateSystemIconsLayoutParams() { RelativeLayout.LayoutParams lp = (LayoutParams) mSystemIconsSuperContainer.getLayoutParams(); int rule = mExpanded - ? mSettingsButton.getId() + ? mSettingsContainer.getId() : mMultiUserSwitch.getId(); if (rule != lp.getRules()[RelativeLayout.START_OF]) { lp.addRule(RelativeLayout.START_OF, rule); @@ -495,6 +501,20 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL @Override public void onClick(View v) { if (v == mSettingsButton) { + if (mSettingsButton.isTunerClick()) { + if (TunerService.isTunerEnabled(mContext)) { + TunerService.showResetRequest(mContext, new Runnable() { + @Override + public void run() { + // Relaunch settings so that the tuner disappears. + startSettingsActivity(); + } + }); + } else { + Toast.makeText(getContext(), R.string.tuner_toast, Toast.LENGTH_LONG).show(); + TunerService.setTunerEnabled(mContext, true); + } + } startSettingsActivity(); } else if (v == mSystemIconsSuperContainer) { startBatteryActivity(); @@ -567,10 +587,10 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL } target.batteryY = mSystemIconsSuperContainer.getTop() + mSystemIconsContainer.getTop(); target.batteryLevelAlpha = getAlphaForVisibility(mBatteryLevel); - target.settingsAlpha = getAlphaForVisibility(mSettingsButton); + target.settingsAlpha = getAlphaForVisibility(mSettingsContainer); target.settingsTranslation = mExpanded ? 0 - : mMultiUserSwitch.getLeft() - mSettingsButton.getLeft(); + : mMultiUserSwitch.getLeft() - mSettingsContainer.getLeft(); target.signalClusterAlpha = mSignalClusterDetached ? 0f : 1f; target.settingsRotation = !mExpanded ? 90f : 0f; } @@ -622,9 +642,11 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL mSignalCluster.setTranslationX(0f); mSignalCluster.setTranslationY(0f); } - mSettingsButton.setTranslationY(mSystemIconsSuperContainer.getTranslationY()); - mSettingsButton.setTranslationX(values.settingsTranslation); - mSettingsButton.setRotation(values.settingsRotation); + if (!mSettingsButton.isAnimating()) { + mSettingsContainer.setTranslationY(mSystemIconsSuperContainer.getTranslationY()); + mSettingsContainer.setTranslationX(values.settingsTranslation); + mSettingsButton.setRotation(values.settingsRotation); + } applyAlpha(mEmergencyCallsOnly, values.emergencyCallsOnlyAlpha); if (!mShowingDetail && !mDetailTransitioning) { // Otherwise it needs to stay invisible @@ -633,7 +655,7 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL applyAlpha(mDateCollapsed, values.dateCollapsedAlpha); applyAlpha(mDateExpanded, values.dateExpandedAlpha); applyAlpha(mBatteryLevel, values.batteryLevelAlpha); - applyAlpha(mSettingsButton, values.settingsAlpha); + applyAlpha(mSettingsContainer, values.settingsAlpha); applyAlpha(mSignalCluster, values.signalClusterAlpha); if (!mExpanded) { mTime.setScaleX(1f); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java index a69416a..e622144 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java @@ -19,15 +19,12 @@ package com.android.systemui.statusbar.phone; import android.content.ComponentCallbacks2; import android.content.Context; import android.os.Bundle; -import android.os.RemoteException; import android.os.SystemClock; -import android.util.Slog; import android.view.KeyEvent; import android.view.View; import android.view.ViewGroup; import android.view.WindowManagerGlobal; -import com.android.internal.policy.IKeyguardShowCallback; import com.android.internal.widget.LockPatternUtils; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.ViewMediatorCallback; @@ -163,26 +160,10 @@ public class StatusBarKeyguardViewManager { mBouncer.onScreenTurnedOff(); } - public void onScreenTurnedOn(final IKeyguardShowCallback callback) { + public void onScreenTurnedOn() { mScreenOn = true; mScreenWillWakeUp = false; mPhoneStatusBar.onScreenTurnedOn(); - if (callback != null) { - callbackAfterDraw(callback); - } - } - - private void callbackAfterDraw(final IKeyguardShowCallback callback) { - mContainer.post(new Runnable() { - @Override - public void run() { - try { - callback.onShown(mContainer.getWindowToken()); - } catch (RemoteException e) { - Slog.w(TAG, "Exception calling onShown():", e); - } - } - }); } public void notifyScreenWakeUpRequested() { @@ -270,16 +251,22 @@ public class StatusBarKeyguardViewManager { mPhoneStatusBar.setKeyguardFadingAway(startTime, delay, fadeoutDuration); boolean staying = mPhoneStatusBar.hideKeyguard(); if (!staying) { - mStatusBarWindowManager.setKeyguardFadingAway(true); - mScrimController.animateKeyguardFadingOut(delay, fadeoutDuration, new Runnable() { - @Override - public void run() { - mStatusBarWindowManager.setKeyguardFadingAway(false); - mPhoneStatusBar.finishKeyguardFadingAway(); - WindowManagerGlobal.getInstance().trimMemory( - ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN); - } - }); + if (fadeoutDuration == 0) { + mPhoneStatusBar.finishKeyguardFadingAway(); + WindowManagerGlobal.getInstance().trimMemory( + ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN); + } else { + mStatusBarWindowManager.setKeyguardFadingAway(true); + mScrimController.animateKeyguardFadingOut(delay, fadeoutDuration, new Runnable() { + @Override + public void run() { + mStatusBarWindowManager.setKeyguardFadingAway(false); + mPhoneStatusBar.finishKeyguardFadingAway(); + WindowManagerGlobal.getInstance().trimMemory( + ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN); + } + }); + } } else { mScrimController.animateGoingToFullShade(delay, fadeoutDuration); mPhoneStatusBar.finishKeyguardFadingAway(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java index 66d71f6..f31311d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java @@ -39,9 +39,10 @@ public class UnlockMethodCache { /** Whether the user configured a secure unlock method (PIN, password, etc.) */ private boolean mSecure; /** Whether the unlock method is currently insecure (insecure method or trusted environment) */ - private boolean mCurrentlyInsecure; + private boolean mCanSkipBouncer; private boolean mTrustManaged; private boolean mFaceUnlockRunning; + private boolean mTrusted; private UnlockMethodCache(Context ctx) { mLockPatternUtils = new LockPatternUtils(ctx); @@ -64,11 +65,15 @@ public class UnlockMethodCache { return mSecure; } + public boolean isTrusted() { + return mTrusted; + } + /** - * @return whether the lockscreen is currently insecure, i. e. the bouncer won't be shown + * @return whether the lockscreen is currently insecure, and the bouncer won't be shown */ - public boolean isCurrentlyInsecure() { - return mCurrentlyInsecure; + public boolean canSkipBouncer() { + return mCanSkipBouncer; } public void addListener(OnUnlockMethodChangedListener listener) { @@ -82,15 +87,17 @@ public class UnlockMethodCache { private void update(boolean updateAlways) { int user = KeyguardUpdateMonitor.getCurrentUser(); boolean secure = mLockPatternUtils.isSecure(user); - boolean currentlyInsecure = !secure || mKeyguardUpdateMonitor.getUserHasTrust(user); + boolean canSkipBouncer = !secure || mKeyguardUpdateMonitor.getUserCanSkipBouncer(user); boolean trustManaged = mKeyguardUpdateMonitor.getUserTrustIsManaged(user); + boolean trusted = mKeyguardUpdateMonitor.getUserHasTrust(user); boolean faceUnlockRunning = mKeyguardUpdateMonitor.isFaceUnlockRunning(user) && trustManaged; - boolean changed = secure != mSecure || currentlyInsecure != mCurrentlyInsecure || + boolean changed = secure != mSecure || canSkipBouncer != mCanSkipBouncer || trustManaged != mTrustManaged || faceUnlockRunning != mFaceUnlockRunning; if (changed || updateAlways) { mSecure = secure; - mCurrentlyInsecure = currentlyInsecure; + mCanSkipBouncer = canSkipBouncer; + mTrusted = trusted; mTrustManaged = trustManaged; mFaceUnlockRunning = faceUnlockRunning; notifyListeners(); @@ -125,7 +132,7 @@ public class UnlockMethodCache { } @Override - public void onFingerprintAuthenticated(int userId) { + public void onFingerprintAuthenticated(int userId, boolean wakeAndUnlocking) { update(false /* updateAlways */); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java index 04c626b..61986ad 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java @@ -232,7 +232,13 @@ public class Clock extends TextView implements DemoMode { } else if (hhmm != null && hhmm.length() == 4) { int hh = Integer.parseInt(hhmm.substring(0, 2)); int mm = Integer.parseInt(hhmm.substring(2)); - mCalendar.set(Calendar.HOUR, hh); + boolean is24 = DateFormat.is24HourFormat( + getContext(), ActivityManager.getCurrentUser()); + if (is24) { + mCalendar.set(Calendar.HOUR_OF_DAY, hh); + } else { + mCalendar.set(Calendar.HOUR, hh); + } mCalendar.set(Calendar.MINUTE, mm); } setText(getSmallTime()); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java index 1e3bc4d..41aeac9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java @@ -17,7 +17,6 @@ package com.android.systemui.statusbar.policy; import android.content.BroadcastReceiver; -import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; @@ -27,6 +26,8 @@ import android.util.Log; import com.android.settingslib.TetherUtil; +import java.io.FileDescriptor; +import java.io.PrintWriter; import java.util.ArrayList; public class HotspotControllerImpl implements HotspotController { @@ -43,11 +44,32 @@ public class HotspotControllerImpl implements HotspotController { private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>(); private final Receiver mReceiver = new Receiver(); private final Context mContext; - private final WifiManager mWifiManager; + + private int mHotspotState; public HotspotControllerImpl(Context context) { mContext = context; - mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); + } + + public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + pw.println("HotspotController state:"); + pw.print(" mHotspotEnabled="); pw.println(stateToString(mHotspotState)); + } + + private static String stateToString(int hotspotState) { + switch (hotspotState) { + case WifiManager.WIFI_AP_STATE_DISABLED: + return "DISABLED"; + case WifiManager.WIFI_AP_STATE_DISABLING: + return "DISABLING"; + case WifiManager.WIFI_AP_STATE_ENABLED: + return "ENABLED"; + case WifiManager.WIFI_AP_STATE_ENABLING: + return "ENABLING"; + case WifiManager.WIFI_AP_STATE_FAILED: + return "FAILED"; + } + return null; } public void addCallback(Callback callback) { @@ -66,7 +88,7 @@ public class HotspotControllerImpl implements HotspotController { @Override public boolean isHotspotEnabled() { - return mWifiManager.getWifiApState() == WifiManager.WIFI_AP_STATE_ENABLED; + return mHotspotState == WifiManager.WIFI_AP_STATE_ENABLED; } @Override @@ -76,7 +98,6 @@ public class HotspotControllerImpl implements HotspotController { @Override public void setHotspotEnabled(boolean enabled) { - final ContentResolver cr = mContext.getContentResolver(); // Call provisioning app which is called when enabling Tethering from Settings if (enabled && TetherUtil.isProvisioningNeeded(mContext)) { mContext.startServiceAsUser(TETHER_SERVICE_INTENT, UserHandle.CURRENT); @@ -113,7 +134,8 @@ public class HotspotControllerImpl implements HotspotController { if (DEBUG) Log.d(TAG, "onReceive " + intent.getAction()); int state = intent.getIntExtra( WifiManager.EXTRA_WIFI_AP_STATE, WifiManager.WIFI_AP_STATE_FAILED); - fireCallback(WifiManager.WIFI_AP_STATE_ENABLED == state); + mHotspotState = state; + fireCallback(mHotspotState == WifiManager.WIFI_AP_STATE_ENABLED); } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java index d4eb553..d907b00 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java @@ -36,7 +36,7 @@ public final class KeyguardMonitor extends KeyguardUpdateMonitorCallback { private int mCurrentUser; private boolean mShowing; private boolean mSecure; - private boolean mTrusted; + private boolean mCanSkipBouncer; private boolean mListening; @@ -47,7 +47,7 @@ public final class KeyguardMonitor extends KeyguardUpdateMonitorCallback { @Override public void onUserSwitched(int newUserId) { mCurrentUser = newUserId; - updateTrustedState(); + updateCanSkipBouncerState(); } }; } @@ -57,7 +57,7 @@ public final class KeyguardMonitor extends KeyguardUpdateMonitorCallback { if (mCallbacks.size() != 0 && !mListening) { mListening = true; mCurrentUser = ActivityManager.getCurrentUser(); - updateTrustedState(); + updateCanSkipBouncerState(); mKeyguardUpdateMonitor.registerCallback(this); mUserTracker.startTracking(); } @@ -79,8 +79,8 @@ public final class KeyguardMonitor extends KeyguardUpdateMonitorCallback { return mSecure; } - public boolean isTrusted() { - return mTrusted; + public boolean canSkipBouncer() { + return mCanSkipBouncer; } public void notifyKeyguardState(boolean showing, boolean secure) { @@ -92,12 +92,12 @@ public final class KeyguardMonitor extends KeyguardUpdateMonitorCallback { @Override public void onTrustChanged(int userId) { - updateTrustedState(); + updateCanSkipBouncerState(); notifyKeyguardChanged(); } - private void updateTrustedState() { - mTrusted = mKeyguardUpdateMonitor.getUserHasTrust(mCurrentUser); + private void updateCanSkipBouncerState() { + mCanSkipBouncer = mKeyguardUpdateMonitor.getUserCanSkipBouncer(mCurrentUser); } private void notifyKeyguardChanged() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java index 81f2d53..57dfff5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java @@ -31,6 +31,7 @@ import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.provider.Settings; +import android.telephony.ServiceState; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener; @@ -117,6 +118,9 @@ public class NetworkControllerImpl extends BroadcastReceiver // Handler that all callbacks are made on. private final CallbackHandler mCallbackHandler; + @VisibleForTesting + ServiceState mLastServiceState; + /** * Construct this controller object and register for updates. */ @@ -194,10 +198,10 @@ public class NetworkControllerImpl extends BroadcastReceiver filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED); filter.addAction(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED); filter.addAction(TelephonyIntents.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED); + filter.addAction(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED); filter.addAction(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION); filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); filter.addAction(ConnectivityManager.INET_CONDITION_ACTION); - filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED); filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED); mContext.registerReceiver(this, filter, null, mReceiverHandler); mListening = true; @@ -260,6 +264,11 @@ public class NetworkControllerImpl extends BroadcastReceiver } public boolean isEmergencyOnly() { + if (mMobileSignalControllers.size() == 0) { + // When there are no active subscriptions, determine emengency state from last + // broadcast. + return mLastServiceState != null && mLastServiceState.isEmergencyOnly(); + } int voiceSubId = mSubDefaults.getDefaultVoiceSubId(); if (!SubscriptionManager.isValidSubscriptionId(voiceSubId)) { for (MobileSignalController mobileSignalController : @@ -339,8 +348,6 @@ public class NetworkControllerImpl extends BroadcastReceiver if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION) || action.equals(ConnectivityManager.INET_CONDITION_ACTION)) { updateConnectivity(); - } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) { - handleConfigurationChanged(); } else if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) { refreshLocale(); updateAirplaneMode(false); @@ -356,6 +363,13 @@ public class NetworkControllerImpl extends BroadcastReceiver } else if (action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) { // Might have different subscriptions now. updateMobileControllers(); + } else if (action.equals(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED)) { + mLastServiceState = ServiceState.newFromBundle(intent.getExtras()); + if (mMobileSignalControllers.size() == 0) { + // If none of the subscriptions are active, we might need to recalculate + // emergency state. + recalculateEmergency(); + } } else { int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY, SubscriptionManager.INVALID_SUBSCRIPTION_ID); @@ -373,8 +387,18 @@ public class NetworkControllerImpl extends BroadcastReceiver } } - public void handleConfigurationChanged() { + public void onConfigurationChanged() { mConfig = Config.readConfig(mContext); + mReceiverHandler.post(new Runnable() { + @Override + public void run() { + handleConfigurationChanged(); + } + }); + } + + @VisibleForTesting + void handleConfigurationChanged() { for (MobileSignalController mobileSignalController : mMobileSignalControllers.values()) { mobileSignalController.setConfiguration(mConfig); } @@ -580,6 +604,8 @@ public class NetworkControllerImpl extends BroadcastReceiver pw.println(mAirplaneMode); pw.print(" mLocale="); pw.println(mLocale); + pw.print(" mLastServiceState="); + pw.println(mLastServiceState); for (MobileSignalController mobileSignalController : mMobileSignalControllers.values()) { mobileSignalController.dump(pw); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java index 41fc967..6fabe9b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java @@ -412,7 +412,7 @@ public class UserSwitcherController { public int getCount() { boolean secureKeyguardShowing = mController.mKeyguardMonitor.isShowing() && mController.mKeyguardMonitor.isSecure() - && !mController.mKeyguardMonitor.isTrusted(); + && !mController.mKeyguardMonitor.canSkipBouncer(); if (!secureKeyguardShowing) { return mController.mUsers.size(); } diff --git a/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java index 3f5ca58..a2b062c 100644 --- a/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java +++ b/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java @@ -28,13 +28,14 @@ import android.preference.PreferenceFragment; import android.preference.PreferenceScreen; import android.preference.SwitchPreference; import android.provider.Settings; +import android.view.MenuItem; +import com.android.internal.logging.MetricsLogger; import com.android.systemui.DemoMode; import com.android.systemui.R; public class DemoModeFragment extends PreferenceFragment implements OnPreferenceChangeListener { - private static final String DEMO_MODE_ALLOWED = "sysui_demo_allowed"; private static final String DEMO_MODE_ON = "sysui_tuner_demo_on"; private static final String[] STATUS_ICONS = { @@ -75,10 +76,33 @@ public class DemoModeFragment extends PreferenceFragment implements OnPreference updateDemoModeEnabled(); updateDemoModeOn(); ContentResolver contentResolver = getContext().getContentResolver(); - contentResolver.registerContentObserver(Settings.Global.getUriFor(DEMO_MODE_ALLOWED), false, - mDemoModeObserver); + contentResolver.registerContentObserver(Settings.Global.getUriFor( + DemoMode.DEMO_MODE_ALLOWED), false, mDemoModeObserver); contentResolver.registerContentObserver(Settings.Global.getUriFor(DEMO_MODE_ON), false, mDemoModeObserver); + setHasOptionsMenu(true); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + getFragmentManager().popBackStack(); + break; + } + return super.onOptionsItemSelected(item); + } + + @Override + public void onResume() { + super.onResume(); + MetricsLogger.visibility(getContext(), MetricsLogger.TUNER_DEMO_MODE, true); + } + + @Override + public void onPause() { + super.onPause(); + MetricsLogger.visibility(getContext(), MetricsLogger.TUNER_DEMO_MODE, false); } @Override @@ -89,7 +113,7 @@ public class DemoModeFragment extends PreferenceFragment implements OnPreference private void updateDemoModeEnabled() { boolean enabled = Settings.Global.getInt(getContext().getContentResolver(), - DEMO_MODE_ALLOWED, 0) != 0; + DemoMode.DEMO_MODE_ALLOWED, 0) != 0; mEnabledSwitch.setChecked(enabled); mOnSwitch.setEnabled(enabled); } @@ -102,15 +126,18 @@ public class DemoModeFragment extends PreferenceFragment implements OnPreference @Override public boolean onPreferenceChange(Preference preference, Object newValue) { + boolean enabled = newValue == Boolean.TRUE; if (preference == mEnabledSwitch) { - if (newValue != Boolean.TRUE) { + if (!enabled) { // Make sure we aren't in demo mode when disabling it. mOnSwitch.setChecked(false); stopDemoMode(); } - setGlobal(DEMO_MODE_ALLOWED, newValue == Boolean.TRUE ? 1 : 0); + MetricsLogger.action(getContext(), MetricsLogger.TUNER_DEMO_MODE_ENABLED, enabled); + setGlobal(DemoMode.DEMO_MODE_ALLOWED, enabled ? 1 : 0); } else if (preference == mOnSwitch) { - if (newValue == Boolean.TRUE) { + MetricsLogger.action(getContext(), MetricsLogger.TUNER_DEMO_MODE_ON, enabled); + if (enabled) { startDemoMode(); } else { stopDemoMode(); diff --git a/packages/SystemUI/src/com/android/systemui/tuner/QsTuner.java b/packages/SystemUI/src/com/android/systemui/tuner/QsTuner.java index a5b244e..37ac098 100644 --- a/packages/SystemUI/src/com/android/systemui/tuner/QsTuner.java +++ b/packages/SystemUI/src/com/android/systemui/tuner/QsTuner.java @@ -40,6 +40,7 @@ import android.widget.EditText; import android.widget.FrameLayout; import android.widget.ScrollView; +import com.android.internal.logging.MetricsLogger; import com.android.systemui.R; import com.android.systemui.qs.QSPanel; import com.android.systemui.qs.QSTile; @@ -79,12 +80,25 @@ public class QsTuner extends Fragment implements Callback { menu.add(0, MENU_RESET, 0, com.android.internal.R.string.reset); } + public void onResume() { + super.onResume(); + MetricsLogger.visibility(getContext(), MetricsLogger.TUNER_QS, true); + } + + public void onPause() { + super.onPause(); + MetricsLogger.visibility(getContext(), MetricsLogger.TUNER_QS, false); + } + @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case MENU_RESET: mTileHost.reset(); break; + case android.R.id.home: + getFragmentManager().popBackStack(); + break; } return super.onOptionsItemSelected(item); } @@ -205,6 +219,8 @@ public class QsTuner extends Fragment implements Callback { if (oldTile.equals(newTile)) { return; } + MetricsLogger.action(getContext(), MetricsLogger.TUNER_QS_REORDER, oldTile + "," + + newTile); List<String> order = new ArrayList<>(mTileSpecs); int index = order.indexOf(oldTile); if (index < 0) { @@ -217,12 +233,14 @@ public class QsTuner extends Fragment implements Callback { } public void remove(String tile) { + MetricsLogger.action(getContext(), MetricsLogger.TUNER_QS_REMOVE, tile); List<String> tiles = new ArrayList<>(mTileSpecs); tiles.remove(tile); setTiles(tiles); } public void add(String tile) { + MetricsLogger.action(getContext(), MetricsLogger.TUNER_QS_ADD, tile); List<String> tiles = new ArrayList<>(mTileSpecs); tiles.add(tile); setTiles(tiles); diff --git a/packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java b/packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java index d4cc56d..e5b550e 100644 --- a/packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java +++ b/packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java @@ -23,6 +23,7 @@ import android.provider.Settings; import android.text.TextUtils; import android.util.AttributeSet; +import com.android.internal.logging.MetricsLogger; import com.android.systemui.statusbar.phone.StatusBarIconController; import com.android.systemui.tuner.TunerService.Tunable; @@ -50,11 +51,14 @@ public class StatusBarSwitch extends SwitchPreference implements Tunable { if (!value) { // If not enabled add to blacklist. if (!mBlacklist.contains(getKey())) { + MetricsLogger.action(getContext(), MetricsLogger.TUNER_STATUS_BAR_DISABLE, + getKey()); mBlacklist.add(getKey()); setList(mBlacklist); } } else { if (mBlacklist.remove(getKey())) { + MetricsLogger.action(getContext(), MetricsLogger.TUNER_STATUS_BAR_ENABLE, getKey()); setList(mBlacklist); } } diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java index 4a8c2e4..71b5de5 100644 --- a/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java +++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java @@ -17,7 +17,10 @@ package com.android.systemui.tuner; import static com.android.systemui.BatteryMeterView.SHOW_PERCENT_SETTING; +import android.app.AlertDialog; import android.app.FragmentTransaction; +import android.content.DialogInterface; +import android.content.DialogInterface.OnClickListener; import android.database.ContentObserver; import android.net.Uri; import android.os.Bundle; @@ -28,19 +31,29 @@ import android.preference.Preference.OnPreferenceClickListener; import android.preference.PreferenceFragment; import android.preference.PreferenceGroup; import android.preference.SwitchPreference; +import android.provider.Settings; import android.provider.Settings.System; +import android.view.Menu; +import android.view.MenuInflater; import android.view.MenuItem; +import com.android.internal.logging.MetricsLogger; import com.android.systemui.R; import com.android.systemui.statusbar.phone.StatusBarIconController; import com.android.systemui.tuner.TunerService.Tunable; public class TunerFragment extends PreferenceFragment { + private static final String TAG = "TunerFragment"; + private static final String KEY_QS_TUNER = "qs_tuner"; private static final String KEY_DEMO_MODE = "demo_mode"; private static final String KEY_BATTERY_PCT = "battery_pct"; + public static final String SETTING_SEEN_TUNER_WARNING = "seen_tuner_warning"; + + private static final int MENU_REMOVE = Menu.FIRST + 1; + private final SettingObserver mSettingObserver = new SettingObserver(); private SwitchPreference mBatteryPct; @@ -73,6 +86,19 @@ public class TunerFragment extends PreferenceFragment { } }); mBatteryPct = (SwitchPreference) findPreference(KEY_BATTERY_PCT); + if (Settings.Secure.getInt(getContext().getContentResolver(), SETTING_SEEN_TUNER_WARNING, + 0) == 0) { + new AlertDialog.Builder(getContext()) + .setTitle(R.string.tuner_warning_title) + .setMessage(R.string.tuner_warning) + .setPositiveButton(R.string.got_it, new OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + Settings.Secure.putInt(getContext().getContentResolver(), + SETTING_SEEN_TUNER_WARNING, 1); + } + }).show(); + } } @Override @@ -83,6 +109,7 @@ public class TunerFragment extends PreferenceFragment { System.getUriFor(SHOW_PERCENT_SETTING), false, mSettingObserver); registerPrefs(getPreferenceScreen()); + MetricsLogger.visibility(getContext(), MetricsLogger.TUNER, true); } @Override @@ -91,6 +118,7 @@ public class TunerFragment extends PreferenceFragment { getContext().getContentResolver().unregisterContentObserver(mSettingObserver); unregisterPrefs(getPreferenceScreen()); + MetricsLogger.visibility(getContext(), MetricsLogger.TUNER, false); } private void registerPrefs(PreferenceGroup group) { @@ -120,11 +148,24 @@ public class TunerFragment extends PreferenceFragment { } @Override + public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + menu.add(Menu.NONE, MENU_REMOVE, Menu.NONE, R.string.remove_from_settings); + } + + @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: getActivity().finish(); return true; + case MENU_REMOVE: + TunerService.showResetRequest(getContext(), new Runnable() { + @Override + public void run() { + getActivity().finish(); + } + }); + return true; } return super.onOptionsItemSelected(item); } @@ -152,6 +193,7 @@ public class TunerFragment extends PreferenceFragment { @Override public boolean onPreferenceChange(Preference preference, Object newValue) { final boolean v = (Boolean) newValue; + MetricsLogger.action(getContext(), MetricsLogger.TUNER_BATTERY_PERCENTAGE, v); System.putInt(getContext().getContentResolver(), SHOW_PERCENT_SETTING, v ? 1 : 0); return true; } diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java index de5aaf6..d3f33ab 100644 --- a/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java +++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java @@ -16,8 +16,15 @@ package com.android.systemui.tuner; import android.app.ActivityManager; +import android.app.AlertDialog; +import android.content.BroadcastReceiver; +import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; +import android.content.DialogInterface; +import android.content.DialogInterface.OnClickListener; +import android.content.Intent; +import android.content.pm.PackageManager; import android.database.ContentObserver; import android.net.Uri; import android.os.Handler; @@ -25,9 +32,13 @@ import android.os.Looper; import android.provider.Settings; import android.util.ArrayMap; +import com.android.systemui.BatteryMeterView; +import com.android.systemui.DemoMode; +import com.android.systemui.R; import com.android.systemui.SystemUI; import com.android.systemui.SystemUIApplication; import com.android.systemui.settings.CurrentUserTracker; +import com.android.systemui.statusbar.phone.SystemUIDialog; import java.util.ArrayList; import java.util.HashMap; @@ -36,6 +47,8 @@ import java.util.List; public class TunerService extends SystemUI { + public static final String ACTION_CLEAR = "com.android.systemui.action.CLEAR_TUNER"; + private final Observer mObserver = new Observer(); // Map of Uris we listen on to their settings keys. private final ArrayMap<Uri, String> mListeningUris = new ArrayMap<>(); @@ -118,6 +131,19 @@ public class TunerService extends SystemUI { } } + public void clearAll() { + // A couple special cases. + Settings.Global.putString(mContentResolver, DemoMode.DEMO_MODE_ALLOWED, null); + Settings.System.putString(mContentResolver, BatteryMeterView.SHOW_PERCENT_SETTING, null); + Intent intent = new Intent(DemoMode.ACTION_DEMO); + intent.putExtra(DemoMode.EXTRA_COMMAND, DemoMode.COMMAND_EXIT); + mContext.sendBroadcast(intent); + + for (String key : mTunableLookup.keySet()) { + Settings.Secure.putString(mContentResolver, key, null); + } + } + // Only used in other processes, such as the tuner. private static TunerService sInstance; @@ -141,6 +167,44 @@ public class TunerService extends SystemUI { return sInstance; } + public static final void showResetRequest(final Context context, final Runnable onDisabled) { + SystemUIDialog dialog = new SystemUIDialog(context); + dialog.setMessage(R.string.remove_from_settings_prompt); + dialog.setButton(DialogInterface.BUTTON_NEGATIVE, context.getString(R.string.cancel), + (OnClickListener) null); + dialog.setButton(DialogInterface.BUTTON_POSITIVE, + context.getString(R.string.guest_exit_guest_dialog_remove), new OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + // Tell the tuner (in main SysUI process) to clear all its settings. + context.sendBroadcast(new Intent(TunerService.ACTION_CLEAR)); + // Disable access to tuner. + TunerService.setTunerEnabled(context, false); + // Make them sit through the warning dialog again. + Settings.Secure.putInt(context.getContentResolver(), + TunerFragment.SETTING_SEEN_TUNER_WARNING, 0); + if (onDisabled != null) { + onDisabled.run(); + } + } + }); + dialog.show(); + } + + public static final void setTunerEnabled(Context context, boolean enabled) { + context.getPackageManager().setComponentEnabledSetting( + new ComponentName(context, TunerActivity.class), + enabled ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED + : PackageManager.COMPONENT_ENABLED_STATE_DISABLED, + PackageManager.DONT_KILL_APP); + } + + public static final boolean isTunerEnabled(Context context) { + return context.getPackageManager().getComponentEnabledSetting( + new ComponentName(context, TunerActivity.class)) + == PackageManager.COMPONENT_ENABLED_STATE_ENABLED; + } + private class Observer extends ContentObserver { public Observer() { super(new Handler(Looper.getMainLooper())); @@ -157,4 +221,13 @@ public class TunerService extends SystemUI { public interface Tunable { void onTuningChanged(String key, String newValue); } + + public static class ClearReceiver extends BroadcastReceiver { + @Override + public void onReceive(Context context, Intent intent) { + if (ACTION_CLEAR.equals(intent.getAction())) { + get(context).clearAll(); + } + } + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java index 52dea40..d9b9063 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java @@ -21,6 +21,7 @@ import android.content.Intent; import android.net.ConnectivityManager; import android.net.NetworkCapabilities; import android.os.Looper; +import android.telephony.ServiceState; import android.telephony.SignalStrength; import android.telephony.SubscriptionInfo; import android.telephony.TelephonyManager; @@ -70,11 +71,20 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest { public void testEmergencyOnlyNoSubscriptions() { setupDefaultSignal(); + setSubscriptions(); + mNetworkController.mLastServiceState = new ServiceState(); + mNetworkController.mLastServiceState.setEmergencyOnly(true); mNetworkController.recalculateEmergency(); - verifyEmergencyOnly(false); + verifyEmergencyOnly(true); + } + public void testNoEmengencyNoSubscriptions() { + setupDefaultSignal(); setSubscriptions(); - verifyEmergencyOnly(true); + mNetworkController.mLastServiceState = new ServiceState(); + mNetworkController.mLastServiceState.setEmergencyOnly(false); + mNetworkController.recalculateEmergency(); + verifyEmergencyOnly(false); } public void testNoSimlessIconWithoutMobile() { |