From 89907cdd37b02468e5e12d2203dc6cf5123e98c7 Mon Sep 17 00:00:00 2001 From: Nathan Harold Date: Mon, 20 May 2019 23:21:48 +0000 Subject: [PATCH 01/21] Revert "Use the SubId in the TM.getNetworkType if Valid" This reverts commit f36fee3cf764838aa8b1f59142e82049e4cbacb1. Reason for revert: 133129040 Bug: 133129040 Merged-In: I9a974018d4155426b1050a4b80b82f4bf4a9d996 Change-Id: Ib6f9a4e461a7e1cfa6c4648bd289a8f92475423e (cherry picked from commit af62adcb6c328ef682237ec027793fc8e27782d5) --- .../android/telephony/TelephonyManager.java | 34 +++++++++++++++++-- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index b722b79240dd8..dab1e6f4abde2 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -2446,7 +2446,21 @@ public class TelephonyManager { * @return the NETWORK_TYPE_xxxx for current data connection. */ public @NetworkType int getNetworkType() { - return getDataNetworkType(); + try { + ITelephony telephony = getITelephony(); + if (telephony != null) { + return telephony.getNetworkType(); + } else { + // This can happen when the ITelephony interface is not up yet. + return NETWORK_TYPE_UNKNOWN; + } + } catch(RemoteException ex) { + // This shouldn't happen in the normal case + return NETWORK_TYPE_UNKNOWN; + } catch (NullPointerException ex) { + // This could happen before phone restarts due to crashing + return NETWORK_TYPE_UNKNOWN; + } } /** @@ -2477,9 +2491,23 @@ public class TelephonyManager { * @hide */ @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) + @UnsupportedAppUsage public int getNetworkType(int subId) { - return getDataNetworkType(subId); + try { + ITelephony telephony = getITelephony(); + if (telephony != null) { + return telephony.getNetworkTypeForSubscriber(subId, getOpPackageName()); + } else { + // This can happen when the ITelephony interface is not up yet. + return NETWORK_TYPE_UNKNOWN; + } + } catch (RemoteException ex) { + // This shouldn't happen in the normal case + return NETWORK_TYPE_UNKNOWN; + } catch (NullPointerException ex) { + // This could happen before phone restarts due to crashing + return NETWORK_TYPE_UNKNOWN; + } } /** From 555f75d0796be0bac738ed592cf19467bfe9a446 Mon Sep 17 00:00:00 2001 From: James O'Leary Date: Mon, 20 May 2019 23:21:54 -0400 Subject: [PATCH 02/21] Fix NPE with live wallpaper Test: Verify WAI Fixes: 133130262, 133194773, 133168135, 133160573 Change-Id: Ib38947326839a5c4806b909ead2484efd5a535a1 (cherry picked from commit 35cb43b811206def4929128911d658ed415673b3) --- .../src/com/android/systemui/assist/PhoneStateMonitor.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/SystemUI/src/com/android/systemui/assist/PhoneStateMonitor.java b/packages/SystemUI/src/com/android/systemui/assist/PhoneStateMonitor.java index 8c070835f69ed..ea08c335b31d4 100644 --- a/packages/SystemUI/src/com/android/systemui/assist/PhoneStateMonitor.java +++ b/packages/SystemUI/src/com/android/systemui/assist/PhoneStateMonitor.java @@ -136,7 +136,11 @@ final class PhoneStateMonitor { } private boolean isLauncherShowing(ActivityManager.RunningTaskInfo runningTaskInfo) { - return runningTaskInfo.topActivity.equals(mDefaultHome); + if (runningTaskInfo == null) { + return false; + } else { + return runningTaskInfo.topActivity.equals(mDefaultHome); + } } private boolean isAppImmersive() { From aa872b724e0fd993a571c18eacdbef7e95bb7a18 Mon Sep 17 00:00:00 2001 From: Lucas Dupin Date: Wed, 22 May 2019 13:04:12 -0700 Subject: [PATCH 03/21] Temporarily disable retry on bouncer when pattern Bug: 132687980 Test: manual Change-Id: I40c1e6201a6ce2b7bc644a2977f7afe383dd2e35 (cherry picked from commit d5c4ca2e914c0243f517af6114adb1d97055534c) --- .../src/com/android/keyguard/KeyguardSecurityContainer.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java index 906ace78148e5..eef61dbb0949c 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java @@ -269,7 +269,8 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe mSwipeUpToRetry = mUpdateMonitor.isUnlockWithFacePossible(userId) && securityMode != SecurityMode.SimPin && securityMode != SecurityMode.SimPuk - && securityMode != SecurityMode.None; + && securityMode != SecurityMode.None + && securityMode != SecurityMode.Pattern; } public CharSequence getTitle() { From 9c0d170a5ce9e62e79e47a644e2d17104a3c88ff Mon Sep 17 00:00:00 2001 From: chen xu Date: Tue, 28 May 2019 15:28:37 -0700 Subject: [PATCH 04/21] skip permission check for TelephonyManager API getMmsUserAgent Bug: 133637995 Test: Manual test Change-Id: Ib9f211120c34e9b48c02f990088c32fb307a64f2 (cherry picked from commit 48781653654ff06b5db51ab312fd1f01111d65de) --- .../android/telephony/TelephonyManager.java | 24 ++++++++++++++----- .../internal/telephony/ITelephony.aidl | 10 ++++++++ 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index d63c37accb37b..2ba34c6c3453a 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -5356,18 +5356,30 @@ public class TelephonyManager { * Returns the MMS user agent. */ public String getMmsUserAgent() { - if (mContext == null) return null; - return SubscriptionManager.getResourcesForSubId(mContext, getSubId()).getString( - com.android.internal.R.string.config_mms_user_agent); + try { + ITelephony telephony = getITelephony(); + if (telephony != null) { + return telephony.getMmsUserAgent(getSubId()); + } + } catch (RemoteException ex) { + } catch (NullPointerException ex) { + } + return null; } /** * Returns the MMS user agent profile URL. */ public String getMmsUAProfUrl() { - if (mContext == null) return null; - return SubscriptionManager.getResourcesForSubId(mContext, getSubId()).getString( - com.android.internal.R.string.config_mms_user_agent_profile_url); + try { + ITelephony telephony = getITelephony(); + if (telephony != null) { + return telephony.getMmsUAProfUrl(getSubId()); + } + } catch (RemoteException ex) { + } catch (NullPointerException ex) { + } + return null; } /** diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl index 63aded1c4b206..cf1323a328fe4 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -1986,4 +1986,14 @@ interface ITelephony { * outgoing SmsManager operation. */ oneway void enqueueSmsPickResult(String callingPackage, IIntegerConsumer subIdResult); + + /** + * Returns the MMS user agent. + */ + String getMmsUserAgent(int subId); + + /** + * Returns the MMS user agent profile URL. + */ + String getMmsUAProfUrl(int subId); } From 5e096eec2060bf5073d896a6b35ea10c1aa4d8df Mon Sep 17 00:00:00 2001 From: chen xu Date: Tue, 28 May 2019 15:28:37 -0700 Subject: [PATCH 05/21] skip permission check for TelephonyManager API getMmsUserAgent Bug: 133637995 Test: Manual test Change-Id: Ib9f211120c34e9b48c02f990088c32fb307a64f2 (cherry picked from commit 48781653654ff06b5db51ab312fd1f01111d65de) --- .../android/telephony/TelephonyManager.java | 24 ++++++++++++++----- .../internal/telephony/ITelephony.aidl | 10 ++++++++ 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index d63c37accb37b..2ba34c6c3453a 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -5356,18 +5356,30 @@ public class TelephonyManager { * Returns the MMS user agent. */ public String getMmsUserAgent() { - if (mContext == null) return null; - return SubscriptionManager.getResourcesForSubId(mContext, getSubId()).getString( - com.android.internal.R.string.config_mms_user_agent); + try { + ITelephony telephony = getITelephony(); + if (telephony != null) { + return telephony.getMmsUserAgent(getSubId()); + } + } catch (RemoteException ex) { + } catch (NullPointerException ex) { + } + return null; } /** * Returns the MMS user agent profile URL. */ public String getMmsUAProfUrl() { - if (mContext == null) return null; - return SubscriptionManager.getResourcesForSubId(mContext, getSubId()).getString( - com.android.internal.R.string.config_mms_user_agent_profile_url); + try { + ITelephony telephony = getITelephony(); + if (telephony != null) { + return telephony.getMmsUAProfUrl(getSubId()); + } + } catch (RemoteException ex) { + } catch (NullPointerException ex) { + } + return null; } /** diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl index 63aded1c4b206..cf1323a328fe4 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -1986,4 +1986,14 @@ interface ITelephony { * outgoing SmsManager operation. */ oneway void enqueueSmsPickResult(String callingPackage, IIntegerConsumer subIdResult); + + /** + * Returns the MMS user agent. + */ + String getMmsUserAgent(int subId); + + /** + * Returns the MMS user agent profile URL. + */ + String getMmsUAProfUrl(int subId); } From 7f84c0c3d7ffdf97f3adf47abbb9b964c2ef577e Mon Sep 17 00:00:00 2001 From: Daniel Chapin Date: Thu, 30 May 2019 19:40:47 +0000 Subject: [PATCH 06/21] Revert "Fix AppFuseMountScope.close()" This reverts commit be9c9900198891e97c228d244c3df064560c4756. Reason for revert: b/134032662 Change-Id: I7132ba078d44ba424bc8a9bf6874f8077738b22d (cherry picked from commit e890b9793b4f0d7d139a5e78a5c46735b2cf04c2) --- .../com/android/server/StorageManagerService.java | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java index d2b992bad4623..2f2b40a7b20f7 100644 --- a/services/core/java/com/android/server/StorageManagerService.java +++ b/services/core/java/com/android/server/StorageManagerService.java @@ -2842,9 +2842,8 @@ class StorageManagerService extends IStorageManager.Stub } } - /** Not thread safe */ class AppFuseMountScope extends AppFuseBridge.MountScope { - private boolean mMounted = false; + boolean opened = false; public AppFuseMountScope(int uid, int mountId) { super(uid, mountId); @@ -2853,9 +2852,8 @@ class StorageManagerService extends IStorageManager.Stub @Override public ParcelFileDescriptor open() throws NativeDaemonConnectorException { try { - final FileDescriptor fd = mVold.mountAppFuse(uid, mountId); - mMounted = true; - return new ParcelFileDescriptor(fd); + return new ParcelFileDescriptor( + mVold.mountAppFuse(uid, mountId)); } catch (Exception e) { throw new NativeDaemonConnectorException("Failed to mount", e); } @@ -2874,9 +2872,9 @@ class StorageManagerService extends IStorageManager.Stub @Override public void close() throws Exception { - if (mMounted) { + if (opened) { mVold.unmountAppFuse(uid, mountId); - mMounted = false; + opened = false; } } } From f9a50938bcec3952b0ed7ea8e0aa63e702184b65 Mon Sep 17 00:00:00 2001 From: "Philip P. Moltmann" Date: Thu, 30 May 2019 16:21:57 -0700 Subject: [PATCH 07/21] Don't create system fixed, revoked permissions .. when restricting a previously unrestricted permission. Fixes: 134069814 Test: Upgraded from Q (before loc bg was restricted) to Q (after log bg was restricted) and saw previously system-fixed loc bg perm to be re-granted via the DefaultPermissionGrantPolicy. Change-Id: I641a95a0e481ca057c4fb7e05b29b18b7a8c10b6 (cherry picked from commit 6a59bbe2be05c374df96765600f616df8b4c564c) --- .../server/pm/permission/PermissionManagerService.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java index 267fbf030619f..beb72686d6cee 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java @@ -1173,6 +1173,14 @@ public class PermissionManagerService { } } + if (hardRestricted && !restrictionExempt + && (flags & FLAG_PERMISSION_SYSTEM_FIXED) != 0) { + // Applying a hard restriction implies revoking it. This might + // lead to a system-fixed, revoked permission. + flags &= ~FLAG_PERMISSION_SYSTEM_FIXED; + wasChanged = true; + } + if (wasChanged) { updatedUserIds = ArrayUtils.appendInt(updatedUserIds, userId); } From 185357389a2e12525761d7a8416ab7100844263e Mon Sep 17 00:00:00 2001 From: "Philip P. Moltmann" Date: Fri, 31 May 2019 08:48:14 -0700 Subject: [PATCH 08/21] Reset SYSTEM_FIXED flags for hard restricted perms So that incorrectly SYSTEM_FIXED / denied permissions will be able to get regrated via the default permission grant policy This can be removed after all devices have been fixed Test: Got system into the state with SYSTEM_FIXED / denied permission and then silulated an OTA with this change Bug: 134069814 Change-Id: I7bc986f0d3e69dd60a017f16867182163fd6eecb (cherry picked from commit 0891123822d6173686e9772c3265b72c27b2b901) --- .../android/server/pm/permission/PermissionManagerService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java index beb72686d6cee..81dd868ca8e9b 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java @@ -1173,7 +1173,7 @@ public class PermissionManagerService { } } - if (hardRestricted && !restrictionExempt + if (hardRestricted && (flags & FLAG_PERMISSION_SYSTEM_FIXED) != 0) { // Applying a hard restriction implies revoking it. This might // lead to a system-fixed, revoked permission. From a8e63b3decdc67c341df53c33670968719d91c49 Mon Sep 17 00:00:00 2001 From: Elisa Pascual Trevino Date: Wed, 12 Jun 2019 22:10:23 +0000 Subject: [PATCH 09/21] Revert "Prevent dismissing starting window when reopening app" This reverts commit 7c88cf83035e331bb4c4ccb519c8200f2e9d083f. Original bug: b/134561008 Reason for revert: b/135084202 Change-Id: Ib4c17f98d66c9efb10d800d9ba585d14be4ac878 (cherry picked from commit 6e814f9f3356cd56623c47ec50e2a84ec6bc10be) --- .../core/java/com/android/server/wm/AppWindowToken.java | 8 -------- 1 file changed, 8 deletions(-) diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java index 60cfe14f40803..4a9a3f71f90e5 100644 --- a/services/core/java/com/android/server/wm/AppWindowToken.java +++ b/services/core/java/com/android/server/wm/AppWindowToken.java @@ -540,14 +540,6 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree // If the app was already visible, don't reset the waitingToShow state. if (isHidden()) { waitingToShow = true; - - // Let's reset the draw state in order to prevent the starting window to be - // immediately dismissed when the app still has the surface. - forAllWindows(w -> { - if (w.mAttrs.type != TYPE_APPLICATION_STARTING) { - w.mWinAnimator.resetDrawState(); - } - }, true /* traverseTopToBottom */); } } From 14fdc8c3288a2bed2da3a2c43ef0a8ea3daaf19c Mon Sep 17 00:00:00 2001 From: Beth Thibodeau Date: Wed, 31 Jul 2019 20:23:44 +0000 Subject: [PATCH 10/21] Revert "Stop timer when notification isn't visible" This reverts commit 3c4a8e48d404649bd03ee8e6e377dcf9a65afee9. Reason for revert: NPE errors Fixes: b/138697134 Change-Id: Ic89eb58cd68485dcc5e7c5a3ef48d7ed79c303ca (cherry picked from commit 4c9726e0417521b20205165c8e81d24b3a95729c) --- .../widget/MediaNotificationView.java | 47 ------------------- .../NotificationMediaTemplateViewWrapper.java | 47 ++++--------------- 2 files changed, 8 insertions(+), 86 deletions(-) diff --git a/core/java/com/android/internal/widget/MediaNotificationView.java b/core/java/com/android/internal/widget/MediaNotificationView.java index 0d87afa42e3eb..e7d240a1035e6 100644 --- a/core/java/com/android/internal/widget/MediaNotificationView.java +++ b/core/java/com/android/internal/widget/MediaNotificationView.java @@ -26,8 +26,6 @@ import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.RemoteViews; -import java.util.ArrayList; - /** * A TextView that can float around an image on the end. * @@ -44,7 +42,6 @@ public class MediaNotificationView extends FrameLayout { private View mMainColumn; private View mMediaContent; private int mImagePushIn; - private ArrayList mListeners; public MediaNotificationView(Context context) { this(context, null); @@ -171,48 +168,4 @@ public class MediaNotificationView extends FrameLayout { mMainColumn = findViewById(com.android.internal.R.id.notification_main_column); mMediaContent = findViewById(com.android.internal.R.id.notification_media_content); } - - @Override - public void onVisibilityAggregated(boolean isVisible) { - super.onVisibilityAggregated(isVisible); - for (int i = 0; i < mListeners.size(); i++) { - mListeners.get(i).onAggregatedVisibilityChanged(isVisible); - } - } - - /** - * Add a listener to receive updates on the visibility of this view - * - * @param listener The listener to add. - */ - public void addVisibilityListener(VisibilityChangeListener listener) { - if (mListeners == null) { - mListeners = new ArrayList<>(); - } - if (!mListeners.contains(listener)) { - mListeners.add(listener); - } - } - - /** - * Remove the specified listener - * - * @param listener The listener to remove. - */ - public void removeVisibilityListener(VisibilityChangeListener listener) { - if (mListeners != null) { - mListeners.remove(listener); - } - } - - /** - * Interface for receiving updates when the view's visibility changes - */ - public interface VisibilityChangeListener { - /** - * Method called when the visibility of this view has changed - * @param isVisible true if the view is now visible - */ - void onAggregatedVisibilityChanged(boolean isVisible); - } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java index 38f9bff2a63f9..20e8b733ce6ab 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java @@ -39,7 +39,6 @@ import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; -import com.android.internal.widget.MediaNotificationView; import com.android.systemui.Dependency; import com.android.systemui.statusbar.NotificationMediaManager; import com.android.systemui.statusbar.TransformableView; @@ -68,7 +67,6 @@ public class NotificationMediaTemplateViewWrapper extends NotificationTemplateVi private View mSeekBarView; private Context mContext; private MetricsLogger mMetricsLogger; - private boolean mIsViewVisible; @VisibleForTesting protected SeekBar.OnSeekBarChangeListener mSeekListener = @@ -90,33 +88,11 @@ public class NotificationMediaTemplateViewWrapper extends NotificationTemplateVi } }; - MediaNotificationView.VisibilityChangeListener mVisibilityListener = - new MediaNotificationView.VisibilityChangeListener() { - @Override - public void onAggregatedVisibilityChanged(boolean isVisible) { - mIsViewVisible = isVisible; - if (isVisible) { - // Restart timer if we're currently playing and didn't already have one going - PlaybackState state = mMediaController.getPlaybackState(); - if (state != null && state.getState() == PlaybackState.STATE_PLAYING - && mSeekBarTimer == null && mSeekBarView != null - && mSeekBarView.getVisibility() != View.GONE) { - startTimer(); - } - } else { - clearTimer(); - } - } - }; - private MediaController.Callback mMediaCallback = new MediaController.Callback() { @Override public void onSessionDestroyed() { clearTimer(); mMediaController.unregisterCallback(this); - if (mView instanceof MediaNotificationView) { - ((MediaNotificationView) mView).removeVisibilityListener(mVisibilityListener); - } } @Override @@ -150,16 +126,10 @@ public class NotificationMediaTemplateViewWrapper extends NotificationTemplateVi mContext = ctx; mMediaManager = Dependency.get(NotificationMediaManager.class); mMetricsLogger = Dependency.get(MetricsLogger.class); - - if (mView instanceof MediaNotificationView) { - MediaNotificationView mediaView = (MediaNotificationView) mView; - mediaView.addVisibilityListener(mVisibilityListener); - } } private void resolveViews() { mActions = mView.findViewById(com.android.internal.R.id.media_actions); - mIsViewVisible = mView.isShown(); final MediaSession.Token token = mRow.getEntry().notification.getNotification().extras .getParcelable(Notification.EXTRA_MEDIA_SESSION); @@ -238,19 +208,18 @@ public class NotificationMediaTemplateViewWrapper extends NotificationTemplateVi private void startTimer() { clearTimer(); - if (mIsViewVisible) { - mSeekBarTimer = new Timer(true /* isDaemon */); - mSeekBarTimer.schedule(new TimerTask() { - @Override - public void run() { - mHandler.post(mOnUpdateTimerTick); - } - }, 0, PROGRESS_UPDATE_INTERVAL); - } + mSeekBarTimer = new Timer(true /* isDaemon */); + mSeekBarTimer.schedule(new TimerTask() { + @Override + public void run() { + mHandler.post(mOnUpdateTimerTick); + } + }, 0, PROGRESS_UPDATE_INTERVAL); } private void clearTimer() { if (mSeekBarTimer != null) { + // TODO: also trigger this when the notification panel is collapsed mSeekBarTimer.cancel(); mSeekBarTimer.purge(); mSeekBarTimer = null; From 8c1576b6ae0bc24426c32824d3c20e2f7e5ad621 Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Thu, 29 Aug 2019 15:16:27 -0700 Subject: [PATCH 11/21] Fix regression in updating gesture exclusion rects - Only update the rects when the view visibility changes if there were previously set rects Bug: 140157754 Test: atest SystemGestureExclusionRectsTest Change-Id: Ica58de4ff43da75cfcdac3f359fc915f65608e78 (cherry picked from commit 3baffd871c1e1a0b9ab412f4e6a2ba11758c6076) --- core/java/android/view/View.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 9c55bb065d41d..acccbffada352 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -14423,7 +14423,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } notifyAppearedOrDisappearedForContentCaptureIfNeeded(isVisible); - updateSystemGestureExclusionRects(); + + // Update the gesture exclusion rects only if they are set + final ListenerInfo info = getListenerInfo(); + if (info != null && info.mSystemGestureExclusionRects != null) { + updateSystemGestureExclusionRects(); + } } /** From 0fea60073bff3c1d6b089b18d4842930b11238d4 Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Thu, 29 Aug 2019 15:16:27 -0700 Subject: [PATCH 12/21] Fix regression in updating gesture exclusion rects - Only update the rects when the view visibility changes if there were previously set rects Bug: 140157754 Test: atest SystemGestureExclusionRectsTest Change-Id: Ica58de4ff43da75cfcdac3f359fc915f65608e78 (cherry picked from commit 3baffd871c1e1a0b9ab412f4e6a2ba11758c6076) --- core/java/android/view/View.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 9c55bb065d41d..acccbffada352 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -14423,7 +14423,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } notifyAppearedOrDisappearedForContentCaptureIfNeeded(isVisible); - updateSystemGestureExclusionRects(); + + // Update the gesture exclusion rects only if they are set + final ListenerInfo info = getListenerInfo(); + if (info != null && info.mSystemGestureExclusionRects != null) { + updateSystemGestureExclusionRects(); + } } /** From 0cb1a9f021c9cbd8702386b64dd245bb203e5f08 Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Thu, 29 Aug 2019 15:16:27 -0700 Subject: [PATCH 13/21] Fix regression in updating gesture exclusion rects - Only update the rects when the view visibility changes if there were previously set rects Bug: 140157754 Test: atest SystemGestureExclusionRectsTest Change-Id: Ica58de4ff43da75cfcdac3f359fc915f65608e78 (cherry picked from commit 3baffd871c1e1a0b9ab412f4e6a2ba11758c6076) --- core/java/android/view/View.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 9c55bb065d41d..acccbffada352 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -14423,7 +14423,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } notifyAppearedOrDisappearedForContentCaptureIfNeeded(isVisible); - updateSystemGestureExclusionRects(); + + // Update the gesture exclusion rects only if they are set + final ListenerInfo info = getListenerInfo(); + if (info != null && info.mSystemGestureExclusionRects != null) { + updateSystemGestureExclusionRects(); + } } /** From c67b17017cadd3bf51050e57651240e36bca261c Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Thu, 29 Aug 2019 15:16:27 -0700 Subject: [PATCH 14/21] Fix regression in updating gesture exclusion rects - Use the precalculated aggregate visibility instead of traversing hierarchy again in isShown() Bug: 140157754 Test: atest SystemGestureExclusionRectsTest Change-Id: Ica58de4ff43da75cfcdac3f359fc915f65608e78 (cherry picked from commit 05a36465b4dec80a656f0659536d5fc6187f9b0b) --- .../java/android/view/GestureExclusionTracker.java | 4 ++-- core/java/android/view/View.java | 14 ++++++++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/core/java/android/view/GestureExclusionTracker.java b/core/java/android/view/GestureExclusionTracker.java index fcc14c1967301..fffb323e6d500 100644 --- a/core/java/android/view/GestureExclusionTracker.java +++ b/core/java/android/view/GestureExclusionTracker.java @@ -44,7 +44,7 @@ class GestureExclusionTracker { while (i.hasNext()) { final GestureExclusionViewInfo info = i.next(); final View v = info.getView(); - if (v == null || !v.isAttachedToWindow() || !v.isShown()) { + if (v == null || !v.isAttachedToWindow() || !v.isAggregatedVisible()) { mGestureExclusionViewsChanged = true; i.remove(); continue; @@ -123,7 +123,7 @@ class GestureExclusionTracker { public int update() { final View excludedView = getView(); if (excludedView == null || !excludedView.isAttachedToWindow() - || !excludedView.isShown()) return GONE; + || !excludedView.isAggregatedVisible()) return GONE; final List localRects = excludedView.getSystemGestureExclusionRects(); final List newRects = new ArrayList<>(localRects.size()); for (Rect src : localRects) { diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 9c55bb065d41d..84665f78c7029 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -14343,6 +14343,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } } + /** + * @return true if this view and all ancestors are visible as of the last + * {@link #onVisibilityAggregated(boolean)} call. + */ + boolean isAggregatedVisible() { + return (mPrivateFlags3 & PFLAG3_AGGREGATED_VISIBLE) != 0; + } + /** * Internal dispatching method for {@link #onVisibilityAggregated}. Overridden by * ViewGroup. Intended to only be called when {@link #isAttachedToWindow()}, @@ -14371,7 +14379,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, @CallSuper public void onVisibilityAggregated(boolean isVisible) { // Update our internal visibility tracking so we can detect changes - boolean oldVisible = (mPrivateFlags3 & PFLAG3_AGGREGATED_VISIBLE) != 0; + boolean oldVisible = isAggregatedVisible(); mPrivateFlags3 = isVisible ? (mPrivateFlags3 | PFLAG3_AGGREGATED_VISIBLE) : (mPrivateFlags3 & ~PFLAG3_AGGREGATED_VISIBLE); if (isVisible && mAttachInfo != null) { @@ -14423,7 +14431,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } notifyAppearedOrDisappearedForContentCaptureIfNeeded(isVisible); - updateSystemGestureExclusionRects(); + if (isVisible != oldVisible) { + updateSystemGestureExclusionRects(); + } } /** From 31b0f874a8b38a6c42771dc46b967ebb59e65f87 Mon Sep 17 00:00:00 2001 From: Fabian Kozynski Date: Wed, 4 Sep 2019 11:18:46 -0400 Subject: [PATCH 15/21] Fixes regression caused by ag/9259064 Makes sure that onClickListeners are always up to date. Fixes: 139920678 Test: manual Test: atest UserDetailViewAdapterTest (fails on old code) Change-Id: I1060cb432b7e24a46a3472754efdf004798d6b6e (cherry picked from commit 8f571e59547dfb6293b9c24764bdc087c46fc713) --- .../systemui/qs/tiles/UserDetailView.java | 2 +- .../qs/tiles/UserDetailViewAdapterTest.kt | 128 ++++++++++++++++++ 2 files changed, 129 insertions(+), 1 deletion(-) create mode 100644 packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UserDetailViewAdapterTest.kt diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java index d6dad687e5d47..187a3bdec13fc 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java @@ -76,7 +76,7 @@ public class UserDetailView extends PseudoGridView { UserSwitcherController.UserRecord item) { UserDetailItemView v = UserDetailItemView.convertOrInflate( mContext, convertView, parent); - if ((v != convertView && !item.isCurrent) || item.isGuest) { + if (!item.isCurrent || item.isGuest) { v.setOnClickListener(this); } else { v.setOnClickListener(null); diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UserDetailViewAdapterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UserDetailViewAdapterTest.kt new file mode 100644 index 0000000000000..b51e716591fe4 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UserDetailViewAdapterTest.kt @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2019 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.qs.tiles + +import android.content.Context +import android.content.pm.UserInfo +import android.graphics.Bitmap +import android.testing.AndroidTestingRunner +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.statusbar.policy.UserSwitcherController +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.ArgumentMatchers.any +import org.mockito.ArgumentMatchers.anyBoolean +import org.mockito.ArgumentMatchers.anyInt +import org.mockito.Mock +import org.mockito.Mockito.`when` +import org.mockito.Mockito.verify +import org.mockito.MockitoAnnotations + +@RunWith(AndroidTestingRunner::class) +@SmallTest +class UserDetailViewAdapterTest : SysuiTestCase() { + + @Mock private lateinit var mUserSwitcherController: UserSwitcherController + @Mock private lateinit var mParent: ViewGroup + @Mock private lateinit var mUserDetailItemView: UserDetailItemView + @Mock private lateinit var mOtherView: View + @Mock private lateinit var mInflatedUserDetailItemView: UserDetailItemView + @Mock private lateinit var mUserInfo: UserInfo + @Mock private lateinit var mPicture: Bitmap + @Mock private lateinit var mLayoutInflater: LayoutInflater + private lateinit var adapter: UserDetailView.Adapter + + @Before + fun setUp() { + MockitoAnnotations.initMocks(this) + + mContext.addMockSystemService(Context.LAYOUT_INFLATER_SERVICE, mLayoutInflater) + `when`(mLayoutInflater.inflate(anyInt(), any(ViewGroup::class.java), anyBoolean())) + .thenReturn(mInflatedUserDetailItemView) + adapter = UserDetailView.Adapter(mContext, mUserSwitcherController) + } + + private fun clickableTest( + current: Boolean, + guest: Boolean, + convertView: View, + shouldBeClickable: Boolean + ) { + val user = createUserRecord(current, guest) + val v = adapter.createUserDetailItemView(convertView, mParent, user) + if (shouldBeClickable) { + verify(v).setOnClickListener(adapter) + } else { + verify(v).setOnClickListener(null) + } + } + + @Test + fun testGuestIsClickable_differentViews_notCurrent() { + clickableTest(false, true, mOtherView, true) + } + + @Test + fun testGuestIsClickable_differentViews_Current() { + clickableTest(true, true, mOtherView, true) + } + + @Test + fun testGuestIsClickable_sameView_notCurrent() { + clickableTest(false, true, mUserDetailItemView, true) + } + + @Test + fun testGuestIsClickable_sameView_Current() { + clickableTest(true, true, mUserDetailItemView, true) + } + + @Test + fun testNotGuestCurrentUserIsNotClickable_otherView() { + clickableTest(true, false, mOtherView, false) + } + + @Test + fun testNotGuestCurrentUserIsNotClickable_sameView() { + clickableTest(true, false, mUserDetailItemView, false) + } + + @Test + fun testNotGuestNotCurrentUserIsClickable_otherView() { + clickableTest(false, false, mOtherView, true) + } + + @Test + fun testNotGuestNotCurrentUserIsClickable_sameView() { + clickableTest(false, false, mUserDetailItemView, true) + } + + private fun createUserRecord(current: Boolean, guest: Boolean) = + UserSwitcherController.UserRecord( + mUserInfo, + mPicture, + guest, + current, + false /* isAddUser */, + false /* isRestricted */, + true /* isSwitchToEnabled */) +} \ No newline at end of file From 2b904295d28c504aecb239b0bb8e9f2cff58d0b1 Mon Sep 17 00:00:00 2001 From: Fabian Kozynski Date: Wed, 4 Sep 2019 11:18:46 -0400 Subject: [PATCH 16/21] Fixes regression caused by ag/9259064 Makes sure that onClickListeners are always up to date. Fixes: 139920678 Test: manual Test: atest UserDetailViewAdapterTest (fails on old code) Change-Id: I1060cb432b7e24a46a3472754efdf004798d6b6e (cherry picked from commit 8f571e59547dfb6293b9c24764bdc087c46fc713) --- .../systemui/qs/tiles/UserDetailView.java | 2 +- .../qs/tiles/UserDetailViewAdapterTest.kt | 128 ++++++++++++++++++ 2 files changed, 129 insertions(+), 1 deletion(-) create mode 100644 packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UserDetailViewAdapterTest.kt diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java index d6dad687e5d47..187a3bdec13fc 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java @@ -76,7 +76,7 @@ public class UserDetailView extends PseudoGridView { UserSwitcherController.UserRecord item) { UserDetailItemView v = UserDetailItemView.convertOrInflate( mContext, convertView, parent); - if ((v != convertView && !item.isCurrent) || item.isGuest) { + if (!item.isCurrent || item.isGuest) { v.setOnClickListener(this); } else { v.setOnClickListener(null); diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UserDetailViewAdapterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UserDetailViewAdapterTest.kt new file mode 100644 index 0000000000000..b51e716591fe4 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UserDetailViewAdapterTest.kt @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2019 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.qs.tiles + +import android.content.Context +import android.content.pm.UserInfo +import android.graphics.Bitmap +import android.testing.AndroidTestingRunner +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.statusbar.policy.UserSwitcherController +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.ArgumentMatchers.any +import org.mockito.ArgumentMatchers.anyBoolean +import org.mockito.ArgumentMatchers.anyInt +import org.mockito.Mock +import org.mockito.Mockito.`when` +import org.mockito.Mockito.verify +import org.mockito.MockitoAnnotations + +@RunWith(AndroidTestingRunner::class) +@SmallTest +class UserDetailViewAdapterTest : SysuiTestCase() { + + @Mock private lateinit var mUserSwitcherController: UserSwitcherController + @Mock private lateinit var mParent: ViewGroup + @Mock private lateinit var mUserDetailItemView: UserDetailItemView + @Mock private lateinit var mOtherView: View + @Mock private lateinit var mInflatedUserDetailItemView: UserDetailItemView + @Mock private lateinit var mUserInfo: UserInfo + @Mock private lateinit var mPicture: Bitmap + @Mock private lateinit var mLayoutInflater: LayoutInflater + private lateinit var adapter: UserDetailView.Adapter + + @Before + fun setUp() { + MockitoAnnotations.initMocks(this) + + mContext.addMockSystemService(Context.LAYOUT_INFLATER_SERVICE, mLayoutInflater) + `when`(mLayoutInflater.inflate(anyInt(), any(ViewGroup::class.java), anyBoolean())) + .thenReturn(mInflatedUserDetailItemView) + adapter = UserDetailView.Adapter(mContext, mUserSwitcherController) + } + + private fun clickableTest( + current: Boolean, + guest: Boolean, + convertView: View, + shouldBeClickable: Boolean + ) { + val user = createUserRecord(current, guest) + val v = adapter.createUserDetailItemView(convertView, mParent, user) + if (shouldBeClickable) { + verify(v).setOnClickListener(adapter) + } else { + verify(v).setOnClickListener(null) + } + } + + @Test + fun testGuestIsClickable_differentViews_notCurrent() { + clickableTest(false, true, mOtherView, true) + } + + @Test + fun testGuestIsClickable_differentViews_Current() { + clickableTest(true, true, mOtherView, true) + } + + @Test + fun testGuestIsClickable_sameView_notCurrent() { + clickableTest(false, true, mUserDetailItemView, true) + } + + @Test + fun testGuestIsClickable_sameView_Current() { + clickableTest(true, true, mUserDetailItemView, true) + } + + @Test + fun testNotGuestCurrentUserIsNotClickable_otherView() { + clickableTest(true, false, mOtherView, false) + } + + @Test + fun testNotGuestCurrentUserIsNotClickable_sameView() { + clickableTest(true, false, mUserDetailItemView, false) + } + + @Test + fun testNotGuestNotCurrentUserIsClickable_otherView() { + clickableTest(false, false, mOtherView, true) + } + + @Test + fun testNotGuestNotCurrentUserIsClickable_sameView() { + clickableTest(false, false, mUserDetailItemView, true) + } + + private fun createUserRecord(current: Boolean, guest: Boolean) = + UserSwitcherController.UserRecord( + mUserInfo, + mPicture, + guest, + current, + false /* isAddUser */, + false /* isRestricted */, + true /* isSwitchToEnabled */) +} \ No newline at end of file From 83a6fc2a43982bbfd606362c80ae28c096e6ff8b Mon Sep 17 00:00:00 2001 From: Fabian Kozynski Date: Wed, 4 Sep 2019 16:53:37 -0400 Subject: [PATCH 17/21] Use UnlockMethodCache#canSkipBouncer in user switcher KeyguardMonitor#canSkipBouncer was not updated properly when the phone was unlocked using fingerprint. This CL removes that method and changes UserSwitcherController to query UnlockMethodCache directly, as it was KeyguardMonitor's only client for that method. Test: manual unlocking with FP and with pattern Test: no automated test yet Bug: 140486529 Merged-In: Idbff4fbabca962c632ff5d78b25418c0502db9a7 Change-Id: Idbff4fbabca962c632ff5d78b25418c0502db9a7 (cherry picked from commit d2eb34b689eaa8a9b064b4e69773083c723e3756) --- .../statusbar/policy/KeyguardMonitor.java | 1 - .../statusbar/policy/KeyguardMonitorImpl.java | 26 ------------------- .../policy/UserSwitcherController.java | 7 +++-- .../utils/leaks/FakeKeyguardMonitor.java | 5 ---- 4 files changed, 5 insertions(+), 34 deletions(-) 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 e1ef809a883c5..6dc90b9028fa6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java @@ -19,7 +19,6 @@ import com.android.systemui.statusbar.policy.KeyguardMonitor.Callback; public interface KeyguardMonitor extends CallbackController { boolean isSecure(); - boolean canSkipBouncer(); boolean isShowing(); boolean isOccluded(); boolean isKeyguardFadingAway(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java index 87ed14a9eeece..26d615c86c29d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java @@ -17,13 +17,11 @@ package com.android.systemui.statusbar.policy; import android.annotation.NonNull; -import android.app.ActivityManager; import android.content.Context; import com.android.internal.util.Preconditions; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.KeyguardUpdateMonitorCallback; -import com.android.systemui.settings.CurrentUserTracker; import java.util.ArrayList; @@ -39,14 +37,11 @@ public class KeyguardMonitorImpl extends KeyguardUpdateMonitorCallback private final ArrayList mCallbacks = new ArrayList<>(); private final Context mContext; - private final CurrentUserTracker mUserTracker; private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; - private int mCurrentUser; private boolean mShowing; private boolean mSecure; private boolean mOccluded; - private boolean mCanSkipBouncer; private boolean mListening; private boolean mKeyguardFadingAway; @@ -62,13 +57,6 @@ public class KeyguardMonitorImpl extends KeyguardUpdateMonitorCallback public KeyguardMonitorImpl(Context context) { mContext = context; mKeyguardUpdateMonitor = KeyguardUpdateMonitor.getInstance(mContext); - mUserTracker = new CurrentUserTracker(mContext) { - @Override - public void onUserSwitched(int newUserId) { - mCurrentUser = newUserId; - updateCanSkipBouncerState(); - } - }; } @Override @@ -77,10 +65,7 @@ public class KeyguardMonitorImpl extends KeyguardUpdateMonitorCallback mCallbacks.add(callback); if (mCallbacks.size() != 0 && !mListening) { mListening = true; - mCurrentUser = ActivityManager.getCurrentUser(); - updateCanSkipBouncerState(); mKeyguardUpdateMonitor.registerCallback(this); - mUserTracker.startTracking(); } } @@ -90,7 +75,6 @@ public class KeyguardMonitorImpl extends KeyguardUpdateMonitorCallback if (mCallbacks.remove(callback) && mCallbacks.size() == 0 && mListening) { mListening = false; mKeyguardUpdateMonitor.removeCallback(this); - mUserTracker.stopTracking(); } } @@ -109,11 +93,6 @@ public class KeyguardMonitorImpl extends KeyguardUpdateMonitorCallback return mOccluded; } - @Override - public boolean canSkipBouncer() { - return mCanSkipBouncer; - } - public void notifyKeyguardState(boolean showing, boolean secure, boolean occluded) { if (mShowing == showing && mSecure == secure && mOccluded == occluded) return; mShowing = showing; @@ -124,7 +103,6 @@ public class KeyguardMonitorImpl extends KeyguardUpdateMonitorCallback @Override public void onTrustChanged(int userId) { - updateCanSkipBouncerState(); notifyKeyguardChanged(); } @@ -132,10 +110,6 @@ public class KeyguardMonitorImpl extends KeyguardUpdateMonitorCallback return mKeyguardUpdateMonitor.isDeviceInteractive(); } - private void updateCanSkipBouncerState() { - mCanSkipBouncer = mKeyguardUpdateMonitor.getUserCanSkipBouncer(mCurrentUser); - } - private void notifyKeyguardChanged() { // Copy the list to allow removal during callback. new ArrayList<>(mCallbacks).forEach(Callback::onKeyguardShowingChanged); 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 395add76dda49..35e3923f285b3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java @@ -61,6 +61,7 @@ import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.qs.DetailAdapter; import com.android.systemui.qs.tiles.UserDetailView; import com.android.systemui.statusbar.phone.SystemUIDialog; +import com.android.systemui.statusbar.phone.UnlockMethodCache; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -595,17 +596,19 @@ public class UserSwitcherController implements Dumpable { final UserSwitcherController mController; private final KeyguardMonitor mKeyguardMonitor; + private final UnlockMethodCache mUnlockMethodCache; protected BaseUserAdapter(UserSwitcherController controller) { mController = controller; mKeyguardMonitor = controller.mKeyguardMonitor; + mUnlockMethodCache = UnlockMethodCache.getInstance(controller.mContext); controller.addAdapter(new WeakReference<>(this)); } public int getUserCount() { boolean secureKeyguardShowing = mKeyguardMonitor.isShowing() && mKeyguardMonitor.isSecure() - && !mKeyguardMonitor.canSkipBouncer(); + && !mUnlockMethodCache.canSkipBouncer(); if (!secureKeyguardShowing) { return mController.getUsers().size(); } @@ -627,7 +630,7 @@ public class UserSwitcherController implements Dumpable { public int getCount() { boolean secureKeyguardShowing = mKeyguardMonitor.isShowing() && mKeyguardMonitor.isSecure() - && !mKeyguardMonitor.canSkipBouncer(); + && !mUnlockMethodCache.canSkipBouncer(); if (!secureKeyguardShowing) { return mController.getUsers().size(); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeKeyguardMonitor.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeKeyguardMonitor.java index 95c7a4d09f928..2fb0e0e7caf8c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeKeyguardMonitor.java +++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeKeyguardMonitor.java @@ -80,9 +80,4 @@ public class FakeKeyguardMonitor implements KeyguardMonitor { public long calculateGoingToFullShadeDelay() { return 0; } - - @Override - public boolean canSkipBouncer() { - return false; - } } From d09b2769844eb9d749b1b68ac33ac459e817361f Mon Sep 17 00:00:00 2001 From: Seigo Nonaka Date: Fri, 6 Sep 2019 16:34:07 -0700 Subject: [PATCH 18/21] don't compute outside of visible range Bug: 140632678 Test: manually done Test: TreeHugger Change-Id: I646851973b3816bf9ba32dfe26748c0345a5a081 (cherry picked from commit 0a57fe099a55ab3a7583b229fa7cfb905d6106f3) --- core/java/android/text/TextLine.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core/java/android/text/TextLine.java b/core/java/android/text/TextLine.java index 86651060a3946..5a2d8f4329dca 100644 --- a/core/java/android/text/TextLine.java +++ b/core/java/android/text/TextLine.java @@ -276,6 +276,7 @@ public class TextLine { final int runCount = mDirections.getRunCount(); for (int runIndex = 0; runIndex < runCount; runIndex++) { final int runStart = mDirections.getRunStart(runIndex); + if (runStart >= mLen) break; final int runLimit = Math.min(runStart + mDirections.getRunLength(runIndex), mLen); final boolean runIsRtl = mDirections.isRunRtl(runIndex); @@ -360,6 +361,7 @@ public class TextLine { float h = 0; for (int runIndex = 0; runIndex < mDirections.getRunCount(); runIndex++) { final int runStart = mDirections.getRunStart(runIndex); + if (runStart >= mLen) break; final int runLimit = Math.min(runStart + mDirections.getRunLength(runIndex), mLen); final boolean runIsRtl = mDirections.isRunRtl(runIndex); @@ -417,6 +419,7 @@ public class TextLine { float h = 0; for (int runIndex = 0; runIndex < mDirections.getRunCount(); runIndex++) { final int runStart = mDirections.getRunStart(runIndex); + if (runStart > mLen) break; final int runLimit = Math.min(runStart + mDirections.getRunLength(runIndex), mLen); final boolean runIsRtl = mDirections.isRunRtl(runIndex); From 4a55d31999135e92eef204da1e01c89636088003 Mon Sep 17 00:00:00 2001 From: Adam Seaton Date: Fri, 13 Sep 2019 22:08:30 +0000 Subject: [PATCH 19/21] Revert "don't compute outside of visible range" bug:141016653 This reverts commit 0a57fe099a55ab3a7583b229fa7cfb905d6106f3. Reason for revert: CL is implicated in https://b.corp.google.com/issues/141016653 Change-Id: I39954226cb8971ee17e367692b3fd0e29871ad48 (cherry picked from commit b4583e4dcd316a1e5b417b2112a51b5bd7ac982a) --- core/java/android/text/TextLine.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/core/java/android/text/TextLine.java b/core/java/android/text/TextLine.java index 5a2d8f4329dca..86651060a3946 100644 --- a/core/java/android/text/TextLine.java +++ b/core/java/android/text/TextLine.java @@ -276,7 +276,6 @@ public class TextLine { final int runCount = mDirections.getRunCount(); for (int runIndex = 0; runIndex < runCount; runIndex++) { final int runStart = mDirections.getRunStart(runIndex); - if (runStart >= mLen) break; final int runLimit = Math.min(runStart + mDirections.getRunLength(runIndex), mLen); final boolean runIsRtl = mDirections.isRunRtl(runIndex); @@ -361,7 +360,6 @@ public class TextLine { float h = 0; for (int runIndex = 0; runIndex < mDirections.getRunCount(); runIndex++) { final int runStart = mDirections.getRunStart(runIndex); - if (runStart >= mLen) break; final int runLimit = Math.min(runStart + mDirections.getRunLength(runIndex), mLen); final boolean runIsRtl = mDirections.isRunRtl(runIndex); @@ -419,7 +417,6 @@ public class TextLine { float h = 0; for (int runIndex = 0; runIndex < mDirections.getRunCount(); runIndex++) { final int runStart = mDirections.getRunStart(runIndex); - if (runStart > mLen) break; final int runLimit = Math.min(runStart + mDirections.getRunLength(runIndex), mLen); final boolean runIsRtl = mDirections.isRunRtl(runIndex); From c341e4c8fcf35719a94e696d2414bd437836b402 Mon Sep 17 00:00:00 2001 From: Seigo Nonaka Date: Mon, 16 Sep 2019 14:49:49 -0700 Subject: [PATCH 20/21] Do not compute outside given range in TextLine This is second attempt of I646851973b3816bf9ba32dfe26748c0345a5a081 which breaks various layout test on application. The empty string must be also handled by the TextLine since it retrieves the default line height from the empty string. Bug: 140632678 Test: StaticLayoutTest Test: Manually done Change-Id: I7089ed9b711dddd7de2b27c9c2fa0fb4cb53a735 (cherry picked from commit 7c38cafc22e9ac7a023b9680b4f98a5fd8306777) --- core/java/android/text/TextLine.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core/java/android/text/TextLine.java b/core/java/android/text/TextLine.java index 86651060a3946..1c50d73c49533 100644 --- a/core/java/android/text/TextLine.java +++ b/core/java/android/text/TextLine.java @@ -276,6 +276,7 @@ public class TextLine { final int runCount = mDirections.getRunCount(); for (int runIndex = 0; runIndex < runCount; runIndex++) { final int runStart = mDirections.getRunStart(runIndex); + if (runStart > mLen) break; final int runLimit = Math.min(runStart + mDirections.getRunLength(runIndex), mLen); final boolean runIsRtl = mDirections.isRunRtl(runIndex); @@ -360,6 +361,7 @@ public class TextLine { float h = 0; for (int runIndex = 0; runIndex < mDirections.getRunCount(); runIndex++) { final int runStart = mDirections.getRunStart(runIndex); + if (runStart > mLen) break; final int runLimit = Math.min(runStart + mDirections.getRunLength(runIndex), mLen); final boolean runIsRtl = mDirections.isRunRtl(runIndex); @@ -417,6 +419,7 @@ public class TextLine { float h = 0; for (int runIndex = 0; runIndex < mDirections.getRunCount(); runIndex++) { final int runStart = mDirections.getRunStart(runIndex); + if (runStart > mLen) break; final int runLimit = Math.min(runStart + mDirections.getRunLength(runIndex), mLen); final boolean runIsRtl = mDirections.isRunRtl(runIndex); From 438c04e55c0a7d0763b26f0d102ef8e522c29bfe Mon Sep 17 00:00:00 2001 From: Evan Laird Date: Wed, 18 Sep 2019 20:09:34 +0000 Subject: [PATCH 21/21] DO NOT MERGE: Revert "Force FGS notifications to show for a minimum time" This reverts commit 09843a687bc19f8e360b2f5b0493a1f378bb603b. Reason for revert: There is possible reentrant behavior when posting the safeToRemove callback after a FGS has been canceled/reposted Bug: 140948482 Change-Id: I2c5b9135e57a87f412dce8c167147dcb38f6bbae (cherry picked from commit 7c6df8dad1c7c45a95b889429cf45dd0fa6bf3c5) --- ...ForegroundServiceNotificationListener.java | 70 --------------- .../NotificationLifetimeExtender.java | 12 --- .../NotificationEntryManager.java | 20 +---- .../phone/StatusBarNotificationPresenter.java | 2 +- ...groundServiceNotificationListenerTest.java | 86 ------------------- .../NotificationManagerService.java | 12 +-- .../NotificationManagerServiceTest.java | 14 --- 7 files changed, 6 insertions(+), 210 deletions(-) delete mode 100644 packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceNotificationListenerTest.java diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java b/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java index 46e08661cd707..96b62ac918ab4 100644 --- a/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java +++ b/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java @@ -16,20 +16,14 @@ package com.android.systemui; -import android.annotation.NonNull; import android.app.Notification; import android.app.NotificationManager; import android.content.Context; import android.os.Bundle; -import android.os.Handler; -import android.os.Looper; import android.service.notification.StatusBarNotification; -import android.util.ArraySet; import android.util.Log; -import com.android.internal.annotations.VisibleForTesting; import com.android.internal.statusbar.NotificationVisibility; -import com.android.systemui.statusbar.NotificationLifetimeExtender; import com.android.systemui.statusbar.notification.NotificationEntryListener; import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; @@ -72,9 +66,6 @@ public class ForegroundServiceNotificationListener { removeNotification(entry.notification); } }); - - notificationEntryManager.addNotificationLifetimeExtender( - new ForegroundServiceNotificationListener.ForegroundServiceLifetimeExtender()); } /** @@ -153,65 +144,4 @@ public class ForegroundServiceNotificationListener { }, true /* create if not found */); } - - /** - * Extends the lifetime of foreground notification services such that they show for at least - * five seconds - */ - public static class ForegroundServiceLifetimeExtender implements NotificationLifetimeExtender { - - private static final String TAG = "FGSLifetimeExtender"; - @VisibleForTesting - static final int MIN_FGS_TIME_MS = 5000; - - private NotificationSafeToRemoveCallback mNotificationSafeToRemoveCallback; - private ArraySet mManagedEntries = new ArraySet<>(); - private Handler mHandler = new Handler(Looper.getMainLooper()); - - public ForegroundServiceLifetimeExtender() { - } - - @Override - public void setCallback(@NonNull NotificationSafeToRemoveCallback callback) { - mNotificationSafeToRemoveCallback = callback; - } - - @Override - public boolean shouldExtendLifetime(@NonNull NotificationEntry entry) { - if ((entry.notification.getNotification().flags - & Notification.FLAG_FOREGROUND_SERVICE) == 0) { - return false; - } - - long currentTime = System.currentTimeMillis(); - return currentTime - entry.notification.getPostTime() < MIN_FGS_TIME_MS; - } - - @Override - public boolean shouldExtendLifetimeForPendingNotification( - @NonNull NotificationEntry entry) { - return shouldExtendLifetime(entry); - } - - @Override - public void setShouldManageLifetime( - @NonNull NotificationEntry entry, boolean shouldManage) { - if (!shouldManage) { - mManagedEntries.remove(entry); - return; - } - - mManagedEntries.add(entry); - - Runnable r = () -> { - if (mManagedEntries.contains(entry)) { - if (mNotificationSafeToRemoveCallback != null) { - mNotificationSafeToRemoveCallback.onSafeToRemove(entry.key); - } - mManagedEntries.remove(entry); - } - }; - mHandler.postDelayed(r, MIN_FGS_TIME_MS); - } - } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLifetimeExtender.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLifetimeExtender.java index 48e2923c97d99..0f295ba75fe40 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLifetimeExtender.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLifetimeExtender.java @@ -26,18 +26,6 @@ public interface NotificationLifetimeExtender { */ boolean shouldExtendLifetime(@NonNull NotificationEntry entry); - /** - * It's possible that a notification was canceled before it ever became visible. This callback - * gives lifetime extenders a chance to make sure it shows up. For example if a foreground - * service is canceled too quickly but we still want to make sure a FGS notification shows. - * @param pendingEntry the canceled (but pending) entry - * @return true if the notification lifetime should be extended - */ - default boolean shouldExtendLifetimeForPendingNotification( - @NonNull NotificationEntry pendingEntry) { - return false; - } - /** * Sets whether or not the lifetime should be managed by the extender. In practice, if * shouldManage is true, this is where the extender starts managing the entry internally and is diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java index a37367e4bb255..f8fef7d4778c8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java @@ -281,25 +281,11 @@ public class NotificationEntryManager implements } final NotificationEntry entry = mNotificationData.get(key); + + abortExistingInflation(key); + boolean lifetimeExtended = false; - // Notification was canceled before it got inflated - if (entry == null) { - NotificationEntry pendingEntry = mPendingNotifications.get(key); - if (pendingEntry != null) { - for (NotificationLifetimeExtender extender : mNotificationLifetimeExtenders) { - if (extender.shouldExtendLifetimeForPendingNotification(pendingEntry)) { - extendLifetime(pendingEntry, extender); - lifetimeExtended = true; - } - } - } - } - - if (!lifetimeExtended) { - abortExistingInflation(key); - } - if (entry != null) { // If a manager needs to keep the notification around for whatever reason, we // keep the notification diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java index 069219802cc3d..a870590c08ac7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java @@ -224,7 +224,7 @@ public class StatusBarNotificationPresenter implements NotificationPresenter, mVisualStabilityManager.setUpWithPresenter(this); mGutsManager.setUpWithPresenter(this, notifListContainer, mCheckSaveListener, mOnSettingsClickListener); - // ForegroundServiceNotificationListener adds its listener in its constructor + // ForegroundServiceControllerListener adds its listener in its constructor // but we need to request it here in order for it to be instantiated. // TODO: figure out how to do this correctly once Dependency.get() is gone. Dependency.get(ForegroundServiceNotificationListener.class); diff --git a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceNotificationListenerTest.java b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceNotificationListenerTest.java deleted file mode 100644 index 72a457e9bbbee..0000000000000 --- a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceNotificationListenerTest.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (C) 2019 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 static com.android.systemui.ForegroundServiceNotificationListener.ForegroundServiceLifetimeExtender.MIN_FGS_TIME_MS; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import android.app.Notification; -import android.service.notification.StatusBarNotification; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import com.android.systemui.statusbar.notification.collection.NotificationEntry; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class ForegroundServiceNotificationListenerTest extends SysuiTestCase { - private ForegroundServiceNotificationListener.ForegroundServiceLifetimeExtender mExtender = - new ForegroundServiceNotificationListener.ForegroundServiceLifetimeExtender(); - private StatusBarNotification mSbn; - private NotificationEntry mEntry; - private Notification mNotif; - - @Before - public void setup() { - mNotif = new Notification.Builder(mContext, "") - .setSmallIcon(R.drawable.ic_person) - .setContentTitle("Title") - .setContentText("Text") - .build(); - - mSbn = mock(StatusBarNotification.class); - when(mSbn.getNotification()).thenReturn(mNotif); - - mEntry = new NotificationEntry(mSbn); - } - - /** - * ForegroundServiceLifetimeExtenderTest - */ - @Test - public void testShouldExtendLifetime_should_foreground() { - // Extend the lifetime of a FGS notification iff it has not been visible - // for the minimum time - mNotif.flags |= Notification.FLAG_FOREGROUND_SERVICE; - when(mSbn.getPostTime()).thenReturn(System.currentTimeMillis()); - assertTrue(mExtender.shouldExtendLifetime(mEntry)); - } - - @Test - public void testShouldExtendLifetime_shouldNot_foreground() { - mNotif.flags |= Notification.FLAG_FOREGROUND_SERVICE; - when(mSbn.getPostTime()).thenReturn(System.currentTimeMillis() - MIN_FGS_TIME_MS - 1); - assertFalse(mExtender.shouldExtendLifetime(mEntry)); - } - - @Test - public void testShouldExtendLifetime_shouldNot_notForeground() { - mNotif.flags = 0; - when(mSbn.getPostTime()).thenReturn(System.currentTimeMillis() - MIN_FGS_TIME_MS - 1); - assertFalse(mExtender.shouldExtendLifetime(mEntry)); - } -} diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 3eb442f9bdda1..c8d0682437885 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -5343,16 +5343,8 @@ public class NotificationManagerService extends SystemService { } synchronized (mNotificationLock) { - // If the notification is currently enqueued, repost this runnable so it has a - // chance to notify listeners - if ((findNotificationByListLocked(mEnqueuedNotifications, mPkg, mTag, mId, mUserId)) - != null) { - mHandler.post(this); - return; - } - // Look for the notification in the posted list, since we already checked enqueued. - NotificationRecord r = - findNotificationByListLocked(mNotificationList, mPkg, mTag, mId, mUserId); + // Look for the notification, searching both the posted and enqueued lists. + NotificationRecord r = findNotificationLocked(mPkg, mTag, mId, mUserId); if (r != null) { // The notification was found, check if it should be removed. diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java index 6c91e2f52f0c5..dc5edcd815861 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java @@ -1016,20 +1016,6 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { assertEquals(0, mService.getNotificationRecordCount()); } - @Test - public void testCancelImmediatelyAfterEnqueueNotifiesListeners_ForegroundServiceFlag() - throws Exception { - final StatusBarNotification sbn = generateNotificationRecord(null).sbn; - sbn.getNotification().flags = - Notification.FLAG_ONGOING_EVENT | FLAG_FOREGROUND_SERVICE; - mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", - sbn.getId(), sbn.getNotification(), sbn.getUserId()); - mBinderService.cancelNotificationWithTag(PKG, "tag", sbn.getId(), sbn.getUserId()); - waitForIdle(); - verify(mListeners, times(1)).notifyPostedLocked(any(), any()); - verify(mListeners, times(1)).notifyRemovedLocked(any(), anyInt(), any()); - } - @Test public void testUserInitiatedClearAll_noLeak() throws Exception { final NotificationRecord n = generateNotificationRecord(