Merge "Import translations. DO NOT MERGE ANYWHERE"
diff --git a/api/test-current.txt b/api/test-current.txt
index 529dcf7..5741fe7 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -5579,7 +5579,7 @@
method @BinderThread public void onTaskInfoChanged(@NonNull android.app.ActivityManager.RunningTaskInfo);
method @BinderThread public void onTaskVanished(@NonNull android.app.ActivityManager.RunningTaskInfo);
method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public final void registerOrganizer();
- method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public void setInterceptBackPressedOnTaskRoot(boolean);
+ method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public void setInterceptBackPressedOnTaskRoot(@NonNull android.window.WindowContainerToken, boolean);
method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public static void setLaunchRoot(int, @NonNull android.window.WindowContainerToken);
method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public final void unregisterOrganizer();
}
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index cee607f..fef8d10 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -1924,10 +1924,8 @@
@Override
public Object getSystemService(String name) {
if (vmIncorrectContextUseEnabled()) {
- // We may override this API from outer context.
- final boolean isUiContext = isUiContext() || isOuterUiContext();
// Check incorrect Context usage.
- if (isUiComponent(name) && !isUiContext) {
+ if (isUiComponent(name) && !isSelfOrOuterUiContext()) {
final String errorMessage = "Tried to access visual service "
+ SystemServiceRegistry.getSystemServiceClassName(name)
+ " from a non-visual Context:" + getOuterContext();
@@ -1944,15 +1942,17 @@
return SystemServiceRegistry.getSystemService(this, name);
}
- private boolean isOuterUiContext() {
- return getOuterContext() != null && getOuterContext().isUiContext();
- }
-
@Override
public String getSystemServiceName(Class<?> serviceClass) {
return SystemServiceRegistry.getSystemServiceName(serviceClass);
}
+ // TODO(b/149463653): check if we still need this method after migrating IMS to WindowContext.
+ private boolean isSelfOrOuterUiContext() {
+ // We may override outer context's isUiContext
+ return isUiContext() || getOuterContext() != null && getOuterContext().isUiContext();
+ }
+
/** @hide */
@Override
public boolean isUiContext() {
@@ -2413,7 +2413,7 @@
context.setResources(createResources(mToken, mPackageInfo, mSplitName, overrideDisplayId,
overrideConfiguration, getDisplayAdjustments(displayId).getCompatibilityInfo(),
mResources.getLoaders()));
- context.mIsUiContext = isUiContext() || isOuterUiContext();
+ context.mIsUiContext = isSelfOrOuterUiContext();
return context;
}
@@ -2529,9 +2529,9 @@
@Override
public Display getDisplay() {
- if (!mIsSystemOrSystemUiContext && !mIsAssociatedWithDisplay) {
+ if (!mIsSystemOrSystemUiContext && !mIsAssociatedWithDisplay && !isSelfOrOuterUiContext()) {
throw new UnsupportedOperationException("Tried to obtain display from a Context not "
- + "associated with one. Only visual Contexts (such as Activity or one created "
+ + "associated with one. Only visual Contexts (such as Activity or one created "
+ "with Context#createWindowContext) or ones created with "
+ "Context#createDisplayContext are associated with displays. Other types of "
+ "Contexts are typically related to background entities and may return an "
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index c61426d..98de85d 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -9751,21 +9751,6 @@
}
/**
- * @hide
- * Return if this user is a system-only user. An admin can manage a device from a system only
- * user by calling {@link #ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE}.
- * @param admin Which device owner this request is associated with.
- * @return if this user is a system-only user.
- */
- public boolean isSystemOnlyUser(@NonNull ComponentName admin) {
- try {
- return mService.isSystemOnlyUser(admin);
- } catch (RemoteException re) {
- throw re.rethrowFromSystemServer();
- }
- }
-
- /**
* Called by device owner, or profile owner on organization-owned device, to get the MAC
* address of the Wi-Fi device.
*
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 9c6a274..1c7b617 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -345,7 +345,6 @@
void setKeepUninstalledPackages(in ComponentName admin, in String callerPackage, in List<String> packageList);
List<String> getKeepUninstalledPackages(in ComponentName admin, in String callerPackage);
boolean isManagedProfile(in ComponentName admin);
- boolean isSystemOnlyUser(in ComponentName admin);
String getWifiMacAddress(in ComponentName admin);
void reboot(in ComponentName admin);
diff --git a/core/java/android/companion/TEST_MAPPING b/core/java/android/companion/TEST_MAPPING
new file mode 100644
index 0000000..63f54fa
--- /dev/null
+++ b/core/java/android/companion/TEST_MAPPING
@@ -0,0 +1,12 @@
+{
+ "presubmit": [
+ {
+ "name": "CtsOsTestCases",
+ "options": [
+ {
+ "include-filter": "android.os.cts.CompanionDeviceManagerTest"
+ }
+ ]
+ }
+ ]
+}
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index da8d15a..d672c6a 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -788,7 +788,6 @@
INSTALL_ENABLE_ROLLBACK,
INSTALL_ALLOW_DOWNGRADE,
INSTALL_STAGED,
- INSTALL_DRY_RUN,
})
@Retention(RetentionPolicy.SOURCE)
public @interface InstallFlags {}
@@ -966,14 +965,6 @@
*/
public static final int INSTALL_STAGED = 0x00200000;
- /**
- * Flag parameter for {@link #installPackage} to indicate that package should only be verified
- * but not installed.
- *
- * @hide
- */
- public static final int INSTALL_DRY_RUN = 0x00800000;
-
/** @hide */
@IntDef(flag = true, value = {
DONT_KILL_APP,
diff --git a/core/java/android/content/pm/RegisteredServicesCache.java b/core/java/android/content/pm/RegisteredServicesCache.java
index bd909c7..192470e 100644
--- a/core/java/android/content/pm/RegisteredServicesCache.java
+++ b/core/java/android/content/pm/RegisteredServicesCache.java
@@ -43,11 +43,11 @@
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastXmlSerializer;
-import libcore.io.IoUtils;
-
import com.google.android.collect.Lists;
import com.google.android.collect.Maps;
+import libcore.io.IoUtils;
+
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
@@ -793,7 +793,7 @@
@VisibleForTesting
protected List<UserInfo> getUsers() {
- return UserManager.get(mContext).getUsers(true);
+ return UserManager.get(mContext).getAliveUsers();
}
@VisibleForTesting
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 7250801..55afefe 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -1210,15 +1210,19 @@
mWindow.getWindow().getAttributes().setFitInsetsIgnoringVisibility(true);
// IME layout should always be inset by navigation bar, no matter its current visibility,
- // unless automotive requests it, since automotive may hide the navigation bar.
+ // unless automotive requests it. Automotive devices may request the navigation bar to be
+ // hidden when the IME shows up (controlled via config_automotiveHideNavBarForKeyboard)
+ // in order to maximize the visible screen real estate. When this happens, the IME window
+ // should animate from the bottom of the screen to reduce the jank that happens from the
+ // lack of synchronization between the bottom system window and the IME window.
+ if (mIsAutomotive && mAutomotiveHideNavBarForKeyboard) {
+ mWindow.getWindow().setDecorFitsSystemWindows(false);
+ }
mWindow.getWindow().getDecorView().setOnApplyWindowInsetsListener(
(v, insets) -> v.onApplyWindowInsets(
new WindowInsets.Builder(insets).setInsets(
navigationBars(),
- mIsAutomotive && mAutomotiveHideNavBarForKeyboard
- ? android.graphics.Insets.NONE
- : insets.getInsetsIgnoringVisibility(navigationBars())
- )
+ insets.getInsetsIgnoringVisibility(navigationBars()))
.build()));
// For ColorView in DecorView to work, FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS needs to be set
diff --git a/core/java/android/inputmethodservice/TEST_MAPPING b/core/java/android/inputmethodservice/TEST_MAPPING
new file mode 100644
index 0000000..0ccd75d
--- /dev/null
+++ b/core/java/android/inputmethodservice/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "imports": [
+ {
+ "path": "frameworks/base/core/java/android/view/inputmethod"
+ }
+ ]
+}
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 81a147c..81ffefd 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -1293,7 +1293,7 @@
* in {@link UserManager} & {@link DevicePolicyManager}.
* Note: This is slightly different from the real set of user restrictions listed in {@link
* com.android.server.pm.UserRestrictionsUtils#USER_RESTRICTIONS}. For example
- * {@link #KEY_RESTRICTIONS_PENDING} is not a real user restriction, but is a a legitimate
+ * {@link #KEY_RESTRICTIONS_PENDING} is not a real user restriction, but is a legitimate
* value that can be passed into {@link #hasUserRestriction(String)}.
* @hide
*/
@@ -3252,7 +3252,8 @@
@SystemApi
@RequiresPermission(android.Manifest.permission.MANAGE_USERS)
public @NonNull List<UserHandle> getUserHandles(boolean excludeDying) {
- List<UserInfo> users = getUsers(excludeDying);
+ List<UserInfo> users = getUsers(/* excludePartial= */ true, excludeDying,
+ /* excludePreCreated= */ true);
List<UserHandle> result = new ArrayList<>(users.size());
for (UserInfo user : users) {
result.add(user.getUserHandle());
@@ -3270,7 +3271,8 @@
@SystemApi
@RequiresPermission(android.Manifest.permission.MANAGE_USERS)
public long[] getSerialNumbersOfUsers(boolean excludeDying) {
- List<UserInfo> users = getUsers(excludeDying);
+ List<UserInfo> users = getUsers(/* excludePartial= */ true, excludeDying,
+ /* excludePreCreated= */ true);
long[] result = new long[users.size()];
for (int i = 0; i < result.length; i++) {
result[i] = users.get(i).serialNumber;
@@ -3336,7 +3338,7 @@
public boolean canAddMoreUsers() {
// TODO(b/142482943): UMS has different logic, excluding Demo and Profile from counting. Why
// not here? The logic is inconsistent. See UMS.canAddMoreManagedProfiles
- final List<UserInfo> users = getUsers(true);
+ final List<UserInfo> users = getAliveUsers();
final int totalUserCount = users.size();
int aliveUserCount = 0;
for (int i = 0; i < totalUserCount; i++) {
@@ -4144,7 +4146,7 @@
/** Returns whether there are any users (other than the current user) to which to switch. */
private boolean areThereUsersToWhichToSwitch() {
- final List<UserInfo> users = getUsers(true);
+ final List<UserInfo> users = getAliveUsers();
if (users == null) {
return false;
}
diff --git a/core/java/android/os/incremental/IIncrementalService.aidl b/core/java/android/os/incremental/IIncrementalService.aidl
index be8b929..f351c7d 100644
--- a/core/java/android/os/incremental/IIncrementalService.aidl
+++ b/core/java/android/os/incremental/IIncrementalService.aidl
@@ -90,6 +90,14 @@
int unlink(int storageId, in @utf8InCpp String path);
/**
+ * Checks if a file is fully loaded. File is specified by its path.
+ * 0 - fully loaded
+ * >0 - certain pages missing
+ * <0 - -errcode
+ */
+ int isFileFullyLoaded(int storageId, in @utf8InCpp String path);
+
+ /**
* Returns overall loading progress of all the files on a storage, progress value between [0,1].
* Returns a negative value on error.
*/
diff --git a/core/java/android/os/incremental/IncrementalStorage.java b/core/java/android/os/incremental/IncrementalStorage.java
index b8dbfbb..ed386f7 100644
--- a/core/java/android/os/incremental/IncrementalStorage.java
+++ b/core/java/android/os/incremental/IncrementalStorage.java
@@ -304,6 +304,25 @@
}
/**
+ * Checks whether a file under the current storage directory is fully loaded.
+ *
+ * @param path The relative path of the file.
+ * @return True if the file is fully loaded.
+ */
+ public boolean isFileFullyLoaded(@NonNull String path) throws IOException {
+ try {
+ int res = mService.isFileFullyLoaded(mId, path);
+ if (res < 0) {
+ throw new IOException("isFileFullyLoaded() failed, errno " + -res);
+ }
+ return res == 0;
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ return false;
+ }
+ }
+
+ /**
* Returns the loading progress of a storage
*
* @return progress value between [0, 1].
diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java
index 276f162..c3b6d8e 100644
--- a/core/java/android/provider/CallLog.java
+++ b/core/java/android/provider/CallLog.java
@@ -870,7 +870,7 @@
// Otherwise, insert to all other users that are running and unlocked.
- final List<UserInfo> users = userManager.getUsers(true);
+ final List<UserInfo> users = userManager.getAliveUsers();
final int count = users.size();
for (int i = 0; i < count; i++) {
diff --git a/core/java/android/provider/DocumentsProvider.java b/core/java/android/provider/DocumentsProvider.java
index 327bca2..d55fc51 100644
--- a/core/java/android/provider/DocumentsProvider.java
+++ b/core/java/android/provider/DocumentsProvider.java
@@ -218,8 +218,15 @@
}
/** {@hide} */
- private void enforceTree(Uri documentUri) {
- if (isTreeUri(documentUri)) {
+ private void enforceTreeForExtraUris(Bundle extras) {
+ enforceTree(extras.getParcelable(DocumentsContract.EXTRA_URI));
+ enforceTree(extras.getParcelable(DocumentsContract.EXTRA_PARENT_URI));
+ enforceTree(extras.getParcelable(DocumentsContract.EXTRA_TARGET_URI));
+ }
+
+ /** {@hide} */
+ private void enforceTree(@Nullable Uri documentUri) {
+ if (documentUri != null && isTreeUri(documentUri)) {
final String parent = getTreeDocumentId(documentUri);
final String child = getDocumentId(documentUri);
if (Objects.equals(parent, child)) {
@@ -1076,6 +1083,9 @@
final Context context = getContext();
final Bundle out = new Bundle();
+ // If the URI is a tree URI performs some validation.
+ enforceTreeForExtraUris(extras);
+
if (METHOD_EJECT_ROOT.equals(method)) {
// Given that certain system apps can hold MOUNT_UNMOUNT permission, but only apps
// signed with platform signature can hold MANAGE_DOCUMENTS, we are going to check for
@@ -1099,9 +1109,6 @@
"Requested authority " + authority + " doesn't match provider " + mAuthority);
}
- // If the URI is a tree URI performs some validation.
- enforceTree(documentUri);
-
if (METHOD_IS_CHILD_DOCUMENT.equals(method)) {
enforceReadPermissionInner(documentUri, getCallingPackage(),
getCallingAttributionTag(), null);
diff --git a/core/java/android/telephony/PhoneStateListener.java b/core/java/android/telephony/PhoneStateListener.java
index b807180..cbc304b 100644
--- a/core/java/android/telephony/PhoneStateListener.java
+++ b/core/java/android/telephony/PhoneStateListener.java
@@ -950,10 +950,6 @@
* This method will be called when an emergency call is placed on any subscription (including
* the no-SIM case), regardless of which subscription this listener was registered on.
*
- * This method is deprecated. Both this method and the new
- * {@link #onOutgoingEmergencyCall(EmergencyNumber, int)} will be called when an outgoing
- * emergency call is placed.
- *
* @param placedEmergencyNumber The {@link EmergencyNumber} the emergency call was placed to.
*
* @deprecated Use {@link #onOutgoingEmergencyCall(EmergencyNumber, int)}.
@@ -972,22 +968,24 @@
* This method will be called when an emergency call is placed on any subscription (including
* the no-SIM case), regardless of which subscription this listener was registered on.
*
- * Both this method and the deprecated {@link #onOutgoingEmergencyCall(EmergencyNumber)} will be
- * called when an outgoing emergency call is placed. You should only implement one of these
- * methods.
+ * The default implementation of this method calls
+ * {@link #onOutgoingEmergencyCall(EmergencyNumber)} for backwards compatibility purposes. Do
+ * not call {@code super(...)} from within your implementation unless you want
+ * {@link #onOutgoingEmergencyCall(EmergencyNumber)} to be called as well.
*
* @param placedEmergencyNumber The {@link EmergencyNumber} the emergency call was placed to.
* @param subscriptionId The subscription ID used to place the emergency call. If the
* emergency call was placed without a valid subscription (e.g. when there
* are no SIM cards in the device), this will be equal to
* {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID}.
- *
* @hide
*/
@SystemApi
@TestApi
public void onOutgoingEmergencyCall(@NonNull EmergencyNumber placedEmergencyNumber,
int subscriptionId) {
+ // Default implementation for backwards compatibility
+ onOutgoingEmergencyCall(placedEmergencyNumber);
}
/**
@@ -1375,10 +1373,6 @@
Binder.withCleanCallingIdentity(
() -> mExecutor.execute(
- () -> psl.onOutgoingEmergencyCall(placedEmergencyNumber)));
-
- Binder.withCleanCallingIdentity(
- () -> mExecutor.execute(
() -> psl.onOutgoingEmergencyCall(placedEmergencyNumber,
subscriptionId)));
}
diff --git a/core/java/android/view/FrameMetrics.java b/core/java/android/view/FrameMetrics.java
index 054dff7..32cc30be8 100644
--- a/core/java/android/view/FrameMetrics.java
+++ b/core/java/android/view/FrameMetrics.java
@@ -250,8 +250,11 @@
Index.INTENDED_VSYNC, Index.FRAME_COMPLETED,
};
+ /**
+ * @hide
+ */
@UnsupportedAppUsage
- /* package */ final long[] mTimingData;
+ public final long[] mTimingData;
/**
* Constructs a FrameMetrics object as a copy.
@@ -270,7 +273,7 @@
/**
* @hide
*/
- FrameMetrics() {
+ public FrameMetrics() {
mTimingData = new long[Index.FRAME_STATS_COUNT];
}
diff --git a/core/java/android/view/inputmethod/TEST_MAPPING b/core/java/android/view/inputmethod/TEST_MAPPING
new file mode 100644
index 0000000..4b2ea1a
--- /dev/null
+++ b/core/java/android/view/inputmethod/TEST_MAPPING
@@ -0,0 +1,18 @@
+{
+ "presubmit": [
+ {
+ "name": "CtsAutoFillServiceTestCases",
+ "options": [
+ {
+ "include-filter": "android.autofillservice.cts.inline"
+ },
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ },
+ {
+ "exclude-annotation": "android.platform.test.annotations.AppModeFull"
+ }
+ ]
+ }
+ ]
+}
diff --git a/core/java/android/window/ITaskOrganizerController.aidl b/core/java/android/window/ITaskOrganizerController.aidl
index 92fa80e..12b16ff 100644
--- a/core/java/android/window/ITaskOrganizerController.aidl
+++ b/core/java/android/window/ITaskOrganizerController.aidl
@@ -60,5 +60,6 @@
* Requests that the given task organizer is notified when back is pressed on the root activity
* of one of its controlled tasks.
*/
- void setInterceptBackPressedOnTaskRoot(ITaskOrganizer organizer, boolean interceptBackPressed);
+ void setInterceptBackPressedOnTaskRoot(in WindowContainerToken task,
+ boolean interceptBackPressed);
}
diff --git a/core/java/android/window/TaskOrganizer.java b/core/java/android/window/TaskOrganizer.java
index 7ec4f99..38fb023 100644
--- a/core/java/android/window/TaskOrganizer.java
+++ b/core/java/android/window/TaskOrganizer.java
@@ -149,9 +149,10 @@
* of one of its controlled tasks.
*/
@RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
- public void setInterceptBackPressedOnTaskRoot(boolean interceptBackPressed) {
+ public void setInterceptBackPressedOnTaskRoot(@NonNull WindowContainerToken task,
+ boolean interceptBackPressed) {
try {
- getController().setInterceptBackPressedOnTaskRoot(mInterface, interceptBackPressed);
+ getController().setInterceptBackPressedOnTaskRoot(task, interceptBackPressed);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/window/TaskOrganizerTaskEmbedder.java b/core/java/android/window/TaskOrganizerTaskEmbedder.java
index 46c72f8..eb9dfed 100644
--- a/core/java/android/window/TaskOrganizerTaskEmbedder.java
+++ b/core/java/android/window/TaskOrganizerTaskEmbedder.java
@@ -74,7 +74,7 @@
// windowing mode tasks. Plan is to migrate this to a wm-shell front-end when that
// infrastructure is ready.
// mTaskOrganizer.registerOrganizer();
- mTaskOrganizer.setInterceptBackPressedOnTaskRoot(true);
+ // mTaskOrganizer.setInterceptBackPressedOnTaskRoot(true);
return super.onInitialize();
}
diff --git a/core/java/com/android/internal/jank/FrameTracker.java b/core/java/com/android/internal/jank/FrameTracker.java
new file mode 100644
index 0000000..f9a2ecc
--- /dev/null
+++ b/core/java/com/android/internal/jank/FrameTracker.java
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.jank;
+
+import android.annotation.NonNull;
+import android.graphics.HardwareRendererObserver;
+import android.os.Handler;
+import android.os.Trace;
+import android.util.Log;
+import android.view.FrameMetrics;
+import android.view.ThreadedRenderer;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.jank.InteractionJankMonitor.Session;
+
+/**
+ * @hide
+ */
+public class FrameTracker implements HardwareRendererObserver.OnFrameMetricsAvailableListener {
+ private static final String TAG = FrameTracker.class.getSimpleName();
+ private static final boolean DEBUG = false;
+ //TODO (163431584): need also consider other refresh rates.
+ private static final long CRITERIA = 1000000000 / 60;
+ @VisibleForTesting
+ public static final long UNKNOWN_TIMESTAMP = -1;
+
+ @VisibleForTesting
+ public long mBeginTime = UNKNOWN_TIMESTAMP;
+ @VisibleForTesting
+ public long mEndTime = UNKNOWN_TIMESTAMP;
+ public boolean mShouldTriggerTrace;
+ public HardwareRendererObserver mObserver;
+ public ThreadedRendererWrapper mRendererWrapper;
+ public FrameMetricsWrapper mMetricsWrapper;
+
+ private Session mSession;
+
+ public FrameTracker(@NonNull Session session,
+ @NonNull Handler handler, @NonNull ThreadedRenderer renderer) {
+ mSession = session;
+ mRendererWrapper = new ThreadedRendererWrapper(renderer);
+ mMetricsWrapper = new FrameMetricsWrapper();
+ mObserver = new HardwareRendererObserver(this, mMetricsWrapper.getTiming(), handler);
+ }
+
+ /**
+ * This constructor is only for unit tests.
+ * @param session a trace session.
+ * @param renderer a test double for ThreadedRenderer
+ * @param metrics a test double for FrameMetrics
+ */
+ @VisibleForTesting
+ public FrameTracker(@NonNull Session session, Handler handler,
+ @NonNull ThreadedRendererWrapper renderer, @NonNull FrameMetricsWrapper metrics) {
+ mSession = session;
+ mRendererWrapper = renderer;
+ mMetricsWrapper = metrics;
+ mObserver = new HardwareRendererObserver(this, mMetricsWrapper.getTiming(), handler);
+ }
+
+ /**
+ * Begin a trace session of the CUJ.
+ */
+ public void begin() {
+ long timestamp = System.nanoTime();
+ if (DEBUG) {
+ Log.d(TAG, "begin: time(ns)=" + timestamp + ", begin(ns)=" + mBeginTime
+ + ", end(ns)=" + mEndTime + ", session=" + mSession);
+ }
+ if (mBeginTime != UNKNOWN_TIMESTAMP && mEndTime == UNKNOWN_TIMESTAMP) {
+ // We have an ongoing tracing already, skip subsequent calls.
+ return;
+ }
+ mBeginTime = timestamp;
+ mEndTime = UNKNOWN_TIMESTAMP;
+ Trace.beginAsyncSection(mSession.getName(), (int) mBeginTime);
+ mRendererWrapper.addObserver(mObserver);
+ }
+
+ /**
+ * End the trace session of the CUJ.
+ */
+ public void end() {
+ long timestamp = System.nanoTime();
+ if (DEBUG) {
+ Log.d(TAG, "end: time(ns)=" + timestamp + ", begin(ns)=" + mBeginTime
+ + ", end(ns)=" + mEndTime + ", session=" + mSession);
+ }
+ if (mBeginTime == UNKNOWN_TIMESTAMP || mEndTime != UNKNOWN_TIMESTAMP) {
+ // We haven't started a trace yet.
+ return;
+ }
+ mEndTime = timestamp;
+ Trace.endAsyncSection(mSession.getName(), (int) mBeginTime);
+ }
+
+ /**
+ * Check if we had a janky frame according to the metrics.
+ * @param metrics frame metrics
+ * @return true if it is a janky frame
+ */
+ @VisibleForTesting
+ public boolean isJankyFrame(FrameMetricsWrapper metrics) {
+ long totalDurationMs = metrics.getMetric(FrameMetrics.TOTAL_DURATION);
+ boolean isFirstFrame = metrics.getMetric(FrameMetrics.FIRST_DRAW_FRAME) == 1;
+ boolean isJanky = !isFirstFrame && totalDurationMs - CRITERIA > 0;
+
+ if (DEBUG) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(isJanky).append(",");
+ sb.append(metrics.getMetric(FrameMetrics.FIRST_DRAW_FRAME)).append(",");
+ sb.append(metrics.getMetric(FrameMetrics.INPUT_HANDLING_DURATION)).append(",");
+ sb.append(metrics.getMetric(FrameMetrics.ANIMATION_DURATION)).append(",");
+ sb.append(metrics.getMetric(FrameMetrics.LAYOUT_MEASURE_DURATION)).append(",");
+ sb.append(metrics.getMetric(FrameMetrics.DRAW_DURATION)).append(",");
+ sb.append(metrics.getMetric(FrameMetrics.SYNC_DURATION)).append(",");
+ sb.append(metrics.getMetric(FrameMetrics.COMMAND_ISSUE_DURATION)).append(",");
+ sb.append(metrics.getMetric(FrameMetrics.SWAP_BUFFERS_DURATION)).append(",");
+ sb.append(totalDurationMs).append(",");
+ sb.append(metrics.getMetric(FrameMetrics.INTENDED_VSYNC_TIMESTAMP)).append(",");
+ sb.append(metrics.getMetric(FrameMetrics.VSYNC_TIMESTAMP)).append(",");
+ Log.v(TAG, "metrics=" + sb.toString());
+ }
+
+ return isJanky;
+ }
+
+ @Override
+ public void onFrameMetricsAvailable(int dropCountSinceLastInvocation) {
+ // Since this callback might come a little bit late after the end() call.
+ // We should keep tracking the begin / end timestamp.
+ // Then compare with vsync timestamp to check if the frame is in the duration of the CUJ.
+
+ if (mBeginTime == UNKNOWN_TIMESTAMP) return; // We haven't started tracing yet.
+ long vsyncTimestamp = mMetricsWrapper.getMetric(FrameMetrics.VSYNC_TIMESTAMP);
+ if (vsyncTimestamp < mBeginTime) return; // The tracing has been started.
+
+ // If the end time has not been set, we are still in the tracing.
+ if (mEndTime != UNKNOWN_TIMESTAMP && vsyncTimestamp > mEndTime) {
+ // The tracing has been ended, remove the observer, see if need to trigger perfetto.
+ mRendererWrapper.removeObserver(mObserver);
+ // Trigger perfetto if necessary.
+ if (mShouldTriggerTrace) {
+ if (DEBUG) {
+ Log.v(TAG, "Found janky frame, triggering perfetto.");
+ }
+ triggerPerfetto();
+ }
+ return;
+ }
+
+ // The frame is in the duration of the CUJ, check if it catches the deadline.
+ if (isJankyFrame(mMetricsWrapper)) {
+ mShouldTriggerTrace = true;
+ }
+ }
+
+ /**
+ * Trigger the prefetto daemon.
+ */
+ @VisibleForTesting
+ public void triggerPerfetto() {
+ InteractionJankMonitor.trigger();
+ }
+
+ /**
+ * A wrapper class that we can spy FrameMetrics (a final class) in unit tests.
+ */
+ public static class FrameMetricsWrapper {
+ private FrameMetrics mFrameMetrics;
+
+ public FrameMetricsWrapper() {
+ mFrameMetrics = new FrameMetrics();
+ }
+
+ /**
+ * Wrapper method.
+ * @return timing data of the metrics
+ */
+ public long[] getTiming() {
+ return mFrameMetrics.mTimingData;
+ }
+
+ /**
+ * Wrapper method.
+ * @param index specific index of the timing data
+ * @return the timing data of the specified index
+ */
+ public long getMetric(int index) {
+ return mFrameMetrics.getMetric(index);
+ }
+ }
+
+ /**
+ * A wrapper class that we can spy ThreadedRenderer (a final class) in unit tests.
+ */
+ public static class ThreadedRendererWrapper {
+ private ThreadedRenderer mRenderer;
+
+ public ThreadedRendererWrapper(ThreadedRenderer renderer) {
+ mRenderer = renderer;
+ }
+
+ /**
+ * Wrapper method.
+ * @param observer observer
+ */
+ public void addObserver(HardwareRendererObserver observer) {
+ mRenderer.addObserver(observer);
+ }
+
+ /**
+ * Wrapper method.
+ * @param observer observer
+ */
+ public void removeObserver(HardwareRendererObserver observer) {
+ mRenderer.removeObserver(observer);
+ }
+ }
+}
diff --git a/core/java/com/android/internal/jank/InteractionJankMonitor.java b/core/java/com/android/internal/jank/InteractionJankMonitor.java
new file mode 100644
index 0000000..6bfb178
--- /dev/null
+++ b/core/java/com/android/internal/jank/InteractionJankMonitor.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.jank;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.os.HandlerThread;
+import android.view.ThreadedRenderer;
+import android.view.View;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * This class let users to begin and end the always on tracing mechanism.
+ * @hide
+ */
+public class InteractionJankMonitor {
+ private static final String TAG = InteractionJankMonitor.class.getSimpleName();
+ private static final boolean DEBUG = false;
+ private static final Object LOCK = new Object();
+ public static final int CUJ_NOTIFICATION_SHADE_MOTION = 0;
+ public static final int CUJ_NOTIFICATION_SHADE_GESTURE = 1;
+
+ private static ThreadedRenderer sRenderer;
+ private static Map<String, FrameTracker> sRunningTracker;
+ private static HandlerThread sWorker;
+ private static boolean sInitialized;
+
+ /** @hide */
+ @IntDef({
+ CUJ_NOTIFICATION_SHADE_MOTION,
+ CUJ_NOTIFICATION_SHADE_GESTURE
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface CujType {}
+
+ /**
+ * @param view Any view in the view tree to get context and ThreadedRenderer.
+ */
+ public static void init(@NonNull View view) {
+ init(view, null, null, null);
+ }
+
+ /**
+ * Should be only invoked internally or from unit tests.
+ */
+ @VisibleForTesting
+ public static void init(@NonNull View view, @NonNull ThreadedRenderer renderer,
+ @NonNull Map<String, FrameTracker> map, @NonNull HandlerThread worker) {
+ //TODO (163505250): This should be no-op if not in droid food rom.
+ synchronized (LOCK) {
+ if (!sInitialized) {
+ if (!view.isAttachedToWindow()) {
+ throw new IllegalStateException("View is not attached!");
+ }
+ sRenderer = renderer == null ? view.getThreadedRenderer() : renderer;
+ sRunningTracker = map == null ? new HashMap<>() : map;
+ sWorker = worker == null ? new HandlerThread("Aot-Worker") : worker;
+ sWorker.start();
+ sInitialized = true;
+ }
+ }
+ }
+
+ /**
+ * Must invoke init() before invoking this method.
+ */
+ public static void begin(@NonNull @CujType int cujType) {
+ begin(cujType, null);
+ }
+
+ /**
+ * Should be only invoked internally or from unit tests.
+ */
+ @VisibleForTesting
+ public static void begin(@NonNull @CujType int cujType, FrameTracker tracker) {
+ //TODO (163505250): This should be no-op if not in droid food rom.
+ //TODO (163510843): Remove synchronized, add @UiThread if only invoked from ui threads.
+ synchronized (LOCK) {
+ checkInitStateLocked();
+ Session session = new Session(cujType);
+ FrameTracker currentTracker = getTracker(session.getName());
+ if (currentTracker != null) return;
+ if (tracker == null) {
+ tracker = new FrameTracker(session, sWorker.getThreadHandler(), sRenderer);
+ }
+ sRunningTracker.put(session.getName(), tracker);
+ tracker.begin();
+ }
+ }
+
+ /**
+ * Must invoke init() before invoking this method.
+ */
+ public static void end(@NonNull @CujType int cujType) {
+ //TODO (163505250): This should be no-op if not in droid food rom.
+ //TODO (163510843): Remove synchronized, add @UiThread if only invoked from ui threads.
+ synchronized (LOCK) {
+ checkInitStateLocked();
+ Session session = new Session(cujType);
+ FrameTracker tracker = getTracker(session.getName());
+ if (tracker != null) {
+ tracker.end();
+ sRunningTracker.remove(session.getName());
+ }
+ }
+ }
+
+ private static void checkInitStateLocked() {
+ if (!sInitialized) {
+ throw new IllegalStateException("InteractionJankMonitor not initialized!");
+ }
+ }
+
+ /**
+ * Should be only invoked from unit tests.
+ */
+ @VisibleForTesting
+ public static void reset() {
+ sInitialized = false;
+ sRenderer = null;
+ sRunningTracker = null;
+ if (sWorker != null) {
+ sWorker.quit();
+ sWorker = null;
+ }
+ }
+
+ private static FrameTracker getTracker(String sessionName) {
+ synchronized (LOCK) {
+ return sRunningTracker.get(sessionName);
+ }
+ }
+
+ /**
+ * Trigger the perfetto daemon to collect and upload data.
+ */
+ public static void trigger() {
+ sWorker.getThreadHandler().post(
+ () -> PerfettoTrigger.trigger(PerfettoTrigger.TRIGGER_TYPE_JANK));
+ }
+
+ /**
+ * A class to represent a session.
+ */
+ public static class Session {
+ private @CujType int mId;
+
+ public Session(@CujType int session) {
+ mId = session;
+ }
+
+ public int getId() {
+ return mId;
+ }
+
+ public String getName() {
+ return "CujType<" + mId + ">";
+ }
+ }
+
+}
diff --git a/core/java/com/android/internal/jank/PerfettoTrigger.java b/core/java/com/android/internal/jank/PerfettoTrigger.java
new file mode 100644
index 0000000..6c8d3cd
--- /dev/null
+++ b/core/java/com/android/internal/jank/PerfettoTrigger.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//TODO (165884885): Make PerfettoTrigger more generic and move it to another package.
+package com.android.internal.jank;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.util.Log;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * A trigger implementation with perfetto backend.
+ * @hide
+ */
+public class PerfettoTrigger {
+ private static final String TAG = PerfettoTrigger.class.getSimpleName();
+ private static final boolean DEBUG = false;
+ private static final String TRIGGER_COMMAND = "/system/bin/trigger_perfetto";
+ private static final String[] TRIGGER_TYPE_NAMES = new String[] { "jank-tracker" };
+ public static final int TRIGGER_TYPE_JANK = 0;
+
+ /** @hide */
+ @IntDef({
+ TRIGGER_TYPE_JANK
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface TriggerType {}
+
+ /**
+ * @param type the trigger type
+ */
+ public static void trigger(@NonNull @TriggerType int type) {
+ try {
+ Token token = new Token(type, TRIGGER_TYPE_NAMES[type]);
+ ProcessBuilder pb = new ProcessBuilder(TRIGGER_COMMAND, token.getName());
+ if (DEBUG) {
+ StringBuilder sb = new StringBuilder();
+ for (String arg : pb.command()) {
+ sb.append(arg).append(" ");
+ }
+ Log.d(TAG, "Triggering " + sb.toString());
+ }
+ Process process = pb.start();
+ if (DEBUG) {
+ readConsoleOutput(process);
+ }
+ } catch (IOException | InterruptedException e) {
+ Log.w(TAG, "Failed to trigger " + type, e);
+ }
+ }
+
+ private static void readConsoleOutput(@NonNull Process process)
+ throws IOException, InterruptedException {
+ process.waitFor();
+ try (BufferedReader errReader =
+ new BufferedReader(new InputStreamReader(process.getErrorStream()))) {
+ StringBuilder errLine = new StringBuilder();
+ String line;
+ while ((line = errReader.readLine()) != null) {
+ errLine.append(line).append("\n");
+ }
+ errLine.append(", code=").append(process.exitValue());
+ Log.d(TAG, "err message=" + errLine.toString());
+ }
+ }
+
+ /**
+ * Token which is used to trigger perfetto.
+ */
+ public static class Token {
+ private int mType;
+ private String mName;
+
+ Token(@TriggerType int type, String name) {
+ mType = type;
+ mName = name;
+ }
+
+ /**
+ * Get trigger type.
+ * @return trigger type, should be @TriggerType
+ */
+ public int getType() {
+ return mType;
+ }
+
+ /**
+ * Get name of this token as the argument while triggering perfetto.
+ * @return name
+ */
+ public String getName() {
+ return mName;
+ }
+ }
+
+}
diff --git a/core/java/com/android/internal/view/ScrollCaptureViewHelper.java b/core/java/com/android/internal/view/ScrollCaptureViewHelper.java
index 9f100bd..a92e978 100644
--- a/core/java/com/android/internal/view/ScrollCaptureViewHelper.java
+++ b/core/java/com/android/internal/view/ScrollCaptureViewHelper.java
@@ -26,6 +26,36 @@
int DOWN = 1;
/**
+ * Contains the result of a scroll request.
+ */
+ class ScrollResult {
+ /**
+ * The area requested in pixels, within {@link #onComputeScrollBounds scroll bounds}, with
+ * top/bottom relative to the scroll position at the start of capture.
+ */
+ public Rect requestedArea;
+ /**
+ * The area, in pixels of the request which is visible and available for capture. In the
+ * same coordinate space as {@link #requestedArea}.
+ */
+ public Rect availableArea;
+ /**
+ * The updated scroll delta (the relative distance, in pixels that the scroll position has
+ * moved from the starting position since capture started).
+ */
+ public int scrollDelta; // visible top offset from start
+
+ @Override
+ public String toString() {
+ return "ScrollResult{"
+ + "requestedArea=" + requestedArea
+ + ", availableArea=" + availableArea
+ + ", scrollDelta=" + scrollDelta
+ + '}';
+ }
+ }
+
+ /**
* Verifies that the view is still visible and scrollable. If true is returned here, expect a
* call to {@link #onComputeScrollBounds(View)} to follow.
*
@@ -48,6 +78,7 @@
view.getWidth() - view.getPaddingRight(),
view.getHeight() - view.getPaddingBottom());
}
+
/**
* Adjust the target for capture.
* <p>
@@ -67,14 +98,14 @@
* needed and return the resulting rectangle describing the position and bounds of the area
* which is visible.
*
+ * @param view the view being captured
* @param scrollBounds the area in which scrolling content moves, local to the {@code containing
* view}
* @param requestRect the area relative to {@code scrollBounds} which describes the location of
* content to capture for the request
- * @return the visible area within scrollBounds of the requested rectangle, return {@code null}
- * in the case of an unrecoverable error condition, to abort the capture process
+ * @return the result of the request as a {@link ScrollResult}
*/
- Rect onScrollRequested(@NonNull V view, Rect scrollBounds, Rect requestRect);
+ ScrollResult onScrollRequested(@NonNull V view, Rect scrollBounds, Rect requestRect);
/**
* Restore the target after capture.
diff --git a/core/java/com/android/internal/view/ScrollCaptureViewSupport.java b/core/java/com/android/internal/view/ScrollCaptureViewSupport.java
index 4087eda..7b4f73f 100644
--- a/core/java/com/android/internal/view/ScrollCaptureViewSupport.java
+++ b/core/java/com/android/internal/view/ScrollCaptureViewSupport.java
@@ -30,21 +30,24 @@
import android.view.Surface;
import android.view.View;
+import com.android.internal.view.ScrollCaptureViewHelper.ScrollResult;
+
import java.lang.ref.WeakReference;
import java.util.function.Consumer;
/**
- * Provides a ScrollCaptureCallback implementation for to handle arbitrary View-based scrolling
- * containers.
- * <p>
- * To use this class, supply the target view and an implementation of {@ScrollCaptureViewHelper}
- * to the callback.
+ * Provides a base ScrollCaptureCallback implementation to handle arbitrary View-based scrolling
+ * containers. This class handles the bookkeeping aspects of {@link ScrollCaptureCallback}
+ * including rendering output using HWUI. Adaptable to any {@link View} using
+ * {@link ScrollCaptureViewHelper}.
*
* @param <V> the specific View subclass handled
- * @hide
+ * @see ScrollCaptureViewHelper
*/
public class ScrollCaptureViewSupport<V extends View> implements ScrollCaptureCallback {
+ private static final String TAG = "ScrollCaptureViewSupport";
+
private final WeakReference<V> mWeakView;
private final ScrollCaptureViewHelper<V> mViewHelper;
private ViewRenderer mRenderer;
@@ -52,11 +55,6 @@
private boolean mStarted;
private boolean mEnded;
- static <V extends View> ScrollCaptureCallback createCallback(V view,
- ScrollCaptureViewHelper<V> impl) {
- return new ScrollCaptureViewSupport<>(view, impl);
- }
-
ScrollCaptureViewSupport(V containingView, ScrollCaptureViewHelper<V> viewHelper) {
mWeakView = new WeakReference<>(containingView);
mRenderer = new ViewRenderer();
@@ -82,6 +80,7 @@
@Override
public final void onScrollCaptureStart(ScrollCaptureSession session, Runnable onReady) {
V view = mWeakView.get();
+
mEnded = false;
mStarted = true;
@@ -103,21 +102,30 @@
session.notifyBufferSent(0, null);
return;
}
- Rect captureArea = mViewHelper.onScrollRequested(view, session.getScrollBounds(),
+ // Ask the view to scroll as needed to bring this area into view.
+ ScrollResult scrollResult = mViewHelper.onScrollRequested(view, session.getScrollBounds(),
requestRect);
- mRenderer.renderFrame(view, captureArea, mUiHandler,
- () -> session.notifyBufferSent(0, captureArea));
+ view.invalidate(); // don't wait for vsync
+
+ // For image capture, shift back by scrollDelta to arrive at the location within the view
+ // where the requested content will be drawn
+ Rect viewCaptureArea = new Rect(scrollResult.availableArea);
+ viewCaptureArea.offset(0, -scrollResult.scrollDelta);
+
+ mRenderer.renderView(view, viewCaptureArea, mUiHandler,
+ (frameNumber) -> session.notifyBufferSent(frameNumber, scrollResult.availableArea));
}
@Override
public final void onScrollCaptureEnd(Runnable onReady) {
V view = mWeakView.get();
if (mStarted && !mEnded) {
- mViewHelper.onPrepareForEnd(view);
- /* empty */
+ if (view != null) {
+ mViewHelper.onPrepareForEnd(view);
+ view.invalidate();
+ }
mEnded = true;
- mRenderer.trimMemory();
- mRenderer.setSurface(null);
+ mRenderer.destroy();
}
onReady.run();
}
@@ -142,7 +150,7 @@
private static final String TAG = "ViewRenderer";
private HardwareRenderer mRenderer;
- private RenderNode mRootRenderNode;
+ private RenderNode mCaptureRenderNode;
private final RectF mTempRectF = new RectF();
private final Rect mSourceRect = new Rect();
private final Rect mTempRect = new Rect();
@@ -151,10 +159,14 @@
private long mLastRenderedSourceDrawingId = -1;
+ public interface FrameCompleteListener {
+ void onFrameComplete(long frameNumber);
+ }
+
ViewRenderer() {
mRenderer = new HardwareRenderer();
- mRootRenderNode = new RenderNode("ScrollCaptureRoot");
- mRenderer.setContentRoot(mRootRenderNode);
+ mCaptureRenderNode = new RenderNode("ScrollCaptureRoot");
+ mRenderer.setContentRoot(mCaptureRenderNode);
// TODO: Figure out a way to flip this on when we are sure the source window is opaque
mRenderer.setOpaque(false);
@@ -193,18 +205,36 @@
// Enable shadows for elevation/Z
mRenderer.setLightSourceGeometry(lightX, lightY, lightZ, lightRadius);
mRenderer.setLightSourceAlpha(AMBIENT_SHADOW_ALPHA, SPOT_SHADOW_ALPHA);
-
}
- public void renderFrame(View localReference, Rect sourceRect, Handler handler,
- Runnable onFrameCommitted) {
- if (updateForView(localReference)) {
- setupLighting(localReference);
+ private void updateRootNode(View source, Rect localSourceRect) {
+ final View rootView = source.getRootView();
+ transformToRoot(source, localSourceRect, mTempRect);
+
+ mCaptureRenderNode.setPosition(0, 0, mTempRect.width(), mTempRect.height());
+ RecordingCanvas canvas = mCaptureRenderNode.beginRecording();
+ canvas.enableZ();
+ canvas.translate(-mTempRect.left, -mTempRect.top);
+
+ RenderNode rootViewRenderNode = rootView.updateDisplayListIfDirty();
+ if (rootViewRenderNode.hasDisplayList()) {
+ canvas.drawRenderNode(rootViewRenderNode);
}
- buildRootDisplayList(localReference, sourceRect);
+ mCaptureRenderNode.endRecording();
+ }
+
+ public void renderView(View view, Rect sourceRect, Handler handler,
+ FrameCompleteListener frameListener) {
+ if (updateForView(view)) {
+ setupLighting(view);
+ }
+ view.invalidate();
+ updateRootNode(view, sourceRect);
HardwareRenderer.FrameRenderRequest request = mRenderer.createRenderRequest();
request.setVsyncTime(SystemClock.elapsedRealtimeNanos());
- request.setFrameCommitCallback(handler::post, onFrameCommitted);
+ // private API b/c request.setFrameCommitCallback does not provide access to frameNumber
+ mRenderer.setFrameCompleteCallback(
+ frameNr -> handler.post(() -> frameListener.onFrameComplete(frameNr)));
request.setWaitForPresent(true);
request.syncAndDraw();
}
@@ -225,15 +255,5 @@
mTempRectF.round(outRect);
}
- private void buildRootDisplayList(View source, Rect localSourceRect) {
- final View captureSource = source.getRootView();
- transformToRoot(source, localSourceRect, mTempRect);
- mRootRenderNode.setPosition(0, 0, mTempRect.width(), mTempRect.height());
- RecordingCanvas canvas = mRootRenderNode.beginRecording(mTempRect.width(),
- mTempRect.height());
- canvas.translate(-mTempRect.left, -mTempRect.top);
- canvas.drawRenderNode(captureSource.updateDisplayListIfDirty());
- mRootRenderNode.endRecording();
- }
}
}
diff --git a/core/java/com/android/internal/view/ScrollViewCaptureHelper.java b/core/java/com/android/internal/view/ScrollViewCaptureHelper.java
index 12bd461..1514b9a 100644
--- a/core/java/com/android/internal/view/ScrollViewCaptureHelper.java
+++ b/core/java/com/android/internal/view/ScrollViewCaptureHelper.java
@@ -35,13 +35,14 @@
* <li>correctly implements {@link ViewParent#requestChildRectangleOnScreen(View,
* Rect, boolean)}
* </ul>
+ *
+ * @see ScrollCaptureViewSupport
*/
public class ScrollViewCaptureHelper implements ScrollCaptureViewHelper<ViewGroup> {
private int mStartScrollY;
private boolean mScrollBarEnabled;
private int mOverScrollMode;
- /** @see ScrollCaptureViewHelper#onPrepareForStart(View, Rect) */
public void onPrepareForStart(@NonNull ViewGroup view, Rect scrollBounds) {
mStartScrollY = view.getScrollY();
mOverScrollMode = view.getOverScrollMode();
@@ -54,8 +55,8 @@
}
}
- /** @see ScrollCaptureViewHelper#onScrollRequested(View, Rect, Rect) */
- public Rect onScrollRequested(@NonNull ViewGroup view, Rect scrollBounds, Rect requestRect) {
+ public ScrollResult onScrollRequested(@NonNull ViewGroup view, Rect scrollBounds,
+ Rect requestRect) {
final View contentView = view.getChildAt(0); // returns null, does not throw IOOBE
if (contentView == null) {
return null;
@@ -87,6 +88,9 @@
\__ Requested Bounds[0,300 - 200,400] (200x100)
*/
+ ScrollResult result = new ScrollResult();
+ result.requestedArea = new Rect(requestRect);
+
// 0) adjust the requestRect to account for scroll change since start
//
// Scroll Bounds[50,50 - 250,250] (w=200,h=200)
@@ -117,8 +121,6 @@
view.getScrollX() - contentView.getLeft(),
view.getScrollY() - contentView.getTop());
-
-
// requestRect is now local to contentView as requestedContentBounds
// contentView (and each parent in turn if possible) will be scrolled
// (if necessary) to make all of requestedContent visible, (if possible!)
@@ -126,35 +128,37 @@
// update new offset between starting and current scroll position
scrollDelta = view.getScrollY() - mStartScrollY;
+ result.scrollDelta = scrollDelta;
-
- // TODO: adjust to avoid occlusions/minimize scroll changes
+ // TODO: crop capture area to avoid occlusions/minimize scroll changes
Point offset = new Point();
- final Rect capturedRect = new Rect(requestedContentBounds); // empty
- if (!view.getChildVisibleRect(contentView, capturedRect, offset)) {
- capturedRect.setEmpty();
- return capturedRect;
+ final Rect available = new Rect(requestedContentBounds); // empty
+ if (!view.getChildVisibleRect(contentView, available, offset)) {
+ available.setEmpty();
+ result.availableArea = available;
+ return result;
}
// Transform back from global to content-view local
- capturedRect.offset(-offset.x, -offset.y);
+ available.offset(-offset.x, -offset.y);
// Then back to container view
- capturedRect.offset(
+ available.offset(
contentView.getLeft() - view.getScrollX(),
contentView.getTop() - view.getScrollY());
// And back to relative to scrollBounds
- capturedRect.offset(-scrollBounds.left, -scrollBounds.top);
+ available.offset(-scrollBounds.left, -scrollBounds.top);
- // Apply scrollDelta again to return to make capturedRect relative to scrollBounds at
+ // Apply scrollDelta again to return to make `available` relative to `scrollBounds` at
// the scroll position at start of capture.
- capturedRect.offset(0, scrollDelta);
- return capturedRect;
+ available.offset(0, scrollDelta);
+
+ result.availableArea = new Rect(available);
+ return result;
}
- /** @see ScrollCaptureViewHelper#onPrepareForEnd(View) */
public void onPrepareForEnd(@NonNull ViewGroup view) {
view.scrollTo(0, mStartScrollY);
if (mOverScrollMode != View.OVER_SCROLL_NEVER) {
diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp
index 5c045b6..7a5c383 100644
--- a/core/jni/android_media_AudioTrack.cpp
+++ b/core/jni/android_media_AudioTrack.cpp
@@ -20,6 +20,7 @@
#include "android_media_AudioTrack.h"
#include <nativehelper/JNIHelp.h>
+#include <nativehelper/ScopedUtfChars.h>
#include "core_jni_helpers.h"
#include <utils/Log.h>
@@ -251,7 +252,7 @@
jint audioFormat, jint buffSizeInBytes, jint memoryMode,
jintArray jSession, jlong nativeAudioTrack,
jboolean offload, jint encapsulationMode,
- jobject tunerConfiguration) {
+ jobject tunerConfiguration, jstring opPackageName) {
ALOGV("sampleRates=%p, channel mask=%x, index mask=%x, audioFormat(Java)=%d, buffSize=%d,"
" nativeAudioTrack=0x%" PRIX64 ", offload=%d encapsulationMode=%d tuner=%p",
jSampleRate, channelPositionMask, channelIndexMask, audioFormat, buffSizeInBytes,
@@ -337,7 +338,8 @@
}
// create the native AudioTrack object
- lpTrack = new AudioTrack();
+ ScopedUtfChars opPackageNameStr(env, opPackageName);
+ lpTrack = new AudioTrack(opPackageNameStr.c_str());
// read the AudioAttributes values
auto paa = JNIAudioAttributeHelper::makeUnique();
@@ -371,23 +373,24 @@
status_t status = NO_ERROR;
switch (memoryMode) {
case MODE_STREAM:
- status = lpTrack->set(
- AUDIO_STREAM_DEFAULT,// stream type, but more info conveyed in paa (last argument)
- sampleRateInHertz,
- format,// word length, PCM
- nativeChannelMask,
- offload ? 0 : frameCount,
- offload ? AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD : AUDIO_OUTPUT_FLAG_NONE,
- audioCallback, &(lpJniStorage->mCallbackData),//callback, callback data (user)
- 0,// notificationFrames == 0 since not using EVENT_MORE_DATA to feed the AudioTrack
- 0,// shared mem
- true,// thread can call Java
- sessionId,// audio session ID
- offload ? AudioTrack::TRANSFER_SYNC_NOTIF_CALLBACK : AudioTrack::TRANSFER_SYNC,
- offload ? &offloadInfo : NULL,
- -1, -1, // default uid, pid values
- paa.get());
-
+ status = lpTrack->set(AUDIO_STREAM_DEFAULT, // stream type, but more info conveyed
+ // in paa (last argument)
+ sampleRateInHertz,
+ format, // word length, PCM
+ nativeChannelMask, offload ? 0 : frameCount,
+ offload ? AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD
+ : AUDIO_OUTPUT_FLAG_NONE,
+ audioCallback,
+ &(lpJniStorage->mCallbackData), // callback, callback data (user)
+ 0, // notificationFrames == 0 since not using EVENT_MORE_DATA
+ // to feed the AudioTrack
+ 0, // shared mem
+ true, // thread can call Java
+ sessionId, // audio session ID
+ offload ? AudioTrack::TRANSFER_SYNC_NOTIF_CALLBACK
+ : AudioTrack::TRANSFER_SYNC,
+ offload ? &offloadInfo : NULL, -1, -1, // default uid, pid values
+ paa.get());
break;
case MODE_STATIC:
@@ -398,22 +401,22 @@
goto native_init_failure;
}
- status = lpTrack->set(
- AUDIO_STREAM_DEFAULT,// stream type, but more info conveyed in paa (last argument)
- sampleRateInHertz,
- format,// word length, PCM
- nativeChannelMask,
- frameCount,
- AUDIO_OUTPUT_FLAG_NONE,
- audioCallback, &(lpJniStorage->mCallbackData),//callback, callback data (user));
- 0,// notificationFrames == 0 since not using EVENT_MORE_DATA to feed the AudioTrack
- lpJniStorage->mMemBase,// shared mem
- true,// thread can call Java
- sessionId,// audio session ID
- AudioTrack::TRANSFER_SHARED,
- NULL, // default offloadInfo
- -1, -1, // default uid, pid values
- paa.get());
+ status = lpTrack->set(AUDIO_STREAM_DEFAULT, // stream type, but more info conveyed
+ // in paa (last argument)
+ sampleRateInHertz,
+ format, // word length, PCM
+ nativeChannelMask, frameCount, AUDIO_OUTPUT_FLAG_NONE,
+ audioCallback,
+ &(lpJniStorage->mCallbackData), // callback, callback data (user)
+ 0, // notificationFrames == 0 since not using EVENT_MORE_DATA
+ // to feed the AudioTrack
+ lpJniStorage->mMemBase, // shared mem
+ true, // thread can call Java
+ sessionId, // audio session ID
+ AudioTrack::TRANSFER_SHARED,
+ NULL, // default offloadInfo
+ -1, -1, // default uid, pid values
+ paa.get());
break;
default:
@@ -1428,7 +1431,8 @@
{"native_stop", "()V", (void *)android_media_AudioTrack_stop},
{"native_pause", "()V", (void *)android_media_AudioTrack_pause},
{"native_flush", "()V", (void *)android_media_AudioTrack_flush},
- {"native_setup", "(Ljava/lang/Object;Ljava/lang/Object;[IIIIII[IJZILjava/lang/Object;)I",
+ {"native_setup",
+ "(Ljava/lang/Object;Ljava/lang/Object;[IIIIII[IJZILjava/lang/Object;Ljava/lang/String;)I",
(void *)android_media_AudioTrack_setup},
{"native_finalize", "()V", (void *)android_media_AudioTrack_finalize},
{"native_release", "()V", (void *)android_media_AudioTrack_release},
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 34e6efb..fcf9b83 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -1261,7 +1261,7 @@
<string name="volume_ringtone" msgid="134784084629229029">"Hlasitost vyzvánění"</string>
<string name="volume_music" msgid="7727274216734955095">"Hlasitost médií"</string>
<string name="volume_music_hint_playing_through_bluetooth" msgid="2614142915948898228">"Přehrávání pomocí rozhraní Bluetooth"</string>
- <string name="volume_music_hint_silent_ringtone_selected" msgid="1514829655029062233">"Je nastaven tichý vyzváněcí tón"</string>
+ <string name="volume_music_hint_silent_ringtone_selected" msgid="1514829655029062233">"Je nastaven tichý vyzvánění"</string>
<string name="volume_call" msgid="7625321655265747433">"Hlasitost hovoru"</string>
<string name="volume_bluetooth_call" msgid="2930204618610115061">"Hlasitost příchozích hovorů při připojení Bluetooth"</string>
<string name="volume_alarm" msgid="4486241060751798448">"Hlasitost budíku"</string>
@@ -1272,10 +1272,10 @@
<string name="volume_icon_description_incall" msgid="4491255105381227919">"Hlasitost hovoru"</string>
<string name="volume_icon_description_media" msgid="4997633254078171233">"Hlasitost médií"</string>
<string name="volume_icon_description_notification" msgid="579091344110747279">"Hlasitost oznámení"</string>
- <string name="ringtone_default" msgid="9118299121288174597">"Výchozí vyzváněcí tón"</string>
+ <string name="ringtone_default" msgid="9118299121288174597">"Výchozí vyzvánění"</string>
<string name="ringtone_default_with_actual" msgid="2709686194556159773">"Výchozí (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="397111123930141876">"Žádný"</string>
- <string name="ringtone_picker_title" msgid="667342618626068253">"Vyzváněcí tóny"</string>
+ <string name="ringtone_picker_title" msgid="667342618626068253">"Vyzvánění"</string>
<string name="ringtone_picker_title_alarm" msgid="7438934548339024767">"Zvuky budíku"</string>
<string name="ringtone_picker_title_notification" msgid="6387191794719608122">"Zvuky upozornění"</string>
<string name="ringtone_unknown" msgid="5059495249862816475">"Neznámé"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 117fecb..0b7e396 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -657,7 +657,7 @@
<string name="permlab_accessNetworkConditions" msgid="1270732533356286514">"observer netværksforhold"</string>
<string name="permdesc_accessNetworkConditions" msgid="2959269186741956109">"Tillader, at en applikation observerer netværksforhold. Bør aldrig være nødvendigt for almindelige apps."</string>
<string name="permlab_setInputCalibration" msgid="932069700285223434">"skift kalibrering for inputenheden"</string>
- <string name="permdesc_setInputCalibration" msgid="2937872391426631726">"Tillader, at appen ændrer kalibreringsparametrene for berøringsskærmen. Dette bør aldrig være nødvendigt for almindelige apps."</string>
+ <string name="permdesc_setInputCalibration" msgid="2937872391426631726">"Tillader, at appen ændrer kalibreringsparametrene for touchskærmen. Dette bør aldrig være nødvendigt for almindelige apps."</string>
<string name="permlab_accessDrmCertificates" msgid="6473765454472436597">"få adgang til DRM-certifikater"</string>
<string name="permdesc_accessDrmCertificates" msgid="6983139753493781941">"Tillader, at en applikation provisionerer og anvender DRM-certifikater. Dette bør aldrig være nødvendigt for almindelige apps."</string>
<string name="permlab_handoverStatus" msgid="7620438488137057281">"modtag status for Android Beam-overførsler"</string>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index ecce980..c93dbbf 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -484,8 +484,8 @@
<string name="permdesc_setTimeZone" product="default" msgid="4611828585759488256">"Telefonoaren ordu-zona aldatzeko baimena ematen die aplikazioei."</string>
<string name="permlab_getAccounts" msgid="5304317160463582791">"bilatu gailuko kontuak"</string>
<string name="permdesc_getAccounts" product="tablet" msgid="1784452755887604512">"Tabletak ezagutzen dituen kontuen zerrenda lortzeko baimena ematen die aplikazioei. Instalatuta dauzkazun aplikazioek sortutako kontuak har daitezke barnean."</string>
- <string name="permdesc_getAccounts" product="tv" msgid="437604680436540822">"Android TV gailuak ezagutzen dituen kontuen zerrenda lortzeko baimena ematen die aplikazioei. Kontu horien artean, instalatuta dituzun aplikazioek sortutako kontuak egon litezke."</string>
- <string name="permdesc_getAccounts" product="default" msgid="2491273043569751867">"Telefonoak ezagutzen dituen kontuen zerrenda lortzeko baimena ematen die aplikazioei. Instalatuta dituzun aplikazioek sortutako kontuak har daitezke barnean."</string>
+ <string name="permdesc_getAccounts" product="tv" msgid="437604680436540822">"Android TV gailuak ezagutzen dituen kontuen zerrenda lortzeko baimena ematen die aplikazioei. Kontu horien artean, instalatuta dauzkazun aplikazioek sortutako kontuak egon litezke."</string>
+ <string name="permdesc_getAccounts" product="default" msgid="2491273043569751867">"Telefonoak ezagutzen dituen kontuen zerrenda lortzeko baimena ematen die aplikazioei. Instalatuta dauzkazun aplikazioek sortutako kontuak har daitezke barnean."</string>
<string name="permlab_accessNetworkState" msgid="2349126720783633918">"ikusi sareko konexioak"</string>
<string name="permdesc_accessNetworkState" msgid="4394564702881662849">"Sareko konexioei buruzko informazioa ikusteko baimena ematen die aplikazioei; adibidez, zer sare dauden eta zeintzuk dauden konektatuta."</string>
<string name="permlab_createNetworkSockets" msgid="3224420491603590541">"izan sarerako sarbide osoa"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index f9e3e2f..f4fb83d 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -2035,7 +2035,7 @@
<string name="usb_device_resolve_prompt_warn" msgid="325871329788064199">"Aplikasi ini tidak diberi izin merekam, tetapi dapat merekam audio melalui perangkat USB ini."</string>
<string name="accessibility_system_action_home_label" msgid="3234748160850301870">"Beranda"</string>
<string name="accessibility_system_action_back_label" msgid="4205361367345537608">"Kembali"</string>
- <string name="accessibility_system_action_recents_label" msgid="4782875610281649728">"Aplikasi yang Baru Dipakai"</string>
+ <string name="accessibility_system_action_recents_label" msgid="4782875610281649728">"Aplikasi Terbaru"</string>
<string name="accessibility_system_action_notifications_label" msgid="6083767351772162010">"Notifikasi"</string>
<string name="accessibility_system_action_quick_settings_label" msgid="4583900123506773783">"Setelan Cepat"</string>
<string name="accessibility_system_action_power_dialog_label" msgid="8095341821683910781">"Dialog Daya"</string>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index bb79c21..ee0362e 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -304,13 +304,13 @@
<string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string>
<string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS सन्देशहरू पठाउनुहोस् र हेर्नुहोस्"</string>
<string name="permgrouplab_storage" msgid="1938416135375282333">"फाइल र मिडिया"</string>
- <string name="permgroupdesc_storage" msgid="6351503740613026600">"तपाईंको यन्त्रमा तस्बिर, मिडिया, र फाइलहरूमाथि पहुँच गर्नुहोस्"</string>
+ <string name="permgroupdesc_storage" msgid="6351503740613026600">"तपाईंको यन्त्रमा फोटो, मिडिया, र फाइलहरूमाथि पहुँच गर्नुहोस्"</string>
<string name="permgrouplab_microphone" msgid="2480597427667420076">"माइक्रोफोन"</string>
<string name="permgroupdesc_microphone" msgid="1047786732792487722">"अडियो रेकर्ड गर्नुहोस्"</string>
<string name="permgrouplab_activityRecognition" msgid="3324466667921775766">"शारीरिक क्रियाकलाप"</string>
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"आफ्नो शारीरिक क्रियाकलापको डेटामाथि पहुँच राख्नु"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"क्यामेरा"</string>
- <string name="permgroupdesc_camera" msgid="7585150538459320326">"तस्बिर खिच्नुका साथै भिडियो रेकर्ड गर्नुहोस्"</string>
+ <string name="permgroupdesc_camera" msgid="7585150538459320326">"फोटो खिच्नुका साथै भिडियो रेकर्ड गर्नुहोस्"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"कलका लगहरू"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"फोन कलको लग पढ्नुहोस् र लेख्नुहोस्"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"फोन"</string>
@@ -437,10 +437,10 @@
<string name="permdesc_sim_communication" msgid="4179799296415957960">"SIM लाई आदेश पठाउन एपलाई अनुमति दिन्छ। यो निकै खतरनाक हुन्छ।"</string>
<string name="permlab_activityRecognition" msgid="1782303296053990884">"शारीरिक गतिविधि पहिचान गर्नुहोस्"</string>
<string name="permdesc_activityRecognition" msgid="8667484762991357519">"यो अनुप्रयोगले तपाईंको शारीरिक गतिविधिको पहिचान गर्न सक्छ।"</string>
- <string name="permlab_camera" msgid="6320282492904119413">"तस्बिरहरू र भिडियोहरू लिनुहोस्।"</string>
- <string name="permdesc_camera" msgid="1354600178048761499">"यस अनुप्रयोगले जुनसुकै समय क्यामेराको प्रयोग गरी तस्बिर खिच्न र भिडियो रेकर्ड गर्न सक्छ।"</string>
- <string name="permlab_systemCamera" msgid="3642917457796210580">"एप वा सेवालाई तस्बिर र भिडियो खिच्न प्रणालीका क्यामेराहरूमाथि पहुँच राख्न दिनुहोस्"</string>
- <string name="permdesc_systemCamera" msgid="5938360914419175986">"प्रणालीको यस विशेषाधिकार प्राप्त अनुप्रयोगले जुनसुकै बेला प्रणालीको क्यामेरा प्रयोग गरी तस्बिर खिच्न र भिडियो रेकर्ड गर्न सक्छ। अनुप्रयोगसँग पनि android.permission.CAMERA प्रयोग गर्ने अनुमति हुनु पर्छ"</string>
+ <string name="permlab_camera" msgid="6320282492904119413">"फोटोहरू र भिडियोहरू लिनुहोस्।"</string>
+ <string name="permdesc_camera" msgid="1354600178048761499">"यस अनुप्रयोगले जुनसुकै समय क्यामेराको प्रयोग गरी फोटो खिच्न र भिडियो रेकर्ड गर्न सक्छ।"</string>
+ <string name="permlab_systemCamera" msgid="3642917457796210580">"एप वा सेवालाई फोटो र भिडियो खिच्न प्रणालीका क्यामेराहरूमाथि पहुँच राख्न दिनुहोस्"</string>
+ <string name="permdesc_systemCamera" msgid="5938360914419175986">"प्रणालीको यस विशेषाधिकार प्राप्त अनुप्रयोगले जुनसुकै बेला प्रणालीको क्यामेरा प्रयोग गरी फोटो खिच्न र भिडियो रेकर्ड गर्न सक्छ। अनुप्रयोगसँग पनि android.permission.CAMERA प्रयोग गर्ने अनुमति हुनु पर्छ"</string>
<string name="permlab_cameraOpenCloseListener" msgid="5548732769068109315">"कुनै एप वा सेवालाई खोलिँदै वा बन्द गरिँदै गरेका क्यामेरा यन्त्रहरूका बारेमा कलब्याक प्राप्त गर्ने अनुमति दिनुहोस्।"</string>
<string name="permdesc_cameraOpenCloseListener" msgid="2002636131008772908">"कुनै क्यामेरा यन्त्र खोलिँदा (कुन अनुप्रयोगले खोलेको भन्ने बारेमा) वा बन्द गरिँदा यो अनुप्रयोगले कलब्याक प्राप्त गर्न सक्छ।"</string>
<string name="permlab_vibrate" msgid="8596800035791962017">"कम्पन नियन्त्रण गर्नुहोस्"</string>
@@ -1347,7 +1347,7 @@
<string name="ext_media_new_notification_title" product="automotive" msgid="9085349544984742727">"<xliff:g id="NAME">%s</xliff:g> ले काम गरिरहेको छैन"</string>
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"सेटअप गर्न ट्याप गर्नुहोस्"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"तपाईंले यो यन्त्र पुनः फर्म्याट गर्नु पर्ने हुन सक्छ। यो यन्त्र हटाउन ट्याप गर्नुहोस्।"</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"तस्बिरहरू र मिडिया स्थानान्तरणका लागि"</string>
+ <string name="ext_media_ready_notification_message" msgid="777258143284919261">"फोटोहरू र मिडिया स्थानान्तरणका लागि"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"<xliff:g id="NAME">%s</xliff:g> मा समस्या देखियो"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> ले काम गरिरहेको छैन"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"समस्या समाधान गर्न ट्याप गर्नुहोस्"</string>
@@ -1914,7 +1914,7 @@
<string name="app_category_game" msgid="4534216074910244790">"खेलहरू"</string>
<string name="app_category_audio" msgid="8296029904794676222">"सङ्गीत तथा अडियो"</string>
<string name="app_category_video" msgid="2590183854839565814">"चलचित्र तथा भिडियो"</string>
- <string name="app_category_image" msgid="7307840291864213007">"तस्बिर तथा छविहरू"</string>
+ <string name="app_category_image" msgid="7307840291864213007">"फोटो तथा छविहरू"</string>
<string name="app_category_social" msgid="2278269325488344054">"सामाजिक तथा सञ्चार"</string>
<string name="app_category_news" msgid="1172762719574964544">"समाचार तथा पत्रिकाहरू"</string>
<string name="app_category_maps" msgid="6395725487922533156">"नक्सा तथा नेभिगेसन"</string>
diff --git a/core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java b/core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java
new file mode 100644
index 0000000..7480a20
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.jank;
+
+import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_GESTURE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.only;
+import static org.mockito.Mockito.verify;
+
+import android.os.Handler;
+import android.view.FrameMetrics;
+import android.view.View;
+import android.view.ViewAttachTestActivity;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.rule.ActivityTestRule;
+
+import com.android.internal.jank.FrameTracker.FrameMetricsWrapper;
+import com.android.internal.jank.FrameTracker.ThreadedRendererWrapper;
+import com.android.internal.jank.InteractionJankMonitor.Session;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import java.util.concurrent.TimeUnit;
+
+@SmallTest
+public class FrameTrackerTest {
+ private ViewAttachTestActivity mActivity;
+
+ @Rule
+ public ActivityTestRule<ViewAttachTestActivity> mRule =
+ new ActivityTestRule<>(ViewAttachTestActivity.class);
+
+ private FrameTracker mTracker;
+ private ThreadedRendererWrapper mRenderer;
+ private FrameMetricsWrapper mWrapper;
+
+ @Before
+ public void setup() {
+ // Prepare an activity for getting ThreadedRenderer later.
+ mActivity = mRule.getActivity();
+ View view = mActivity.getWindow().getDecorView();
+ assertThat(view.isAttachedToWindow()).isTrue();
+
+ Handler handler = mRule.getActivity().getMainThreadHandler();
+ mWrapper = Mockito.spy(new FrameMetricsWrapper());
+ mRenderer = Mockito.spy(new ThreadedRendererWrapper(view.getThreadedRenderer()));
+ doNothing().when(mRenderer).addObserver(any());
+ doNothing().when(mRenderer).removeObserver(any());
+
+ Session session = new Session(CUJ_NOTIFICATION_SHADE_GESTURE);
+ mTracker = Mockito.spy(new FrameTracker(session, handler, mRenderer, mWrapper));
+ doNothing().when(mTracker).triggerPerfetto();
+ }
+
+ @Test
+ public void testIsJankyFrame() {
+ // We skip the first frame.
+ doReturn(1L).when(mWrapper).getMetric(FrameMetrics.FIRST_DRAW_FRAME);
+ doReturn(TimeUnit.MILLISECONDS.toNanos(20L))
+ .when(mWrapper).getMetric(FrameMetrics.TOTAL_DURATION);
+ assertThat(mTracker.isJankyFrame(mWrapper)).isFalse();
+
+ // Should exceed the criteria.
+ doReturn(0L).when(mWrapper).getMetric(FrameMetrics.FIRST_DRAW_FRAME);
+ doReturn(TimeUnit.MILLISECONDS.toNanos(20L))
+ .when(mWrapper).getMetric(FrameMetrics.TOTAL_DURATION);
+ assertThat(mTracker.isJankyFrame(mWrapper)).isTrue();
+
+ // Should be safe.
+ doReturn(TimeUnit.MILLISECONDS.toNanos(10L))
+ .when(mWrapper).getMetric(FrameMetrics.TOTAL_DURATION);
+ assertThat(mTracker.isJankyFrame(mWrapper)).isFalse();
+ }
+
+ @Test
+ public void testBeginEnd() {
+ // assert the initial values
+ assertThat(mTracker.mBeginTime).isEqualTo(FrameTracker.UNKNOWN_TIMESTAMP);
+ assertThat(mTracker.mEndTime).isEqualTo(FrameTracker.UNKNOWN_TIMESTAMP);
+
+ // Observer should be only added once in continuous calls.
+ mTracker.begin();
+ mTracker.begin();
+ verify(mRenderer, only()).addObserver(any());
+
+ // assert the values after begin call.
+ assertThat(mTracker.mBeginTime).isNotEqualTo(FrameTracker.UNKNOWN_TIMESTAMP);
+ assertThat(mTracker.mEndTime).isEqualTo(FrameTracker.UNKNOWN_TIMESTAMP);
+
+ // simulate the callback during trace session
+ // assert the isJankyFrame should be invoked as well.
+ doReturn(System.nanoTime()).when(mWrapper).getMetric(FrameMetrics.VSYNC_TIMESTAMP);
+ doReturn(true).when(mTracker).isJankyFrame(any());
+ mTracker.onFrameMetricsAvailable(0);
+ verify(mTracker).isJankyFrame(any());
+
+ // end the trace session, simulate a callback came after the end call.
+ // assert the end time should be set, the observer should be removed.
+ // triggerPerfetto should be invoked as well.
+ mTracker.end();
+ doReturn(System.nanoTime()).when(mWrapper).getMetric(FrameMetrics.VSYNC_TIMESTAMP);
+ assertThat(mTracker.mEndTime).isNotEqualTo(FrameTracker.UNKNOWN_TIMESTAMP);
+ mTracker.onFrameMetricsAvailable(0);
+ verify(mRenderer).removeObserver(any());
+ verify(mTracker).triggerPerfetto();
+ }
+}
diff --git a/core/tests/coretests/src/com/android/internal/jank/InteractionJankMonitorTest.java b/core/tests/coretests/src/com/android/internal/jank/InteractionJankMonitorTest.java
new file mode 100644
index 0000000..5c0b0c9
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/jank/InteractionJankMonitorTest.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.jank;
+
+import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_GESTURE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.verify;
+
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.view.View;
+import android.view.ViewAttachTestActivity;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.rule.ActivityTestRule;
+
+import com.android.internal.jank.FrameTracker.FrameMetricsWrapper;
+import com.android.internal.jank.FrameTracker.ThreadedRendererWrapper;
+import com.android.internal.jank.InteractionJankMonitor.Session;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.testng.Assert;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@SmallTest
+public class InteractionJankMonitorTest {
+ private ViewAttachTestActivity mActivity;
+ private View mView;
+ private FrameTracker mTracker;
+
+ @Rule
+ public ActivityTestRule<ViewAttachTestActivity> mRule =
+ new ActivityTestRule<>(ViewAttachTestActivity.class);
+
+ @Before
+ public void setup() {
+ // Prepare an activity for getting ThreadedRenderer later.
+ mActivity = mRule.getActivity();
+ mView = mActivity.getWindow().getDecorView();
+ assertThat(mView.isAttachedToWindow()).isTrue();
+
+ InteractionJankMonitor.reset();
+
+ // Prepare a FrameTracker to inject.
+ Session session = new Session(CUJ_NOTIFICATION_SHADE_GESTURE);
+ FrameMetricsWrapper wrapper = Mockito.spy(new FrameTracker.FrameMetricsWrapper());
+ ThreadedRendererWrapper renderer =
+ Mockito.spy(new ThreadedRendererWrapper(mView.getThreadedRenderer()));
+ Handler handler = mActivity.getMainThreadHandler();
+ mTracker = Mockito.spy(new FrameTracker(session, handler, renderer, wrapper));
+ }
+
+ @Test
+ public void testBeginEnd() {
+ // Should throw exception if the view is not attached.
+ Assert.assertThrows(IllegalStateException.class,
+ () -> InteractionJankMonitor.init(new View(mActivity)));
+
+ // Verify we init InteractionJankMonitor correctly.
+ Map<String, FrameTracker> map = new HashMap<>();
+ HandlerThread worker = Mockito.spy(new HandlerThread("Aot-test"));
+ doNothing().when(worker).start();
+ InteractionJankMonitor.init(mView, mView.getThreadedRenderer(), map, worker);
+ verify(worker).start();
+
+ // Simulate a trace session and see if begin / end are invoked.
+ Session session = new Session(CUJ_NOTIFICATION_SHADE_GESTURE);
+ assertThat(map.get(session.getName())).isNull();
+ InteractionJankMonitor.begin(CUJ_NOTIFICATION_SHADE_GESTURE, mTracker);
+ verify(mTracker).begin();
+ assertThat(map.get(session.getName())).isEqualTo(mTracker);
+ InteractionJankMonitor.end(CUJ_NOTIFICATION_SHADE_GESTURE);
+ verify(mTracker).end();
+ assertThat(map.get(session.getName())).isNull();
+ }
+
+ @Test
+ public void testCheckInitState() {
+ // Should throw exception if invoking begin / end without init invocation.
+ Assert.assertThrows(IllegalStateException.class,
+ () -> InteractionJankMonitor.begin(CUJ_NOTIFICATION_SHADE_GESTURE));
+ Assert.assertThrows(IllegalStateException.class,
+ () -> InteractionJankMonitor.end(CUJ_NOTIFICATION_SHADE_GESTURE));
+
+ // Everything should be fine if invoking init first.
+ boolean thrown = false;
+ try {
+ InteractionJankMonitor.init(mActivity.getWindow().getDecorView());
+ InteractionJankMonitor.begin(CUJ_NOTIFICATION_SHADE_GESTURE);
+ InteractionJankMonitor.end(CUJ_NOTIFICATION_SHADE_GESTURE);
+ } catch (Exception ex) {
+ thrown = true;
+ } finally {
+ assertThat(thrown).isFalse();
+ }
+ }
+
+}
diff --git a/core/tests/coretests/src/com/android/internal/view/ScrollViewCaptureHelperTest.java b/core/tests/coretests/src/com/android/internal/view/ScrollViewCaptureHelperTest.java
index 63a68e9..ab13fd7d 100644
--- a/core/tests/coretests/src/com/android/internal/view/ScrollViewCaptureHelperTest.java
+++ b/core/tests/coretests/src/com/android/internal/view/ScrollViewCaptureHelperTest.java
@@ -21,12 +21,11 @@
import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
-import static androidx.test.InstrumentationRegistry.getContext;
-
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import android.content.Context;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.graphics.Rect;
@@ -40,10 +39,12 @@
import android.widget.TextView;
import androidx.test.annotation.UiThreadTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.internal.view.ScrollCaptureViewHelper.ScrollResult;
import org.junit.After;
import org.junit.Before;
-import org.junit.BeforeClass;
import org.junit.Test;
import java.util.Random;
@@ -67,28 +68,27 @@
private Random mRandom;
- private static float sDensity;
-
- @BeforeClass
- public static void setUpClass() {
- sDensity = getContext().getResources().getDisplayMetrics().density;
- }
+ private Context mContext;
+ private float mDensity;
@Before
@UiThreadTest
public void setUp() {
- mRandom = new Random();
- mParent = new FrameLayout(getContext());
+ mContext = InstrumentationRegistry.getInstrumentation().getContext();
+ mDensity = mContext.getResources().getDisplayMetrics().density;
- mTarget = new ScrollView(getContext());
+ mRandom = new Random();
+ mParent = new FrameLayout(mContext);
+
+ mTarget = new ScrollView(mContext);
mParent.addView(mTarget, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
- mContent = new LinearLayout(getContext());
+ mContent = new LinearLayout(mContext);
mContent.setOrientation(LinearLayout.VERTICAL);
mTarget.addView(mContent, new ViewGroup.LayoutParams(MATCH_PARENT, WRAP_CONTENT));
for (int i = 0; i < CHILD_VIEWS; i++) {
- TextView view = new TextView(getContext());
+ TextView view = new TextView(mContext);
view.setText("Child #" + i);
view.setTextColor(Color.WHITE);
view.setTextSize(30f);
@@ -99,7 +99,7 @@
// Window -> Parent -> Target -> Content
- mWm = getContext().getSystemService(WindowManager.class);
+ mWm = mContext.getSystemService(WindowManager.class);
// Setup the window that we are going to use
mWindowLayoutParams = new WindowManager.LayoutParams(WINDOW_WIDTH, WINDOW_HEIGHT,
@@ -123,6 +123,190 @@
svc.onPrepareForStart(mTarget, scrollBounds);
}
+ @Test
+ @UiThreadTest
+ public void onScrollRequested_up_fromTop() {
+ final int startScrollY = assertScrollToY(mTarget, 0);
+
+ ScrollViewCaptureHelper svc = new ScrollViewCaptureHelper();
+ Rect scrollBounds = svc.onComputeScrollBounds(mTarget);
+ svc.onPrepareForStart(mTarget, scrollBounds);
+
+ assertTrue(scrollBounds.height() > CAPTURE_HEIGHT);
+
+ Rect request = new Rect(0, -CAPTURE_HEIGHT, scrollBounds.width(), 0);
+
+ ScrollResult scrollResult = svc.onScrollRequested(mTarget,
+ scrollBounds, request);
+
+ // The result is an empty rectangle and no scrolling, since it
+ // is not possible to physically scroll further up to make the
+ // requested area visible at all (it doesn't exist).
+ assertEmpty(scrollResult.availableArea);
+ }
+
+ @Test
+ @UiThreadTest
+ public void onScrollRequested_down_fromTop() {
+ final int startScrollY = assertScrollToY(mTarget, 0);
+
+ ScrollViewCaptureHelper svc = new ScrollViewCaptureHelper();
+ Rect scrollBounds = svc.onComputeScrollBounds(mTarget);
+ svc.onPrepareForStart(mTarget, scrollBounds);
+
+ assertTrue(scrollBounds.height() > CAPTURE_HEIGHT);
+
+ // Capture between y = +1200 to +1500 pixels BELOW current top
+ Rect request = new Rect(0, WINDOW_HEIGHT, scrollBounds.width(),
+ WINDOW_HEIGHT + CAPTURE_HEIGHT);
+
+ ScrollResult scrollResult = svc.onScrollRequested(mTarget, scrollBounds, request);
+ assertRectEquals(request, scrollResult.requestedArea);
+ assertRectEquals(request, scrollResult.availableArea);
+ assertRequestedRectCompletelyVisible(startScrollY, request, getVisibleRect(mContent));
+ assertEquals(CAPTURE_HEIGHT, scrollResult.scrollDelta);
+ }
+
+ @Test
+ @UiThreadTest
+ public void onScrollRequested_up_fromMiddle() {
+ final int startScrollY = assertScrollToY(mTarget, WINDOW_HEIGHT);
+
+ ScrollViewCaptureHelper svc = new ScrollViewCaptureHelper();
+ Rect scrollBounds = svc.onComputeScrollBounds(mTarget);
+ svc.onPrepareForStart(mTarget, scrollBounds);
+
+ Rect request = new Rect(0, -CAPTURE_HEIGHT, scrollBounds.width(), 0);
+
+ ScrollResult scrollResult = svc.onScrollRequested(mTarget, scrollBounds, request);
+ assertRectEquals(request, scrollResult.requestedArea);
+ assertRectEquals(request, scrollResult.availableArea);
+ assertRequestedRectCompletelyVisible(startScrollY, request, getVisibleRect(mContent));
+ assertEquals(-CAPTURE_HEIGHT, scrollResult.scrollDelta);
+ }
+
+ @Test
+ @UiThreadTest
+ public void onScrollRequested_down_fromMiddle() {
+ final int startScrollY = assertScrollToY(mTarget, WINDOW_HEIGHT);
+
+ ScrollViewCaptureHelper svc = new ScrollViewCaptureHelper();
+ Rect scrollBounds = svc.onComputeScrollBounds(mTarget);
+ svc.onPrepareForStart(mTarget, scrollBounds);
+
+ Rect request = new Rect(0, WINDOW_HEIGHT, scrollBounds.width(),
+ WINDOW_HEIGHT + CAPTURE_HEIGHT);
+
+ ScrollResult scrollResult = svc.onScrollRequested(mTarget, scrollBounds, request);
+ assertRectEquals(request, scrollResult.requestedArea);
+ assertRectEquals(request, scrollResult.availableArea);
+ assertRequestedRectCompletelyVisible(startScrollY, request, getVisibleRect(mContent));
+ assertEquals(CAPTURE_HEIGHT, scrollResult.scrollDelta);
+
+ }
+
+ @Test
+ @UiThreadTest
+ public void onScrollRequested_up_fromBottom() {
+ final int startScrollY = assertScrollToY(mTarget, WINDOW_HEIGHT * 2);
+
+ ScrollViewCaptureHelper svc = new ScrollViewCaptureHelper();
+ Rect scrollBounds = svc.onComputeScrollBounds(mTarget);
+ svc.onPrepareForStart(mTarget, scrollBounds);
+
+ Rect request = new Rect(0, -CAPTURE_HEIGHT, scrollBounds.width(), 0);
+
+ ScrollResult scrollResult = svc.onScrollRequested(mTarget, scrollBounds, request);
+ assertRectEquals(request, scrollResult.requestedArea);
+ assertRectEquals(request, scrollResult.availableArea);
+ assertRequestedRectCompletelyVisible(startScrollY, request, getVisibleRect(mContent));
+ assertEquals(-CAPTURE_HEIGHT, scrollResult.scrollDelta);
+ }
+
+ @Test
+ @UiThreadTest
+ public void onScrollRequested_down_fromBottom() {
+ final int startScrollY = assertScrollToY(mTarget, WINDOW_HEIGHT * 2);
+
+ ScrollViewCaptureHelper svc = new ScrollViewCaptureHelper();
+ Rect scrollBounds = svc.onComputeScrollBounds(mTarget);
+ svc.onPrepareForStart(mTarget, scrollBounds);
+
+ Rect request = new Rect(0, WINDOW_HEIGHT, scrollBounds.width(),
+ WINDOW_HEIGHT + CAPTURE_HEIGHT);
+
+ ScrollResult scrollResult = svc.onScrollRequested(mTarget, scrollBounds, request);
+ assertRectEquals(request, scrollResult.requestedArea);
+
+ // The result is an empty rectangle and no scrolling, since it
+ // is not possible to physically scroll further down to make the
+ // requested area visible at all (it doesn't exist).
+ assertEmpty(scrollResult.availableArea);
+ assertEquals(0, scrollResult.scrollDelta);
+ }
+
+ @Test
+ @UiThreadTest
+ public void onScrollRequested_offTopEdge() {
+ final int startScrollY = assertScrollToY(mTarget, 0);
+
+ ScrollViewCaptureHelper svc = new ScrollViewCaptureHelper();
+ Rect scrollBounds = svc.onComputeScrollBounds(mTarget);
+ svc.onPrepareForStart(mTarget, scrollBounds);
+
+ // Create a request which lands halfway off the top of the content
+ //from -1500 to -900, (starting at 1200 = -300 to +300 within the content)
+ int top = 0;
+ Rect request = new Rect(
+ 0, top - (CAPTURE_HEIGHT / 2),
+ scrollBounds.width(), top + (CAPTURE_HEIGHT / 2));
+
+ ScrollResult scrollResult = svc.onScrollRequested(mTarget, scrollBounds, request);
+ assertRectEquals(request, scrollResult.requestedArea);
+
+ ScrollResult result = svc.onScrollRequested(mTarget, scrollBounds, request);
+ // The result is a partial result
+ Rect expectedResult = new Rect(request);
+ expectedResult.top += 300; // top half clipped
+ assertRectEquals(expectedResult, result.availableArea);
+ assertRequestedRectPartiallyVisible(startScrollY, request, getVisibleRect(mContent));
+ assertEquals(0, scrollResult.scrollDelta);
+ }
+
+ @Test
+ @UiThreadTest
+ public void onScrollRequested_offBottomEdge() {
+ final int startScrollY = assertScrollToY(mTarget, WINDOW_HEIGHT * 2); // 2400
+
+ ScrollViewCaptureHelper svc = new ScrollViewCaptureHelper();
+ Rect scrollBounds = svc.onComputeScrollBounds(mTarget);
+ svc.onPrepareForStart(mTarget, scrollBounds);
+
+ // Create a request which lands halfway off the bottom of the content
+ //from 600 to to 1200, (starting at 2400 = 3000 to 3600 within the content)
+
+ int bottom = WINDOW_HEIGHT;
+ Rect request = new Rect(
+ 0, bottom - (CAPTURE_HEIGHT / 2),
+ scrollBounds.width(), bottom + (CAPTURE_HEIGHT / 2));
+
+ ScrollResult result = svc.onScrollRequested(mTarget, scrollBounds, request);
+
+ Rect expectedResult = new Rect(request);
+ expectedResult.bottom -= 300; // bottom half clipped
+ assertRectEquals(expectedResult, result.availableArea);
+ assertRequestedRectPartiallyVisible(startScrollY, request, getVisibleRect(mContent));
+ assertEquals(0, result.scrollDelta);
+ }
+
+ @Test
+ @UiThreadTest
+ public void onPrepareForEnd() {
+ ScrollViewCaptureHelper svc = new ScrollViewCaptureHelper();
+ svc.onPrepareForEnd(mTarget);
+ }
+
+
static void assertEmpty(Rect r) {
if (r != null && !r.isEmpty()) {
fail("Not true that " + r + " is empty");
@@ -155,8 +339,7 @@
return scrollY;
}
-
- static void assertCapturedAreaCompletelyVisible(int startScrollY, Rect requestRect,
+ static void assertRequestedRectCompletelyVisible(int startScrollY, Rect requestRect,
Rect localVisibleNow) {
Rect captured = new Rect(localVisibleNow);
captured.offset(0, -startScrollY); // make relative
@@ -165,7 +348,7 @@
fail("Not true that all of " + requestRect + " is contained by " + captured);
}
}
- static void assertCapturedAreaPartiallyVisible(int startScrollY, Rect requestRect,
+ static void assertRequestedRectPartiallyVisible(int startScrollY, Rect requestRect,
Rect localVisibleNow) {
Rect captured = new Rect(localVisibleNow);
captured.offset(0, -startScrollY); // make relative
@@ -174,179 +357,4 @@
fail("Not true that any of " + requestRect + " intersects " + captured);
}
}
-
- @Test
- @UiThreadTest
- public void onScrollRequested_up_fromTop() {
- final int startScrollY = assertScrollToY(mTarget, 0);
-
- ScrollViewCaptureHelper svc = new ScrollViewCaptureHelper();
- Rect scrollBounds = svc.onComputeScrollBounds(mTarget);
- svc.onPrepareForStart(mTarget, scrollBounds);
-
- assertTrue(scrollBounds.height() > CAPTURE_HEIGHT);
-
- Rect request = new Rect(0, -CAPTURE_HEIGHT, scrollBounds.width(), 0);
-
- Rect result = svc.onScrollRequested(mTarget, scrollBounds, request);
-
- // The result is an empty rectangle and no scrolling, since it
- // is not possible to physically scroll further up to make the
- // requested area visible at all (it doesn't exist).
- assertEmpty(result);
- }
-
- @Test
- @UiThreadTest
- public void onScrollRequested_down_fromTop() {
- final int startScrollY = assertScrollToY(mTarget, 0);
-
-
- ScrollViewCaptureHelper svc = new ScrollViewCaptureHelper();
- Rect scrollBounds = svc.onComputeScrollBounds(mTarget);
- svc.onPrepareForStart(mTarget, scrollBounds);
-
- assertTrue(scrollBounds.height() > CAPTURE_HEIGHT);
-
- // Capture between y = +1200 to +1500 pixels BELOW current top
- Rect request = new Rect(0, WINDOW_HEIGHT, scrollBounds.width(),
- WINDOW_HEIGHT + CAPTURE_HEIGHT);
-
- Rect result = svc.onScrollRequested(mTarget, scrollBounds, request);
- assertRectEquals(request, result);
-
- assertCapturedAreaCompletelyVisible(startScrollY, request, getVisibleRect(mContent));
- }
-
-
- @Test
- @UiThreadTest
- public void onScrollRequested_up_fromMiddle() {
- final int startScrollY = assertScrollToY(mTarget, WINDOW_HEIGHT);
-
- ScrollViewCaptureHelper svc = new ScrollViewCaptureHelper();
- Rect scrollBounds = svc.onComputeScrollBounds(mTarget);
- svc.onPrepareForStart(mTarget, scrollBounds);
-
- Rect request = new Rect(0, -CAPTURE_HEIGHT, scrollBounds.width(), 0);
-
-
- Rect result = svc.onScrollRequested(mTarget, scrollBounds, request);
-
- assertRectEquals(request, result);
-
- assertCapturedAreaCompletelyVisible(startScrollY, request, getVisibleRect(mContent));
- }
-
- @Test
- @UiThreadTest
- public void onScrollRequested_down_fromMiddle() {
- final int startScrollY = assertScrollToY(mTarget, WINDOW_HEIGHT);
-
- ScrollViewCaptureHelper svc = new ScrollViewCaptureHelper();
- Rect scrollBounds = svc.onComputeScrollBounds(mTarget);
- svc.onPrepareForStart(mTarget, scrollBounds);
-
- Rect request = new Rect(0, WINDOW_HEIGHT, scrollBounds.width(),
- WINDOW_HEIGHT + CAPTURE_HEIGHT);
-
- Rect result = svc.onScrollRequested(mTarget, scrollBounds, request);
- assertRectEquals(request, result);
-
- assertCapturedAreaCompletelyVisible(startScrollY, request, getVisibleRect(mContent));
- }
-
- @Test
- @UiThreadTest
- public void onScrollRequested_up_fromBottom() {
- final int startScrollY = assertScrollToY(mTarget, WINDOW_HEIGHT * 2);
-
- ScrollViewCaptureHelper svc = new ScrollViewCaptureHelper();
- Rect scrollBounds = svc.onComputeScrollBounds(mTarget);
- svc.onPrepareForStart(mTarget, scrollBounds);
-
- Rect request = new Rect(0, -CAPTURE_HEIGHT, scrollBounds.width(), 0);
-
- Rect result = svc.onScrollRequested(mTarget, scrollBounds, request);
- assertRectEquals(request, result);
-
- assertCapturedAreaCompletelyVisible(startScrollY, request, getVisibleRect(mContent));
- }
-
- @Test
- @UiThreadTest
- public void onScrollRequested_down_fromBottom() {
- final int startScrollY = assertScrollToY(mTarget, WINDOW_HEIGHT * 2);
-
- ScrollViewCaptureHelper svc = new ScrollViewCaptureHelper();
- Rect scrollBounds = svc.onComputeScrollBounds(mTarget);
- svc.onPrepareForStart(mTarget, scrollBounds);
-
- Rect request = new Rect(0, WINDOW_HEIGHT, scrollBounds.width(),
- WINDOW_HEIGHT + CAPTURE_HEIGHT);
-
- Rect result = svc.onScrollRequested(mTarget, scrollBounds, request);
-
- // The result is an empty rectangle and no scrolling, since it
- // is not possible to physically scroll further down to make the
- // requested area visible at all (it doesn't exist).
- assertEmpty(result);
- }
-
- @Test
- @UiThreadTest
- public void onScrollRequested_offTopEdge() {
- final int startScrollY = assertScrollToY(mTarget, 0);
-
- ScrollViewCaptureHelper svc = new ScrollViewCaptureHelper();
- Rect scrollBounds = svc.onComputeScrollBounds(mTarget);
- svc.onPrepareForStart(mTarget, scrollBounds);
-
- // Create a request which lands halfway off the top of the content
- //from -1500 to -900, (starting at 1200 = -300 to +300 within the content)
- int top = 0;
- Rect request = new Rect(
- 0, top - (CAPTURE_HEIGHT / 2),
- scrollBounds.width(), top + (CAPTURE_HEIGHT / 2));
-
- Rect result = svc.onScrollRequested(mTarget, scrollBounds, request);
- // The result is a partial result
- Rect expectedResult = new Rect(request);
- expectedResult.top += 300; // top half clipped
- assertRectEquals(expectedResult, result);
- assertCapturedAreaPartiallyVisible(startScrollY, request, getVisibleRect(mContent));
- }
-
- @Test
- @UiThreadTest
- public void onScrollRequested_offBottomEdge() {
- final int startScrollY = assertScrollToY(mTarget, WINDOW_HEIGHT * 2); // 2400
-
- ScrollViewCaptureHelper svc = new ScrollViewCaptureHelper();
- Rect scrollBounds = svc.onComputeScrollBounds(mTarget);
- svc.onPrepareForStart(mTarget, scrollBounds);
-
- // Create a request which lands halfway off the bottom of the content
- //from 600 to to 1200, (starting at 2400 = 3000 to 3600 within the content)
-
- int bottom = WINDOW_HEIGHT;
- Rect request = new Rect(
- 0, bottom - (CAPTURE_HEIGHT / 2),
- scrollBounds.width(), bottom + (CAPTURE_HEIGHT / 2));
-
- Rect result = svc.onScrollRequested(mTarget, scrollBounds, request);
-
- Rect expectedResult = new Rect(request);
- expectedResult.bottom -= 300; // bottom half clipped
- assertRectEquals(expectedResult, result);
- assertCapturedAreaPartiallyVisible(startScrollY, request, getVisibleRect(mContent));
-
- }
-
- @Test
- @UiThreadTest
- public void onPrepareForEnd() {
- ScrollViewCaptureHelper svc = new ScrollViewCaptureHelper();
- svc.onPrepareForEnd(mTarget);
- }
}
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json
index 75eb7b6..a2a2216 100644
--- a/data/etc/services.core.protolog.json
+++ b/data/etc/services.core.protolog.json
@@ -325,12 +325,6 @@
"group": "WM_DEBUG_REMOTE_ANIMATIONS",
"at": "com\/android\/server\/wm\/RemoteAnimationController.java"
},
- "-1587841219": {
- "message": "Focus moving from %s to %s displayId=%d",
- "level": "INFO",
- "group": "WM_DEBUG_FOCUS_LIGHT",
- "at": "com\/android\/server\/wm\/WindowManagerService.java"
- },
"-1568331821": {
"message": "Enabling listeners",
"level": "VERBOSE",
@@ -415,6 +409,12 @@
"group": "WM_ERROR",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
+ "-1438175584": {
+ "message": "Input focus has changed to %s display=%d",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_FOCUS_LIGHT",
+ "at": "com\/android\/server\/wm\/InputMonitor.java"
+ },
"-1434147454": {
"message": "cleanupAnimation(): Notify animation finished mPendingAnimations=%d reorderMode=%d",
"level": "DEBUG",
@@ -565,6 +565,12 @@
"group": "WM_SHOW_TRANSACTIONS",
"at": "com\/android\/server\/wm\/WindowStateAnimator.java"
},
+ "-1142279614": {
+ "message": "Looking for focus: %s, flags=%d, canReceive=%b, reason=%s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_FOCUS",
+ "at": "com\/android\/server\/wm\/DisplayContent.java"
+ },
"-1130891072": {
"message": "Orientation continue waiting for draw in %s",
"level": "VERBOSE",
@@ -799,12 +805,6 @@
"group": "WM_DEBUG_ORIENTATION",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
- "-771282525": {
- "message": "Losing focus: %s",
- "level": "INFO",
- "group": "WM_DEBUG_FOCUS_LIGHT",
- "at": "com\/android\/server\/wm\/WindowManagerService.java"
- },
"-771177730": {
"message": "Removing focused app token:%s displayId=%d",
"level": "VERBOSE",
@@ -847,12 +847,6 @@
"group": "WM_DEBUG_ORIENTATION",
"at": "com\/android\/server\/wm\/DragState.java"
},
- "-687185281": {
- "message": "New topFocusedDisplayId=%d",
- "level": "VERBOSE",
- "group": "WM_DEBUG_FOCUS_LIGHT",
- "at": "com\/android\/server\/wm\/RootWindowContainer.java"
- },
"-668956537": {
"message": " THUMBNAIL %s: CREATE",
"level": "INFO",
@@ -877,6 +871,12 @@
"group": "WM_ERROR",
"at": "com\/android\/server\/wm\/WindowToken.java"
},
+ "-639217716": {
+ "message": "setFocusedApp %s displayId=%d Callers=%s",
+ "level": "INFO",
+ "group": "WM_DEBUG_FOCUS_LIGHT",
+ "at": "com\/android\/server\/wm\/DisplayContent.java"
+ },
"-635082269": {
"message": "******** booted=%b msg=%b haveBoot=%b haveApp=%b haveWall=%b wallEnabled=%b haveKeyguard=%b",
"level": "INFO",
@@ -895,12 +895,6 @@
"group": "WM_DEBUG_BOOT",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
- "-603199586": {
- "message": "Clearing focused app, displayId=%d",
- "level": "VERBOSE",
- "group": "WM_DEBUG_FOCUS_LIGHT",
- "at": "com\/android\/server\/wm\/DisplayContent.java"
- },
"-593535526": {
"message": "Binding proc %s with config %s",
"level": "VERBOSE",
@@ -919,6 +913,12 @@
"group": "WM_DEBUG_ORIENTATION",
"at": "com\/android\/server\/wm\/DisplayRotation.java"
},
+ "-561092364": {
+ "message": "onPointerDownOutsideFocusLocked called on %s",
+ "level": "INFO",
+ "group": "WM_DEBUG_FOCUS_LIGHT",
+ "at": "com\/android\/server\/wm\/WindowManagerService.java"
+ },
"-549028919": {
"message": "enableScreenIfNeededLocked: mDisplayEnabled=%b mForceDisplayEnabled=%b mShowingBootMessages=%b mSystemBooted=%b. %s",
"level": "INFO",
@@ -1201,12 +1201,6 @@
"group": "WM_DEBUG_RECENTS_ANIMATIONS",
"at": "com\/android\/server\/wm\/RecentsAnimation.java"
},
- "-96848838": {
- "message": "Gaining focus: %s",
- "level": "INFO",
- "group": "WM_DEBUG_FOCUS_LIGHT",
- "at": "com\/android\/server\/wm\/WindowManagerService.java"
- },
"-90559682": {
"message": "Config is skipping already pausing %s",
"level": "VERBOSE",
@@ -1363,6 +1357,12 @@
"group": "WM_DEBUG_STARTING_WINDOW",
"at": "com\/android\/server\/wm\/ActivityRecord.java"
},
+ "115358443": {
+ "message": "Focus changing: %s -> %s",
+ "level": "INFO",
+ "group": "WM_DEBUG_FOCUS_LIGHT",
+ "at": "com\/android\/server\/wm\/WindowManagerService.java"
+ },
"123161180": {
"message": "SEVER CHILDREN",
"level": "INFO",
@@ -1495,12 +1495,6 @@
"group": "WM_DEBUG_APP_TRANSITIONS_ANIM",
"at": "com\/android\/server\/wm\/AppTransition.java"
},
- "285317231": {
- "message": "Input focus has changed to %s",
- "level": "DEBUG",
- "group": "WM_DEBUG_FOCUS_LIGHT",
- "at": "com\/android\/server\/wm\/InputMonitor.java"
- },
"288485303": {
"message": "Attempted to set remove mode to a display that does not exist: %d",
"level": "WARN",
@@ -1537,6 +1531,12 @@
"group": "WM_SHOW_TRANSACTIONS",
"at": "com\/android\/server\/wm\/WindowSurfaceController.java"
},
+ "312030608": {
+ "message": "New topFocusedDisplayId=%d",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_FOCUS_LIGHT",
+ "at": "com\/android\/server\/wm\/RootWindowContainer.java"
+ },
"315395835": {
"message": "Trying to add window with invalid user=%d",
"level": "WARN",
@@ -1699,12 +1699,6 @@
"group": "WM_SHOW_TRANSACTIONS",
"at": "com\/android\/server\/wm\/WindowSurfaceController.java"
},
- "584499099": {
- "message": "Set focused app to: %s moveFocusNow=%b displayId=%d",
- "level": "VERBOSE",
- "group": "WM_DEBUG_FOCUS_LIGHT",
- "at": "com\/android\/server\/wm\/DisplayContent.java"
- },
"585096182": {
"message": "SURFACE isColorSpaceAgnostic=%b: %s",
"level": "INFO",
@@ -1747,6 +1741,12 @@
"group": "WM_ERROR",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
+ "620519522": {
+ "message": "findFocusedWindow: No focusable windows, display=%d",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_FOCUS_LIGHT",
+ "at": "com\/android\/server\/wm\/DisplayContent.java"
+ },
"628276090": {
"message": "Delaying app transition for screen rotation animation to finish",
"level": "VERBOSE",
@@ -1903,6 +1903,12 @@
"group": "WM_DEBUG_ADD_REMOVE",
"at": "com\/android\/server\/wm\/ActivityRecord.java"
},
+ "872933199": {
+ "message": "Changing focus from %s to %s displayId=%d Callers=%s",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_FOCUS_LIGHT",
+ "at": "com\/android\/server\/wm\/DisplayContent.java"
+ },
"873914452": {
"message": "goodToGo()",
"level": "DEBUG",
@@ -2137,12 +2143,6 @@
"group": "WM_DEBUG_ORIENTATION",
"at": "com\/android\/server\/wm\/ScreenRotationAnimation.java"
},
- "1358462645": {
- "message": "Looking for focus: %s, flags=%d, canReceive=%b",
- "level": "VERBOSE",
- "group": "WM_DEBUG_FOCUS",
- "at": "com\/android\/server\/wm\/DisplayContent.java"
- },
"1360551978": {
"message": "Trying to update display configuration for non-existing displayId=%d",
"level": "WARN",
@@ -2233,12 +2233,6 @@
"group": "WM_DEBUG_APP_TRANSITIONS_ANIM",
"at": "com\/android\/server\/wm\/AppTransitionController.java"
},
- "1469292670": {
- "message": "Changing focus from %s to %s displayId=%d Callers=%s",
- "level": "VERBOSE",
- "group": "WM_DEBUG_FOCUS_LIGHT",
- "at": "com\/android\/server\/wm\/DisplayContent.java"
- },
"1495525537": {
"message": "createWallpaperAnimations()",
"level": "DEBUG",
@@ -2677,12 +2671,6 @@
"group": "WM_DEBUG_IME",
"at": "com\/android\/server\/wm\/DisplayContent.java"
},
- "2128604122": {
- "message": "findFocusedWindow: No focusable windows.",
- "level": "VERBOSE",
- "group": "WM_DEBUG_FOCUS_LIGHT",
- "at": "com\/android\/server\/wm\/DisplayContent.java"
- },
"2128917433": {
"message": "onProposedRotationChanged, rotation=%d",
"level": "VERBOSE",
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 1c0a526..de2a7b2 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -807,7 +807,8 @@
int initResult = native_setup(new WeakReference<AudioTrack>(this), mAttributes,
sampleRate, mChannelMask, mChannelIndexMask, mAudioFormat,
mNativeBufferSizeInBytes, mDataLoadMode, session, 0 /*nativeTrackInJavaObj*/,
- offload, encapsulationMode, tunerConfiguration);
+ offload, encapsulationMode, tunerConfiguration,
+ getCurrentOpPackageName());
if (initResult != SUCCESS) {
loge("Error code "+initResult+" when initializing AudioTrack.");
return; // with mState == STATE_UNINITIALIZED
@@ -893,7 +894,8 @@
nativeTrackInJavaObj,
false /*offload*/,
ENCAPSULATION_MODE_NONE,
- null /* tunerConfiguration */);
+ null /* tunerConfiguration */,
+ "" /* opPackagename */);
if (initResult != SUCCESS) {
loge("Error code "+initResult+" when initializing AudioTrack.");
return; // with mState == STATE_UNINITIALIZED
@@ -4062,7 +4064,8 @@
Object /*AudioAttributes*/ attributes,
int[] sampleRate, int channelMask, int channelIndexMask, int audioFormat,
int buffSizeInBytes, int mode, int[] sessionId, long nativeAudioTrack,
- boolean offload, int encapsulationMode, Object tunerConfiguration);
+ boolean offload, int encapsulationMode, Object tunerConfiguration,
+ @NonNull String opPackageName);
private native final void native_finalize();
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 49e4160..36ae3ec 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -672,7 +672,8 @@
/* Native setup requires a weak reference to our object.
* It's easier to create it here than in C++.
*/
- native_setup(new WeakReference<MediaPlayer>(this));
+ native_setup(new WeakReference<MediaPlayer>(this),
+ getCurrentOpPackageName());
baseRegisterPlayer();
}
@@ -2378,7 +2379,7 @@
private native final int native_setMetadataFilter(Parcel request);
private static native final void native_init();
- private native final void native_setup(Object mediaplayer_this);
+ private native void native_setup(Object mediaplayerThis, @NonNull String opPackageName);
private native final void native_finalize();
/**
diff --git a/media/java/android/media/PlayerBase.java b/media/java/android/media/PlayerBase.java
index ee8f1b3..df5e85e 100644
--- a/media/java/android/media/PlayerBase.java
+++ b/media/java/android/media/PlayerBase.java
@@ -27,6 +27,7 @@
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.text.TextUtils;
import android.util.Log;
import com.android.internal.annotations.GuardedBy;
@@ -622,4 +623,8 @@
Log.w(className, "See the documentation of " + opName + " for what to use instead with " +
"android.media.AudioAttributes to qualify your playback use case");
}
+
+ protected String getCurrentOpPackageName() {
+ return TextUtils.emptyIfNull(ActivityThread.currentOpPackageName());
+ }
}
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index 55aac09..bd8d2e9 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -33,6 +33,7 @@
#include <utils/threads.h>
#include "jni.h"
#include <nativehelper/JNIPlatformHelp.h>
+#include <nativehelper/ScopedUtfChars.h>
#include "android_runtime/AndroidRuntime.h"
#include "android_runtime/android_view_Surface.h"
#include "android_runtime/Log.h"
@@ -944,10 +945,12 @@
}
static void
-android_media_MediaPlayer_native_setup(JNIEnv *env, jobject thiz, jobject weak_this)
+android_media_MediaPlayer_native_setup(JNIEnv *env, jobject thiz, jobject weak_this,
+ jstring opPackageName)
{
ALOGV("native_setup");
- sp<MediaPlayer> mp = new MediaPlayer();
+ ScopedUtfChars opPackageNameStr(env, opPackageName);
+ sp<MediaPlayer> mp = new MediaPlayer(opPackageNameStr.c_str());
if (mp == NULL) {
jniThrowException(env, "java/lang/RuntimeException", "Out of memory");
return;
@@ -1403,7 +1406,7 @@
{"native_setMetadataFilter", "(Landroid/os/Parcel;)I", (void *)android_media_MediaPlayer_setMetadataFilter},
{"native_getMetadata", "(ZZLandroid/os/Parcel;)Z", (void *)android_media_MediaPlayer_getMetadata},
{"native_init", "()V", (void *)android_media_MediaPlayer_native_init},
- {"native_setup", "(Ljava/lang/Object;)V", (void *)android_media_MediaPlayer_native_setup},
+ {"native_setup", "(Ljava/lang/Object;Ljava/lang/String;)V",(void *)android_media_MediaPlayer_native_setup},
{"native_finalize", "()V", (void *)android_media_MediaPlayer_native_finalize},
{"getAudioSessionId", "()I", (void *)android_media_MediaPlayer_get_audio_session_id},
{"setAudioSessionId", "(I)V", (void *)android_media_MediaPlayer_set_audio_session_id},
diff --git a/media/packages/BluetoothMidiService/Android.bp b/media/packages/BluetoothMidiService/Android.bp
index 48fc329..25c34c3 100644
--- a/media/packages/BluetoothMidiService/Android.bp
+++ b/media/packages/BluetoothMidiService/Android.bp
@@ -29,6 +29,5 @@
"src/**/*.java",
],
platform_apis: true,
- certificate: "platform",
manifest: "AndroidManifest.xml",
}
diff --git a/media/packages/BluetoothMidiService/AndroidManifest.xml b/media/packages/BluetoothMidiService/AndroidManifest.xml
index b88bf2a..fc96fd9 100644
--- a/media/packages/BluetoothMidiService/AndroidManifest.xml
+++ b/media/packages/BluetoothMidiService/AndroidManifest.xml
@@ -19,8 +19,6 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.android.bluetoothmidiservice"
- android:versionCode="1"
- android:versionName="R-initial"
>
<uses-sdk android:minSdkVersion="29" android:targetSdkVersion="29" />
diff --git a/media/packages/BluetoothMidiService/AndroidManifestBase.xml b/media/packages/BluetoothMidiService/AndroidManifestBase.xml
index ebe62b0..bfb0546 100644
--- a/media/packages/BluetoothMidiService/AndroidManifestBase.xml
+++ b/media/packages/BluetoothMidiService/AndroidManifestBase.xml
@@ -18,8 +18,6 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.bluetoothmidiservice"
- android:versionCode="1"
- android:versionName="R-initial"
>
<uses-sdk android:minSdkVersion="29" android:targetSdkVersion="29" />
<application
diff --git a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java
index 3eea513..51fda96 100644
--- a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java
+++ b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java
@@ -52,10 +52,10 @@
import com.android.systemui.statusbar.NotificationLockscreenUserManagerImpl;
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.KeyguardEnvironmentImpl;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.phone.ShadeControllerImpl;
import com.android.systemui.statusbar.policy.BatteryController;
@@ -92,7 +92,7 @@
Context context,
StatusBarStateController statusBarStateController,
KeyguardBypassController bypassController,
- NotificationGroupManager groupManager,
+ GroupMembershipManager groupManager,
ConfigurationController configurationController) {
return new HeadsUpManagerPhone(context, statusBarStateController, bypassController,
groupManager, configurationController);
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/CarDeviceProvisionedControllerImpl.java b/packages/CarSystemUI/src/com/android/systemui/car/CarDeviceProvisionedControllerImpl.java
index a2ba880..fef0324 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/CarDeviceProvisionedControllerImpl.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/CarDeviceProvisionedControllerImpl.java
@@ -16,20 +16,19 @@
package com.android.systemui.car;
+import android.annotation.NonNull;
import android.app.ActivityManager;
import android.car.settings.CarSettings;
-import android.content.ContentResolver;
-import android.content.Context;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Handler;
-import android.provider.Settings;
-import com.android.systemui.Dependency;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.statusbar.policy.DeviceProvisionedControllerImpl;
+import com.android.systemui.util.settings.GlobalSettings;
+import com.android.systemui.util.settings.SecureSettings;
import javax.inject.Inject;
@@ -40,30 +39,33 @@
@SysUISingleton
public class CarDeviceProvisionedControllerImpl extends DeviceProvisionedControllerImpl implements
CarDeviceProvisionedController {
- private static final Uri USER_SETUP_IN_PROGRESS_URI = Settings.Secure.getUriFor(
- CarSettings.Secure.KEY_SETUP_WIZARD_IN_PROGRESS);
- private final ContentObserver mCarSettingsObserver = new ContentObserver(
- Dependency.get(Dependency.MAIN_HANDLER)) {
-
- @Override
- public void onChange(boolean selfChange, Uri uri, int flags) {
- if (USER_SETUP_IN_PROGRESS_URI.equals(uri)) {
- notifyUserSetupInProgressChanged();
- }
- }
- };
- private final ContentResolver mContentResolver;
+ private final Uri mUserSetupInProgressUri;
+ private final ContentObserver mCarSettingsObserver;
+ private final Handler mMainHandler;
+ private final SecureSettings mSecureSettings;
@Inject
- public CarDeviceProvisionedControllerImpl(Context context, @Main Handler mainHandler,
- BroadcastDispatcher broadcastDispatcher) {
- super(context, mainHandler, broadcastDispatcher);
- mContentResolver = context.getContentResolver();
+ public CarDeviceProvisionedControllerImpl(@Main Handler mainHandler,
+ BroadcastDispatcher broadcastDispatcher, GlobalSettings globalSetting,
+ SecureSettings secureSettings) {
+ super(mainHandler, broadcastDispatcher, globalSetting, secureSettings);
+ mMainHandler = mainHandler;
+ mSecureSettings = secureSettings;
+ mUserSetupInProgressUri = mSecureSettings.getUriFor(
+ CarSettings.Secure.KEY_SETUP_WIZARD_IN_PROGRESS);
+ mCarSettingsObserver = new ContentObserver(mMainHandler) {
+ @Override
+ public void onChange(boolean selfChange, Uri uri, int flags) {
+ if (mUserSetupInProgressUri.equals(uri)) {
+ notifyUserSetupInProgressChanged();
+ }
+ }
+ };
}
@Override
public boolean isUserSetupInProgress(int user) {
- return Settings.Secure.getIntForUser(mContentResolver,
+ return mSecureSettings.getIntForUser(
CarSettings.Secure.KEY_SETUP_WIZARD_IN_PROGRESS, /* def= */ 0, user) != 0;
}
@@ -73,7 +75,7 @@
}
@Override
- public void addCallback(DeviceProvisionedListener listener) {
+ public void addCallback(@NonNull DeviceProvisionedListener listener) {
super.addCallback(listener);
if (listener instanceof CarDeviceProvisionedListener) {
((CarDeviceProvisionedListener) listener).onUserSetupInProgressChanged();
@@ -82,9 +84,9 @@
@Override
protected void startListening(int user) {
- mContentResolver.registerContentObserver(
- USER_SETUP_IN_PROGRESS_URI, /* notifyForDescendants= */ true, mCarSettingsObserver,
- user);
+ mSecureSettings.registerContentObserverForUser(
+ mUserSetupInProgressUri, /* notifyForDescendants= */ true,
+ mCarSettingsObserver, user);
// The SUW Flag observer is registered before super.startListening() so that the observer is
// in place before DeviceProvisionedController starts to track user switches which avoids
// an edge case where our observer gets registered twice.
@@ -94,16 +96,16 @@
@Override
protected void stopListening() {
super.stopListening();
- mContentResolver.unregisterContentObserver(mCarSettingsObserver);
+ mSecureSettings.unregisterContentObserver(mCarSettingsObserver);
}
@Override
public void onUserSwitched(int newUserId) {
super.onUserSwitched(newUserId);
- mContentResolver.unregisterContentObserver(mCarSettingsObserver);
- mContentResolver.registerContentObserver(
- USER_SETUP_IN_PROGRESS_URI, /* notifyForDescendants= */ true, mCarSettingsObserver,
- newUserId);
+ mSecureSettings.unregisterContentObserver(mCarSettingsObserver);
+ mSecureSettings.registerContentObserverForUser(
+ mUserSetupInProgressUri, /* notifyForDescendants= */ true,
+ mCarSettingsObserver, newUserId);
}
private void notifyUserSetupInProgressChanged() {
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/keyguard/CarKeyguardViewController.java b/packages/CarSystemUI/src/com/android/systemui/car/keyguard/CarKeyguardViewController.java
index 276ddfb..dadbc22 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/keyguard/CarKeyguardViewController.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/keyguard/CarKeyguardViewController.java
@@ -18,7 +18,6 @@
import android.car.Car;
import android.car.user.CarUserManager;
-import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
@@ -28,20 +27,17 @@
import androidx.annotation.VisibleForTesting;
-import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardViewController;
import com.android.keyguard.ViewMediatorCallback;
+import com.android.keyguard.dagger.KeyguardBouncerComponent;
import com.android.systemui.R;
-import com.android.systemui.SystemUIFactory;
import com.android.systemui.car.CarServiceProvider;
import com.android.systemui.car.navigationbar.CarNavigationBarController;
import com.android.systemui.car.window.OverlayViewController;
import com.android.systemui.car.window.OverlayViewGlobalStateController;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.keyguard.DismissCallbackRegistry;
-import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.statusbar.phone.BiometricUnlockController;
import com.android.systemui.statusbar.phone.KeyguardBouncer;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
@@ -63,18 +59,14 @@
private static final String TAG = "CarKeyguardViewController";
private static final boolean DEBUG = true;
- private final Context mContext;
private final Handler mHandler;
private final CarServiceProvider mCarServiceProvider;
private final KeyguardStateController mKeyguardStateController;
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
private final Lazy<BiometricUnlockController> mBiometricUnlockControllerLazy;
- private final LockPatternUtils mLockPatternUtils;
- private final FalsingManager mFalsingManager;
- private final Lazy<KeyguardBypassController> mKeyguardBypassControllerLazy;
- private final DismissCallbackRegistry mDismissCallbackRegistry;
private final ViewMediatorCallback mViewMediatorCallback;
private final CarNavigationBarController mCarNavigationBarController;
+ private final KeyguardBouncerComponent.Factory mKeyguardBouncerComponentFactory;
// Needed to instantiate mBouncer.
private final KeyguardBouncer.BouncerExpansionCallback
mExpansionCallback = new KeyguardBouncer.BouncerExpansionCallback() {
@@ -107,7 +99,6 @@
@Inject
public CarKeyguardViewController(
- Context context,
@Main Handler mainHandler,
CarServiceProvider carServiceProvider,
OverlayViewGlobalStateController overlayViewGlobalStateController,
@@ -116,26 +107,18 @@
Lazy<BiometricUnlockController> biometricUnlockControllerLazy,
ViewMediatorCallback viewMediatorCallback,
CarNavigationBarController carNavigationBarController,
- /* The params below are only used to reuse KeyguardBouncer */
- LockPatternUtils lockPatternUtils,
- DismissCallbackRegistry dismissCallbackRegistry,
- FalsingManager falsingManager,
- Lazy<KeyguardBypassController> keyguardBypassControllerLazy) {
+ KeyguardBouncerComponent.Factory keyguardBouncerComponentFactory) {
super(R.id.keyguard_stub, overlayViewGlobalStateController);
- mContext = context;
mHandler = mainHandler;
mCarServiceProvider = carServiceProvider;
mKeyguardStateController = keyguardStateController;
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mBiometricUnlockControllerLazy = biometricUnlockControllerLazy;
- mLockPatternUtils = lockPatternUtils;
- mFalsingManager = falsingManager;
- mKeyguardBypassControllerLazy = keyguardBypassControllerLazy;
- mDismissCallbackRegistry = dismissCallbackRegistry;
mViewMediatorCallback = viewMediatorCallback;
mCarNavigationBarController = carNavigationBarController;
+ mKeyguardBouncerComponentFactory = keyguardBouncerComponentFactory;
registerUserSwitchedListener();
}
@@ -147,11 +130,9 @@
@Override
public void onFinishInflate() {
- mBouncer = SystemUIFactory.getInstance().createKeyguardBouncer(mContext,
- mViewMediatorCallback, mLockPatternUtils,
- getLayout().findViewById(R.id.keyguard_container), mDismissCallbackRegistry,
- mExpansionCallback, mKeyguardStateController, mFalsingManager,
- mKeyguardBypassControllerLazy.get());
+ mBouncer = mKeyguardBouncerComponentFactory
+ .build(getLayout().findViewById(R.id.keyguard_container), mExpansionCallback)
+ .createKeyguardBouncer();
mBiometricUnlockControllerLazy.get().setKeyguardViewController(this);
}
@@ -359,9 +340,8 @@
public void registerStatusBar(StatusBar statusBar, ViewGroup container,
NotificationPanelViewController notificationPanelViewController,
BiometricUnlockController biometricUnlockController,
- DismissCallbackRegistry dismissCallbackRegistry, ViewGroup lockIconContainer,
- View notificationContainer, KeyguardBypassController bypassController,
- FalsingManager falsingManager) {
+ ViewGroup lockIconContainer,
+ View notificationContainer, KeyguardBypassController bypassController) {
// no-op
}
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/notification/NotificationPanelViewController.java b/packages/CarSystemUI/src/com/android/systemui/car/notification/NotificationPanelViewController.java
index 38e1a48..fe4cba8 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/notification/NotificationPanelViewController.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/notification/NotificationPanelViewController.java
@@ -91,7 +91,6 @@
private RecyclerView mNotificationList;
private NotificationViewController mNotificationViewController;
- private boolean mIsTracking;
private boolean mNotificationListAtEnd;
private float mFirstTouchDownOnGlassPane;
private boolean mNotificationListAtEndAtTimeOfTouch;
@@ -306,7 +305,7 @@
mFirstTouchDownOnGlassPane = event.getRawX();
mNotificationListAtEndAtTimeOfTouch = mNotificationListAtEnd;
// Reset the tracker when there is a touch down on the glass pane.
- mIsTracking = false;
+ setIsTracking(false);
// Pass the down event to gesture detector so that it knows where the touch event
// started.
closeGestureDetector.onTouchEvent(event);
@@ -341,15 +340,15 @@
// If the card is swiping we should not allow the notification shade to close.
// Hence setting mNotificationListAtEndAtTimeOfTouch to false will stop that
- // for us. We are also checking for mIsTracking because while swiping the
+ // for us. We are also checking for isTracking() because while swiping the
// notification shade to close if the user goes a bit horizontal while swiping
// upwards then also this should close.
- if (mIsNotificationCardSwiping && !mIsTracking) {
+ if (mIsNotificationCardSwiping && !isTracking()) {
mNotificationListAtEndAtTimeOfTouch = false;
}
boolean handled = closeGestureDetector.onTouchEvent(event);
- boolean isTracking = mIsTracking;
+ boolean isTracking = isTracking();
Rect rect = getLayout().getClipBounds();
float clippedHeight = 0;
if (rect != null) {
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/UserGridRecyclerView.java b/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/UserGridRecyclerView.java
index 5bd8797..023b5b4 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/UserGridRecyclerView.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/UserGridRecyclerView.java
@@ -131,7 +131,7 @@
}
private List<UserInfo> getUsersForUserGrid() {
- return mUserManager.getUsers(/* excludeDying= */ true)
+ return mUserManager.getAliveUsers()
.stream()
.filter(UserInfo::supportsSwitchToByUser)
.collect(Collectors.toList());
@@ -338,7 +338,7 @@
maxSupportedUsers -= 1;
}
- List<UserInfo> users = mUserManager.getUsers(/* excludeDying= */ true);
+ List<UserInfo> users = mUserManager.getAliveUsers();
// Count all users that are managed profiles of another user.
int managedProfilesCount = 0;
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayPanelViewController.java b/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayPanelViewController.java
index bde31f1..1b00c63 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayPanelViewController.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayPanelViewController.java
@@ -297,14 +297,17 @@
float from = getCurrentStartPosition(rect);
if (from != to) {
animate(from, to, velocity, isClosing);
- return;
}
+
+ // If we swipe down the notification panel all the way to the bottom of the screen
+ // (i.e. from == to), then we have finished animating the panel.
+ return;
}
// We will only be here if the shade is being opened programmatically or via button when
// height of the layout was not calculated.
- ViewTreeObserver notificationTreeObserver = getLayout().getViewTreeObserver();
- notificationTreeObserver.addOnGlobalLayoutListener(
+ ViewTreeObserver panelTreeObserver = getLayout().getViewTreeObserver();
+ panelTreeObserver.addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
@@ -507,6 +510,11 @@
return mIsTracking;
}
+ /** Sets whether the panel is currently tracking or not. */
+ protected final void setIsTracking(boolean isTracking) {
+ mIsTracking = isTracking;
+ }
+
/** Returns {@code true} if the panel is currently animating. */
protected final boolean isAnimating() {
return mIsAnimating;
@@ -545,7 +553,7 @@
}
setPanelVisible(true);
- // clips the view for the notification shade when the user scrolls to open.
+ // clips the view for the panel when the user scrolls to open.
setViewClipBounds((int) event2.getRawY());
// Initially the scroll starts with height being zero. This checks protects from divide
@@ -600,11 +608,11 @@
boolean isInClosingDirection = mAnimateDirection * distanceY > 0;
// This check is to figure out if onScroll was called while swiping the card at
- // bottom of the list. At that time we should not allow notification shade to
+ // bottom of the panel. At that time we should not allow panel to
// close. We are also checking for the upwards swipe gesture here because it is
- // possible if a user is closing the notification shade and while swiping starts
+ // possible if a user is closing the panel and while swiping starts
// to open again but does not fling. At that time we should allow the
- // notification shade to close fully or else it would stuck in between.
+ // panel to close fully or else it would stuck in between.
if (Math.abs(getLayout().getHeight() - y)
> SWIPE_DOWN_MIN_DISTANCE && isInClosingDirection) {
setViewClipBounds((int) y);
diff --git a/packages/CarSystemUI/tests/src/com/android/systemui/car/keyguard/CarKeyguardViewControllerTest.java b/packages/CarSystemUI/tests/src/com/android/systemui/car/keyguard/CarKeyguardViewControllerTest.java
index 62dc236..63d4004 100644
--- a/packages/CarSystemUI/tests/src/com/android/systemui/car/keyguard/CarKeyguardViewControllerTest.java
+++ b/packages/CarSystemUI/tests/src/com/android/systemui/car/keyguard/CarKeyguardViewControllerTest.java
@@ -26,7 +26,6 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import android.content.Context;
import android.os.Handler;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
@@ -35,20 +34,17 @@
import androidx.test.filters.SmallTest;
-import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.ViewMediatorCallback;
+import com.android.keyguard.dagger.KeyguardBouncerComponent;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.car.CarServiceProvider;
import com.android.systemui.car.CarSystemUiTest;
import com.android.systemui.car.navigationbar.CarNavigationBarController;
import com.android.systemui.car.window.OverlayViewGlobalStateController;
-import com.android.systemui.keyguard.DismissCallbackRegistry;
-import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.statusbar.phone.BiometricUnlockController;
import com.android.systemui.statusbar.phone.KeyguardBouncer;
-import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import org.junit.Before;
@@ -58,31 +54,36 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import dagger.Lazy;
-
@CarSystemUiTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
@SmallTest
public class CarKeyguardViewControllerTest extends SysuiTestCase {
- private TestableCarKeyguardViewController mCarKeyguardViewController;
+ private CarKeyguardViewController mCarKeyguardViewController;
@Mock
private OverlayViewGlobalStateController mOverlayViewGlobalStateController;
@Mock
- private KeyguardBouncer mBouncer;
- @Mock
- private CarNavigationBarController mCarNavigationBarController;
- @Mock
private CarKeyguardViewController.OnKeyguardCancelClickedListener mCancelClickedListener;
+ @Mock
+ private KeyguardBouncerComponent.Factory mKeyguardBouncerComponentFactory;
+ @Mock
+ private KeyguardBouncerComponent mKeyguardBouncerComponent;
+ @Mock
+ private KeyguardBouncer mBouncer;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- mCarKeyguardViewController = new TestableCarKeyguardViewController(
- mContext,
+ when(mKeyguardBouncerComponentFactory.build(
+ any(ViewGroup.class),
+ any(KeyguardBouncer.BouncerExpansionCallback.class)))
+ .thenReturn(mKeyguardBouncerComponent);
+ when(mKeyguardBouncerComponent.createKeyguardBouncer()).thenReturn(mBouncer);
+
+ mCarKeyguardViewController = new CarKeyguardViewController(
Handler.getMain(),
mock(CarServiceProvider.class),
mOverlayViewGlobalStateController,
@@ -91,10 +92,7 @@
() -> mock(BiometricUnlockController.class),
mock(ViewMediatorCallback.class),
mock(CarNavigationBarController.class),
- mock(LockPatternUtils.class),
- mock(DismissCallbackRegistry.class),
- mock(FalsingManager.class),
- () -> mock(KeyguardBypassController.class)
+ mKeyguardBouncerComponentFactory
);
mCarKeyguardViewController.inflate((ViewGroup) LayoutInflater.from(mContext).inflate(
R.layout.sysui_overlay_window, /* root= */ null));
@@ -202,33 +200,4 @@
verify(mBouncer).hide(/* destroyView= */ true);
}
-
- private class TestableCarKeyguardViewController extends CarKeyguardViewController {
-
- TestableCarKeyguardViewController(Context context,
- Handler mainHandler,
- CarServiceProvider carServiceProvider,
- OverlayViewGlobalStateController overlayViewGlobalStateController,
- KeyguardStateController keyguardStateController,
- KeyguardUpdateMonitor keyguardUpdateMonitor,
- Lazy<BiometricUnlockController> biometricUnlockControllerLazy,
- ViewMediatorCallback viewMediatorCallback,
- CarNavigationBarController carNavigationBarController,
- LockPatternUtils lockPatternUtils,
- DismissCallbackRegistry dismissCallbackRegistry,
- FalsingManager falsingManager,
- Lazy<KeyguardBypassController> keyguardBypassControllerLazy) {
- super(context, mainHandler, carServiceProvider, overlayViewGlobalStateController,
- keyguardStateController, keyguardUpdateMonitor, biometricUnlockControllerLazy,
- viewMediatorCallback, carNavigationBarController, lockPatternUtils,
- dismissCallbackRegistry, falsingManager, keyguardBypassControllerLazy);
- }
-
- @Override
- public void onFinishInflate() {
- super.onFinishInflate();
- setKeyguardBouncer(CarKeyguardViewControllerTest.this.mBouncer);
- }
- }
-
}
diff --git a/packages/CompanionDeviceManager/TEST_MAPPING b/packages/CompanionDeviceManager/TEST_MAPPING
new file mode 100644
index 0000000..63f54fa
--- /dev/null
+++ b/packages/CompanionDeviceManager/TEST_MAPPING
@@ -0,0 +1,12 @@
+{
+ "presubmit": [
+ {
+ "name": "CtsOsTestCases",
+ "options": [
+ {
+ "include-filter": "android.os.cts.CompanionDeviceManagerTest"
+ }
+ ]
+ }
+ ]
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
index bc58bfc..c57d4ad 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
@@ -13,6 +13,7 @@
import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY;
import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import android.content.Context;
import android.content.Intent;
@@ -250,6 +251,10 @@
statusLabel = mContext.getString(R.string.wifi_status_no_internet);
}
return;
+ } else if (!isDefaultNetwork && mDefaultNetworkCapabilities != null
+ && mDefaultNetworkCapabilities.hasTransport(TRANSPORT_CELLULAR)) {
+ statusLabel = mContext.getString(R.string.wifi_connected_low_quality);
+ return;
}
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 807fbed..9c92b46 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -2576,7 +2576,7 @@
public void syncSsaidTableOnStart() {
synchronized (mLock) {
// Verify that each user's packages and ssaid's are in sync.
- for (UserInfo user : mUserManager.getUsers(true)) {
+ for (UserInfo user : mUserManager.getAliveUsers()) {
// Get all uids for the user's packages.
final List<PackageInfo> packages;
try {
@@ -3007,7 +3007,7 @@
final long identity = Binder.clearCallingIdentity();
try {
- List<UserInfo> users = mUserManager.getUsers(true);
+ List<UserInfo> users = mUserManager.getAliveUsers();
final int userCount = users.size();
for (int i = 0; i < userCount; i++) {
@@ -3244,7 +3244,7 @@
// is a singleton generation entry for the global settings which
// is already incremented be the caller.
final Uri uri = getNotificationUriFor(key, name);
- final List<UserInfo> users = mUserManager.getUsers(/*excludeDying*/ true);
+ final List<UserInfo> users = mUserManager.getAliveUsers();
for (int i = 0; i < users.size(); i++) {
final int userId = users.get(i).id;
if (mUserManager.isUserRunning(UserHandle.of(userId))) {
@@ -3255,7 +3255,7 @@
}
private void notifyLocationChangeForRunningUsers() {
- final List<UserInfo> users = mUserManager.getUsers(/*excludeDying=*/ true);
+ final List<UserInfo> users = mUserManager.getAliveUsers();
for (int i = 0; i < users.size(); i++) {
final int userId = users.get(i).id;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index b048333..0517227 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -796,16 +796,6 @@
securityMode != SecurityMode.None && newView.needsInput());
}
- private KeyguardSecurityViewFlipper getFlipper() {
- for (int i = 0; i < getChildCount(); i++) {
- View child = getChildAt(i);
- if (child instanceof KeyguardSecurityViewFlipper) {
- return (KeyguardSecurityViewFlipper) child;
- }
- }
- return null;
- }
-
private KeyguardSecurityCallback mCallback = new KeyguardSecurityCallback() {
public void userActivity() {
if (mSecurityCallback != null) {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardViewController.java
index 6a90d00..9766ee1 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardViewController.java
@@ -21,9 +21,7 @@
import android.view.ViewGroup;
import android.view.ViewRootImpl;
-import com.android.systemui.keyguard.DismissCallbackRegistry;
import com.android.systemui.keyguard.KeyguardViewMediator;
-import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.statusbar.phone.BiometricUnlockController;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.NotificationPanelViewController;
@@ -180,22 +178,18 @@
/**
* Registers the StatusBar to which this Keyguard View is mounted.
- *
* @param statusBar
* @param container
* @param notificationPanelViewController
* @param biometricUnlockController
- * @param dismissCallbackRegistry
* @param lockIconContainer
* @param notificationContainer
* @param bypassController
- * @param falsingManager
*/
void registerStatusBar(StatusBar statusBar,
ViewGroup container,
NotificationPanelViewController notificationPanelViewController,
BiometricUnlockController biometricUnlockController,
- DismissCallbackRegistry dismissCallbackRegistry,
ViewGroup lockIconContainer, View notificationContainer,
- KeyguardBypassController bypassController, FalsingManager falsingManager);
+ KeyguardBypassController bypassController);
}
diff --git a/packages/SystemUI/src/com/android/keyguard/dagger/ContainerView.java b/packages/SystemUI/src/com/android/keyguard/dagger/ContainerView.java
new file mode 100644
index 0000000..e65f19d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/keyguard/dagger/ContainerView.java
@@ -0,0 +1,30 @@
+/*
+ * 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.keyguard.dagger;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+
+import javax.inject.Qualifier;
+
+@Qualifier
+@Documented
+@Retention(RUNTIME)
+public @interface ContainerView {
+}
diff --git a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerComponent.java b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerComponent.java
new file mode 100644
index 0000000..84deaca
--- /dev/null
+++ b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerComponent.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.keyguard.dagger;
+
+import android.view.ViewGroup;
+
+import com.android.systemui.statusbar.phone.KeyguardBouncer;
+
+import dagger.BindsInstance;
+import dagger.Subcomponent;
+
+/**
+ * Dagger Subcomponent for the {@link KeyguardBouncer}.
+ */
+@Subcomponent
+@KeyguardBouncerScope
+public interface KeyguardBouncerComponent {
+ /** Simple factory for {@link KeyguardBouncerComponent}. */
+ @Subcomponent.Factory
+ interface Factory {
+ KeyguardBouncerComponent build(
+ @BindsInstance @ContainerView ViewGroup container,
+ @BindsInstance KeyguardBouncer.BouncerExpansionCallback bouncerExpansionCallback);
+ }
+
+ /** */
+ KeyguardBouncer createKeyguardBouncer();
+}
diff --git a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerScope.java b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerScope.java
new file mode 100644
index 0000000..207ac28
--- /dev/null
+++ b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerScope.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.keyguard.dagger;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+
+import javax.inject.Scope;
+
+/**
+ * Scope annotation for singleton items within the StatusBarComponent.
+ */
+@Documented
+@Retention(RUNTIME)
+@Scope
+public @interface KeyguardBouncerScope {}
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index 27809b5..ed78c94 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -77,6 +77,7 @@
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationEntryManager.KeyguardEnvironment;
import com.android.systemui.statusbar.notification.NotificationFilter;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.NotificationBlockingHelperManager;
@@ -88,7 +89,6 @@
import com.android.systemui.statusbar.phone.LockscreenGestureLogger;
import com.android.systemui.statusbar.phone.ManagedProfileController;
import com.android.systemui.statusbar.phone.NotificationGroupAlertTransferHelper;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.phone.StatusBarIconController;
@@ -276,7 +276,7 @@
@Inject Lazy<StatusBarStateController> mStatusBarStateController;
@Inject Lazy<NotificationLockscreenUserManager> mNotificationLockscreenUserManager;
@Inject Lazy<NotificationGroupAlertTransferHelper> mNotificationGroupAlertTransferHelper;
- @Inject Lazy<NotificationGroupManager> mNotificationGroupManager;
+ @Inject Lazy<NotificationGroupManagerLegacy> mNotificationGroupManager;
@Inject Lazy<VisualStabilityManager> mVisualStabilityManager;
@Inject Lazy<NotificationGutsManager> mNotificationGutsManager;
@Inject Lazy<NotificationMediaManager> mNotificationMediaManager;
@@ -468,7 +468,7 @@
mProviders.put(NotificationLockscreenUserManager.class,
mNotificationLockscreenUserManager::get);
mProviders.put(VisualStabilityManager.class, mVisualStabilityManager::get);
- mProviders.put(NotificationGroupManager.class, mNotificationGroupManager::get);
+ mProviders.put(NotificationGroupManagerLegacy.class, mNotificationGroupManager::get);
mProviders.put(NotificationGroupAlertTransferHelper.class,
mNotificationGroupAlertTransferHelper::get);
mProviders.put(NotificationMediaManager.class, mNotificationMediaManager::get);
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index f5c3649..f159499 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -19,25 +19,16 @@
import android.content.Context;
import android.content.res.Resources;
import android.os.Handler;
-import android.os.Looper;
import android.util.Log;
-import android.view.ViewGroup;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.widget.LockPatternUtils;
-import com.android.keyguard.KeyguardUpdateMonitor;
-import com.android.keyguard.ViewMediatorCallback;
import com.android.systemui.dagger.DaggerGlobalRootComponent;
import com.android.systemui.dagger.GlobalRootComponent;
import com.android.systemui.dagger.SysUIComponent;
import com.android.systemui.dagger.WMComponent;
-import com.android.systemui.keyguard.DismissCallbackRegistry;
-import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.screenshot.ScreenshotNotificationSmartActionsProvider;
-import com.android.systemui.statusbar.phone.KeyguardBouncer;
-import com.android.systemui.statusbar.phone.KeyguardBypassController;
-import com.android.systemui.statusbar.policy.KeyguardStateController;
+import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
/**
@@ -83,11 +74,16 @@
public SystemUIFactory() {}
- private void init(Context context) {
+ private void init(Context context) throws ExecutionException, InterruptedException {
mRootComponent = buildGlobalRootComponent(context);
+ // Stand up WMComponent
mWMComponent = mRootComponent.getWMComponentBuilder().build();
- // TODO: use WMComponent to pass APIs into the SysUIComponent.
- mSysUIComponent = mRootComponent.getSysUIComponent().build();
+
+ // And finally, retrieve whatever SysUI needs from WMShell and build SysUI.
+ // TODO: StubAPIClass is just a placeholder.
+ mSysUIComponent = mRootComponent.getSysUIComponent()
+ .setStubAPIClass(mWMComponent.createStubAPIClass())
+ .build();
// Every other part of our codebase currently relies on Dependency, so we
// really need to ensure the Dependency gets initialized early on.
@@ -101,10 +97,15 @@
.build();
}
+
public GlobalRootComponent getRootComponent() {
return mRootComponent;
}
+ public WMComponent getWMComponent() {
+ return mWMComponent;
+ }
+
public SysUIComponent getSysUIComponent() {
return mSysUIComponent;
}
@@ -129,17 +130,4 @@
Handler uiHandler) {
return new ScreenshotNotificationSmartActionsProvider();
}
-
- public KeyguardBouncer createKeyguardBouncer(Context context, ViewMediatorCallback callback,
- LockPatternUtils lockPatternUtils, ViewGroup container,
- DismissCallbackRegistry dismissCallbackRegistry,
- KeyguardBouncer.BouncerExpansionCallback expansionCallback,
- KeyguardStateController keyguardStateController, FalsingManager falsingManager,
- KeyguardBypassController bypassController) {
- return new KeyguardBouncer(context, callback, lockPatternUtils, container,
- dismissCallbackRegistry, falsingManager,
- expansionCallback, keyguardStateController,
- Dependency.get(KeyguardUpdateMonitor.class), bypassController,
- new Handler(Looper.getMainLooper()));
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index 9e9d85a..c81b7ce 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -104,11 +104,11 @@
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.coordinator.BubbleCoordinator;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.ScrimController;
import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.phone.StatusBar;
@@ -164,7 +164,7 @@
private final BubbleTaskStackListener mTaskStackListener;
private BubbleExpandListener mExpandListener;
@Nullable private BubbleStackView.SurfaceSynchronizer mSurfaceSynchronizer;
- private final NotificationGroupManager mNotificationGroupManager;
+ private final NotificationGroupManagerLegacy mNotificationGroupManager;
private final ShadeController mShadeController;
private final FloatingContentCoordinator mFloatingContentCoordinator;
private final BubbleDataRepository mDataRepository;
@@ -355,7 +355,7 @@
NotificationInterruptStateProvider interruptionStateProvider,
ZenModeController zenModeController,
NotificationLockscreenUserManager notifUserManager,
- NotificationGroupManager groupManager,
+ NotificationGroupManagerLegacy groupManager,
NotificationEntryManager entryManager,
NotifPipeline notifPipeline,
FeatureFlags featureFlags,
@@ -588,11 +588,11 @@
}
});
- mNotificationGroupManager.addOnGroupChangeListener(
- new NotificationGroupManager.OnGroupChangeListener() {
+ mNotificationGroupManager.registerGroupChangeListener(
+ new NotificationGroupManagerLegacy.OnGroupChangeListener() {
@Override
public void onGroupSuppressionChanged(
- NotificationGroupManager.NotificationGroup group,
+ NotificationGroupManagerLegacy.NotificationGroup group,
boolean suppressed) {
// More notifications could be added causing summary to no longer
// be suppressed -- in this case need to remove the key.
@@ -650,8 +650,7 @@
// 3. User removes all bubbles
// 4. We expect all the removed bubbles AND the summary (note: the summary was
// never added to the suppressedSummary list in BubbleData, so we add this check)
- NotificationEntry summary =
- mNotificationGroupManager.getLogicalGroupSummary(entry.getSbn());
+ NotificationEntry summary = mNotificationGroupManager.getLogicalGroupSummary(entry);
if (summary != null) {
ArrayList<NotificationEntry> summaryChildren =
mNotificationGroupManager.getLogicalChildren(summary.getSbn());
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/dagger/BubbleModule.java b/packages/SystemUI/src/com/android/systemui/bubbles/dagger/BubbleModule.java
index eecc41c..9efc3c2 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/dagger/BubbleModule.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/dagger/BubbleModule.java
@@ -34,8 +34,8 @@
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.ZenModeController;
@@ -62,7 +62,7 @@
NotificationInterruptStateProvider interruptionStateProvider,
ZenModeController zenModeController,
NotificationLockscreenUserManager notifUserManager,
- NotificationGroupManager groupManager,
+ NotificationGroupManagerLegacy groupManager,
NotificationEntryManager entryManager,
NotifPipeline notifPipeline,
FeatureFlags featureFlags,
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/GlobalModule.java b/packages/SystemUI/src/com/android/systemui/dagger/GlobalModule.java
index fd4a409..c5dc8cc 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/GlobalModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/GlobalModule.java
@@ -16,6 +16,8 @@
package com.android.systemui.dagger;
+import com.android.systemui.util.concurrency.GlobalConcurrencyModule;
+
import dagger.Module;
/**
@@ -33,6 +35,8 @@
*
* Please use discretion when adding things to the global scope.
*/
-@Module(includes = {FrameworkServicesModule.class})
+@Module(includes = {
+ FrameworkServicesModule.class,
+ GlobalConcurrencyModule.class})
public class GlobalModule {
}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/GlobalRootComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/GlobalRootComponent.java
index 36fd337..00fdf55 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/GlobalRootComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/GlobalRootComponent.java
@@ -18,6 +18,8 @@
import android.content.Context;
+import com.android.systemui.util.concurrency.ThreadFactory;
+
import javax.inject.Singleton;
import dagger.BindsInstance;
@@ -53,4 +55,9 @@
* Builder for a SysuiComponent.
*/
SysUIComponent.Builder getSysUIComponent();
+
+ /**
+ * Build a {@link ThreadFactory}.
+ */
+ ThreadFactory createThreadFactory();
}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
index a8ed043..2622593 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
@@ -26,6 +26,7 @@
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.util.InjectionInflationController;
+import dagger.BindsInstance;
import dagger.Subcomponent;
/**
@@ -46,6 +47,9 @@
*/
@Subcomponent.Builder
interface Builder {
+ @BindsInstance
+ Builder setStubAPIClass(WMComponent.StubAPIClass stubAPIClass);
+
SysUIComponent build();
}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java
index a021114..2c0b04f 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java
@@ -46,11 +46,11 @@
import com.android.systemui.statusbar.NotificationLockscreenUserManagerImpl;
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
import com.android.systemui.statusbar.phone.DozeServiceHost;
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.KeyguardEnvironmentImpl;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.NotificationShadeWindowControllerImpl;
import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.phone.ShadeControllerImpl;
@@ -143,7 +143,7 @@
Context context,
StatusBarStateController statusBarStateController,
KeyguardBypassController bypassController,
- NotificationGroupManager groupManager,
+ GroupMembershipManager groupManager,
ConfigurationController configurationController) {
return new HeadsUpManagerPhone(context, statusBarStateController, bypassController,
groupManager, configurationController);
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
index 3afe721..8f4e738 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
@@ -16,6 +16,7 @@
package com.android.systemui.dagger;
+import com.android.keyguard.dagger.KeyguardBouncerComponent;
import com.android.systemui.BootCompleteCache;
import com.android.systemui.BootCompleteCacheImpl;
import com.android.systemui.appops.dagger.AppOpsModule;
@@ -42,7 +43,7 @@
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.dagger.StatusBarPolicyModule;
import com.android.systemui.tuner.dagger.TunerModule;
-import com.android.systemui.util.concurrency.ConcurrencyModule;
+import com.android.systemui.util.concurrency.SysUIConcurrencyModule;
import com.android.systemui.util.dagger.UtilModule;
import com.android.systemui.util.sensors.SensorModule;
import com.android.systemui.util.settings.SettingsUtilModule;
@@ -62,7 +63,6 @@
@Module(includes = {
AppOpsModule.class,
AssistModule.class,
- ConcurrencyModule.class,
ControlsModule.class,
DemoModeModule.class,
LogModule.class,
@@ -74,6 +74,7 @@
SettingsModule.class,
SettingsUtilModule.class,
StatusBarPolicyModule.class,
+ SysUIConcurrencyModule.class,
TunerModule.class,
UtilModule.class,
VolumeModule.class
@@ -82,6 +83,7 @@
NotificationRowComponent.class,
DozeComponent.class,
ExpandableNotificationRowComponent.class,
+ KeyguardBouncerComponent.class,
NotificationShelfComponent.class,
FragmentService.FragmentCreator.class})
public abstract class SystemUIModule {
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java
index 929b61a..ad90eff 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java
@@ -16,6 +16,8 @@
package com.android.systemui.dagger;
+import javax.inject.Inject;
+
import dagger.Subcomponent;
/**
@@ -32,4 +34,19 @@
interface Builder {
WMComponent build();
}
+
+
+ /**
+ * Example class used for passing an API to SysUI from WMShell.
+ *
+ * TODO: Remove this once real WM classes are ready to go.
+ **/
+ @WMSingleton
+ class StubAPIClass {
+ @Inject
+ StubAPIClass() {}
+ }
+
+ /** Create a StubAPIClass. */
+ StubAPIClass createStubAPIClass();
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
index 342818d..d9f9717 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
@@ -30,6 +30,8 @@
import android.provider.Settings;
import android.view.Display;
+import androidx.annotation.Nullable;
+
import com.android.systemui.doze.dagger.BrightnessSensor;
import com.android.systemui.doze.dagger.DozeScope;
import com.android.systemui.doze.dagger.WrappedService;
@@ -75,7 +77,7 @@
@Inject
public DozeScreenBrightness(Context context, @WrappedService DozeMachine.Service service,
- AsyncSensorManager sensorManager, @BrightnessSensor Sensor lightSensor,
+ AsyncSensorManager sensorManager, @Nullable @BrightnessSensor Sensor lightSensor,
DozeHost host, Handler handler, AlwaysOnDisplayPolicy alwaysOnDisplayPolicy) {
mContext = context;
mDozeService = service;
diff --git a/packages/SystemUI/src/com/android/systemui/doze/dagger/DozeModule.java b/packages/SystemUI/src/com/android/systemui/doze/dagger/DozeModule.java
index 04f7c36..b899460 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/dagger/DozeModule.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/dagger/DozeModule.java
@@ -20,6 +20,8 @@
import android.hardware.Sensor;
import android.os.Handler;
+import androidx.annotation.Nullable;
+
import com.android.systemui.R;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.doze.DozeAuthRemover;
@@ -91,6 +93,7 @@
@Provides
@BrightnessSensor
+ @Nullable
static Sensor providesBrightnessSensor(AsyncSensorManager sensorManager, Context context) {
return DozeSensors.findSensorWithType(sensorManager,
context.getString(R.string.doze_brightness_sensor_type));
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 3340791..2705f07 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -2184,8 +2184,8 @@
BiometricUnlockController biometricUnlockController, ViewGroup lockIconContainer,
View notificationContainer, KeyguardBypassController bypassController) {
mKeyguardViewControllerLazy.get().registerStatusBar(statusBar, container, panelView,
- biometricUnlockController, mDismissCallbackRegistry, lockIconContainer,
- notificationContainer, bypassController, mFalsingManager);
+ biometricUnlockController, lockIconContainer,
+ notificationContainer, bypassController);
return mKeyguardViewControllerLazy.get();
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
index a003d83..e5a9ac1 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
@@ -172,7 +172,6 @@
// This view is inactive, let's remove this! This happens e.g when dismissing /
// timing out a view. We still have the data around because resumption could
// be on, but we should save the resources and release this.
- oldKey?.let { MediaPlayerData.removeMediaPlayer(it) }
onMediaDataRemoved(key)
} else {
addOrUpdatePlayer(key, oldKey, data)
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
index aec3543..c7e7817 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
@@ -662,7 +662,7 @@
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
- | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
+ | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
| WindowManager.LayoutParams.FLAG_SLIPPERY,
PixelFormat.TRANSLUCENT);
mOrientationParams.setTitle("SecondaryHomeHandle" + mContext.getDisplayId());
diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTutorialHandler.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTutorialHandler.java
index 0354c72..8ef9b09 100644
--- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTutorialHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTutorialHandler.java
@@ -158,7 +158,9 @@
final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
mDisplaySize.x, mTutorialAreaHeight, 0, 0,
WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
- WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
+ WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+ | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
+ | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
lp.gravity = Gravity.TOP | Gravity.LEFT;
lp.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index e24fbc6..7dd4edd 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -573,7 +573,12 @@
private void saveScreenshot(Bitmap screenshot, Consumer<Uri> finisher, Rect screenRect,
Insets screenInsets, boolean showFlash) {
- dismissScreenshot("new screenshot requested", true);
+ if (mScreenshotLayout.isAttachedToWindow()) {
+ if (!mDismissAnimation.isRunning()) { // if we didn't already dismiss for another reason
+ mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_REENTERED);
+ }
+ dismissScreenshot("new screenshot requested", true);
+ }
mScreenBitmap = screenshot;
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotEvent.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotEvent.java
index 6b42f2e..74e0229 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotEvent.java
@@ -59,7 +59,9 @@
@UiEvent(doc = "screenshot interaction timed out")
SCREENSHOT_INTERACTION_TIMEOUT(310),
@UiEvent(doc = "screenshot explicitly dismissed")
- SCREENSHOT_EXPLICIT_DISMISSAL(311);
+ SCREENSHOT_EXPLICIT_DISMISSAL(311),
+ @UiEvent(doc = "screenshot reentered for new screenshot")
+ SCREENSHOT_REENTERED(640);
private final int mId;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
index 852c055..38c7e5c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
@@ -36,12 +36,12 @@
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.inflation.LowPriorityInflationHelper;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.stack.ForegroundServiceSectionController;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.util.Assert;
import java.util.ArrayList;
@@ -72,7 +72,7 @@
// Dependencies:
private final DynamicChildBindController mDynamicChildBindController;
protected final NotificationLockscreenUserManager mLockscreenUserManager;
- protected final NotificationGroupManager mGroupManager;
+ protected final NotificationGroupManagerLegacy mGroupManager;
protected final VisualStabilityManager mVisualStabilityManager;
private final SysuiStatusBarStateController mStatusBarStateController;
private final NotificationEntryManager mEntryManager;
@@ -107,7 +107,7 @@
Context context,
@Main Handler mainHandler,
NotificationLockscreenUserManager notificationLockscreenUserManager,
- NotificationGroupManager groupManager,
+ NotificationGroupManagerLegacy groupManager,
VisualStabilityManager visualStabilityManager,
StatusBarStateController statusBarStateController,
NotificationEntryManager notificationEntryManager,
@@ -187,13 +187,13 @@
ent.setSensitive(sensitive, deviceSensitive);
ent.getRow().setNeedsRedaction(needsRedaction);
mLowPriorityInflationHelper.recheckLowPriorityViewAndInflate(ent, ent.getRow());
- boolean isChildInGroup = mGroupManager.isChildInGroupWithSummary(ent.getSbn());
+ boolean isChildInGroup = mGroupManager.isChildInGroup(ent);
boolean groupChangesAllowed =
mVisualStabilityManager.areGroupChangesAllowed() // user isn't looking at notifs
|| !ent.hasFinishedInitialization(); // notif recently added
- NotificationEntry parent = mGroupManager.getGroupSummary(ent.getSbn());
+ NotificationEntry parent = mGroupManager.getGroupSummary(ent);
if (!groupChangesAllowed) {
// We don't to change groups while the user is looking at them
boolean wasChildInGroup = ent.isChildInGroup();
@@ -431,8 +431,7 @@
while(!stack.isEmpty()) {
ExpandableNotificationRow row = stack.pop();
NotificationEntry entry = row.getEntry();
- boolean isChildNotification =
- mGroupManager.isChildInGroupWithSummary(entry.getSbn());
+ boolean isChildNotification = mGroupManager.isChildInGroup(entry);
if (!onKeyguard) {
// If mAlwaysExpandNonGroupedNotification is false, then only expand the
@@ -448,9 +447,8 @@
boolean showOnKeyguard = mLockscreenUserManager.shouldShowOnKeyguard(entry);
if (!showOnKeyguard) {
// min priority notifications should show if their summary is showing
- if (mGroupManager.isChildInGroupWithSummary(entry.getSbn())) {
- NotificationEntry summary = mGroupManager.getLogicalGroupSummary(
- entry.getSbn());
+ if (mGroupManager.isChildInGroup(entry)) {
+ NotificationEntry summary = mGroupManager.getLogicalGroupSummary(entry);
if (summary != null && mLockscreenUserManager.shouldShowOnKeyguard(summary)) {
showOnKeyguard = true;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java
index db2875a3..d15b847 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java
@@ -44,12 +44,12 @@
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.inflation.LowPriorityInflationHelper;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager;
import com.android.systemui.statusbar.notification.stack.ForegroundServiceSectionController;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.ManagedProfileController;
import com.android.systemui.statusbar.phone.ManagedProfileControllerImpl;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.phone.StatusBarIconControllerImpl;
@@ -157,7 +157,7 @@
Context context,
@Main Handler mainHandler,
NotificationLockscreenUserManager notificationLockscreenUserManager,
- NotificationGroupManager groupManager,
+ NotificationGroupManagerLegacy groupManager,
VisualStabilityManager visualStabilityManager,
StatusBarStateController statusBarStateController,
NotificationEntryManager notificationEntryManager,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ConversationNotifications.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ConversationNotifications.kt
index c68625c..433c8b0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ConversationNotifications.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ConversationNotifications.kt
@@ -30,7 +30,7 @@
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.android.systemui.statusbar.notification.row.NotificationContentView
import com.android.systemui.statusbar.notification.stack.StackStateAnimator
-import com.android.systemui.statusbar.phone.NotificationGroupManager
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy
import java.util.concurrent.ConcurrentHashMap
import javax.inject.Inject
@@ -64,7 +64,7 @@
@SysUISingleton
class ConversationNotificationManager @Inject constructor(
private val notificationEntryManager: NotificationEntryManager,
- private val notificationGroupManager: NotificationGroupManager,
+ private val notificationGroupManager: NotificationGroupManagerLegacy,
private val context: Context,
@Main private val mainHandler: Handler
) {
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 b5f1c7f..e1e77b0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
@@ -48,13 +48,13 @@
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationRankingManager;
import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinder;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager;
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection;
import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
import com.android.systemui.statusbar.notification.dagger.NotificationsModule;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.util.Assert;
import com.android.systemui.util.leak.LeakDetector;
@@ -139,7 +139,7 @@
private final List<NotifCollectionListener> mNotifCollectionListeners = new ArrayList<>();
private final KeyguardEnvironment mKeyguardEnvironment;
- private final NotificationGroupManager mGroupManager;
+ private final NotificationGroupManagerLegacy mGroupManager;
private final NotificationRankingManager mRankingManager;
private final FeatureFlags mFeatureFlags;
private final ForegroundServiceDismissalFeatureController mFgsFeatureController;
@@ -199,7 +199,7 @@
*/
public NotificationEntryManager(
NotificationEntryManagerLogger logger,
- NotificationGroupManager groupManager,
+ NotificationGroupManagerLegacy groupManager,
NotificationRankingManager rankingManager,
KeyguardEnvironment keyguardEnvironment,
FeatureFlags featureFlags,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java
index 590ccf83..73c7fd1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java
@@ -34,7 +34,6 @@
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.ShadeController;
import javax.inject.Inject;
@@ -46,8 +45,6 @@
@SysUISingleton
public class NotificationFilter {
- private final NotificationGroupManager mGroupManager = Dependency.get(
- NotificationGroupManager.class);
private final StatusBarStateController mStatusBarStateController;
private final Boolean mIsMediaFlagEnabled;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
index 8ce9d94..789e78e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
@@ -60,6 +60,7 @@
import com.android.internal.util.ContrastColorUtil;
import com.android.systemui.statusbar.InflationTask;
import com.android.systemui.statusbar.notification.collection.NotifCollection.CancellationReason;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifPromoter;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifDismissInterceptor;
@@ -69,7 +70,6 @@
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRowController;
import com.android.systemui.statusbar.notification.row.NotificationGuts;
import com.android.systemui.statusbar.notification.stack.PriorityBucket;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
import java.util.ArrayList;
import java.util.List;
@@ -430,7 +430,7 @@
* Get the children that are actually attached to this notification's row.
*
* TODO: Seems like most callers here should probably be using
- * {@link NotificationGroupManager#getChildren}
+ * {@link NotificationGroupManagerLegacy#getChildren}
*/
public @Nullable List<NotificationEntry> getAttachedNotifChildren() {
if (row == null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManager.kt
index bab2686..fb42c42 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManager.kt
@@ -33,7 +33,7 @@
import com.android.systemui.statusbar.notification.stack.BUCKET_PEOPLE
import com.android.systemui.statusbar.notification.stack.BUCKET_SILENT
import com.android.systemui.statusbar.notification.stack.PriorityBucket
-import com.android.systemui.statusbar.phone.NotificationGroupManager
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy
import com.android.systemui.statusbar.policy.HeadsUpManager
import dagger.Lazy
import java.util.Objects
@@ -52,7 +52,7 @@
*/
open class NotificationRankingManager @Inject constructor(
private val mediaManagerLazy: Lazy<NotificationMediaManager>,
- private val groupManager: NotificationGroupManager,
+ private val groupManager: NotificationGroupManagerLegacy,
private val headsUpManager: HeadsUpManager,
private val notifFilter: NotificationFilter,
private val logger: NotificationEntryManagerLogger,
@@ -191,7 +191,7 @@
private fun NotificationEntry.isConversation() = getPeopleNotificationType() != TYPE_NON_PERSON
private fun NotificationEntry.getPeopleNotificationType() =
- peopleNotificationIdentifier.getPeopleNotificationType(sbn, ranking)
+ peopleNotificationIdentifier.getPeopleNotificationType(this)
private fun NotificationEntry.isHighPriority() =
highPriorityProvider.isHighPriority(this)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt
index dea1162..3aaa9ac 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt
@@ -53,8 +53,7 @@
}
private fun isConversation(entry: NotificationEntry): Boolean =
- peopleNotificationIdentifier.getPeopleNotificationType(entry.sbn, entry.ranking) !=
- TYPE_NON_PERSON
+ peopleNotificationIdentifier.getPeopleNotificationType(entry) != TYPE_NON_PERSON
companion object {
private const val TAG = "ConversationCoordinator"
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/LowPriorityInflationHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/LowPriorityInflationHelper.java
index 6089aa2..aec2647 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/LowPriorityInflationHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/LowPriorityInflationHelper.java
@@ -20,10 +20,10 @@
import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.statusbar.notification.collection.GroupEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.RowContentBindParams;
import com.android.systemui.statusbar.notification.row.RowContentBindStage;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
import javax.inject.Inject;
@@ -34,13 +34,13 @@
@SysUISingleton
public class LowPriorityInflationHelper {
private final FeatureFlags mFeatureFlags;
- private final NotificationGroupManager mGroupManager;
+ private final NotificationGroupManagerLegacy mGroupManager;
private final RowContentBindStage mRowContentBindStage;
@Inject
LowPriorityInflationHelper(
FeatureFlags featureFlags,
- NotificationGroupManager groupManager,
+ NotificationGroupManagerLegacy groupManager,
RowContentBindStage rowContentBindStage) {
mFeatureFlags = featureFlags;
mGroupManager = groupManager;
@@ -78,7 +78,7 @@
if (mFeatureFlags.isNewNotifPipelineRenderingEnabled()) {
isGroupChild = (entry.getParent() != GroupEntry.ROOT_ENTRY);
} else {
- isGroupChild = mGroupManager.isChildInGroupWithSummary(entry.getSbn());
+ isGroupChild = mGroupManager.isChildInGroup(entry);
}
return entry.isAmbient() && !isGroupChild;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/NotificationGroupManagerLegacy.java
similarity index 81%
rename from packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
rename to packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/NotificationGroupManagerLegacy.java
index c44c59c..21d54c8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/NotificationGroupManagerLegacy.java
@@ -11,10 +11,10 @@
* 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
+ * limitations under the License.
*/
-package com.android.systemui.statusbar.phone;
+package com.android.systemui.statusbar.notification.collection.legacy;
import android.annotation.Nullable;
import android.service.notification.StatusBarNotification;
@@ -22,14 +22,17 @@
import android.util.Log;
import com.android.systemui.Dependency;
+import com.android.systemui.Dumpable;
import com.android.systemui.bubbles.BubbleController;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.notification.collection.ListEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager;
+import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
@@ -37,6 +40,7 @@
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -46,13 +50,19 @@
/**
* A class to handle notifications and their corresponding groups.
+ * This includes:
+ * 1. Determining whether an entry is a member of a group and whether it is a summary or a child
+ * 2. Tracking group expansion states
*/
@SysUISingleton
-public class NotificationGroupManager implements OnHeadsUpChangedListener, StateListener {
+public class NotificationGroupManagerLegacy implements OnHeadsUpChangedListener, StateListener,
+ GroupMembershipManager, GroupExpansionManager, Dumpable {
private static final String TAG = "NotificationGroupManager";
private final HashMap<String, NotificationGroup> mGroupMap = new HashMap<>();
- private final ArraySet<OnGroupChangeListener> mListeners = new ArraySet<>();
+ private final ArraySet<OnGroupExpansionChangeListener> mExpansionChangeListeners =
+ new ArraySet<>();
+ private final ArraySet<OnGroupChangeListener> mGroupChangeListeners = new ArraySet<>();
private final Lazy<PeopleNotificationIdentifier> mPeopleNotificationIdentifier;
private int mBarState = -1;
private HashMap<String, StatusBarNotification> mIsolatedEntries = new HashMap<>();
@@ -61,7 +71,7 @@
@Nullable private BubbleController mBubbleController = null;
@Inject
- public NotificationGroupManager(
+ public NotificationGroupManagerLegacy(
StatusBarStateController statusBarStateController,
Lazy<PeopleNotificationIdentifier> peopleNotificationIdentifier) {
statusBarStateController.addCallback(this);
@@ -77,15 +87,19 @@
/**
* Add a listener for changes to groups.
- *
- * @param listener listener to add
*/
- public void addOnGroupChangeListener(OnGroupChangeListener listener) {
- mListeners.add(listener);
+ public void registerGroupChangeListener(OnGroupChangeListener listener) {
+ mGroupChangeListeners.add(listener);
}
- public boolean isGroupExpanded(StatusBarNotification sbn) {
- NotificationGroup group = mGroupMap.get(getGroupKey(sbn));
+ @Override
+ public void registerGroupExpansionChangeListener(OnGroupExpansionChangeListener listener) {
+ mExpansionChangeListeners.add(listener);
+ }
+
+ @Override
+ public boolean isGroupExpanded(NotificationEntry entry) {
+ NotificationGroup group = mGroupMap.get(getGroupKey(entry.getSbn()));
if (group == null) {
return false;
}
@@ -103,8 +117,9 @@
return group.expanded;
}
- public void setGroupExpanded(StatusBarNotification sbn, boolean expanded) {
- NotificationGroup group = mGroupMap.get(getGroupKey(sbn));
+ @Override
+ public void setGroupExpanded(NotificationEntry entry, boolean expanded) {
+ NotificationGroup group = mGroupMap.get(getGroupKey(entry.getSbn()));
if (group == null) {
return;
}
@@ -114,12 +129,15 @@
private void setGroupExpanded(NotificationGroup group, boolean expanded) {
group.expanded = expanded;
if (group.summary != null) {
- for (OnGroupChangeListener listener : mListeners) {
- listener.onGroupExpansionChanged(group.summary.getRow(), expanded);
+ for (OnGroupExpansionChangeListener listener : mExpansionChangeListeners) {
+ listener.onGroupExpansionChange(group.summary.getRow(), expanded);
}
}
}
+ /**
+ * When we want to remove an entry from being tracked for grouping
+ */
public void onEntryRemoved(NotificationEntry removed) {
onEntryRemovedInternal(removed, removed.getSbn());
mIsolatedEntries.remove(removed.getKey());
@@ -158,7 +176,7 @@
if (group.children.isEmpty()) {
if (group.summary == null) {
mGroupMap.remove(groupKey);
- for (OnGroupChangeListener listener : mListeners) {
+ for (OnGroupChangeListener listener : mGroupChangeListeners) {
listener.onGroupRemoved(group, groupKey);
}
}
@@ -184,7 +202,8 @@
if (group == null) {
group = new NotificationGroup();
mGroupMap.put(groupKey, group);
- for (OnGroupChangeListener listener : mListeners) {
+
+ for (OnGroupChangeListener listener : mGroupChangeListeners) {
listener.onGroupCreated(group, groupKey);
}
}
@@ -195,9 +214,8 @@
Log.wtf(TAG, "Inconsistent entries found with the same key " + added.getKey()
+ "existing removed: " + existing.isRowRemoved()
+ (existingThrowable != null
- ? Log.getStackTraceString(existingThrowable) + "\n": "")
- + " added removed" + added.isRowRemoved()
- , new Throwable());
+ ? Log.getStackTraceString(existingThrowable) + "\n" : "")
+ + " added removed" + added.isRowRemoved(), new Throwable());
}
group.children.put(added.getKey(), added);
updateSuppression(group);
@@ -206,12 +224,12 @@
group.expanded = added.areChildrenExpanded();
updateSuppression(group);
if (!group.children.isEmpty()) {
- ArrayList<NotificationEntry> childrenCopy
- = new ArrayList<>(group.children.values());
+ ArrayList<NotificationEntry> childrenCopy =
+ new ArrayList<>(group.children.values());
for (NotificationEntry child : childrenCopy) {
onEntryBecomingChild(child);
}
- for (OnGroupChangeListener listener : mListeners) {
+ for (OnGroupChangeListener listener : mGroupChangeListeners) {
listener.onGroupCreatedFromChildren(group);
}
}
@@ -243,7 +261,7 @@
&& group.summary.getSbn().getNotification().isGroupSummary()
&& (hasIsolatedChildren(group) || hasBubbles)));
if (prevSuppressed != group.suppressed) {
- for (OnGroupChangeListener listener : mListeners) {
+ for (OnGroupChangeListener listener : mGroupChangeListeners) {
if (!mIsUpdatingUnchangedGroup) {
listener.onGroupSuppressionChanged(group, group.suppressed);
listener.onGroupsChanged();
@@ -306,6 +324,9 @@
}
}
+ /**
+ * Whether the given notification is the summary of a group that is being suppressed
+ */
public boolean isSummaryOfSuppressedGroup(StatusBarNotification sbn) {
return isGroupSuppressed(getGroupKey(sbn)) && sbn.getNotification().isGroupSummary();
}
@@ -315,13 +336,14 @@
&& getTotalNumberOfChildren(sbn) == 1;
}
- public boolean isOnlyChildInGroup(StatusBarNotification sbn) {
+ @Override
+ public boolean isOnlyChildInGroup(NotificationEntry entry) {
+ final StatusBarNotification sbn = entry.getSbn();
if (!isOnlyChild(sbn)) {
return false;
}
- NotificationEntry logicalGroupSummary = getLogicalGroupSummary(sbn);
- return logicalGroupSummary != null
- && !logicalGroupSummary.getSbn().equals(sbn);
+ NotificationEntry logicalGroupSummary = getLogicalGroupSummary(entry);
+ return logicalGroupSummary != null && !logicalGroupSummary.getSbn().equals(sbn);
}
private int getTotalNumberOfChildren(StatusBarNotification sbn) {
@@ -339,11 +361,12 @@
private void setStatusBarState(int newState) {
mBarState = newState;
if (mBarState == StatusBarState.KEYGUARD) {
- collapseAllGroups();
+ collapseGroups();
}
}
- public void collapseAllGroups() {
+ @Override
+ public void collapseGroups() {
// Because notifications can become isolated when the group becomes suppressed it can
// lead to concurrent modifications while looping. We need to make a copy.
ArrayList<NotificationGroup> groupCopy = new ArrayList<>(mGroupMap.values());
@@ -357,10 +380,9 @@
}
}
- /**
- * @return whether a given notification is a child in a group which has a summary
- */
- public boolean isChildInGroupWithSummary(StatusBarNotification sbn) {
+ @Override
+ public boolean isChildInGroup(NotificationEntry entry) {
+ final StatusBarNotification sbn = entry.getSbn();
if (!isGroupChild(sbn)) {
return false;
}
@@ -377,10 +399,9 @@
return true;
}
- /**
- * @return whether a given notification is a summary in a group which has children
- */
- public boolean isSummaryOfGroup(StatusBarNotification sbn) {
+ @Override
+ public boolean isGroupSummary(NotificationEntry entry) {
+ final StatusBarNotification sbn = entry.getSbn();
if (!isGroupSummary(sbn)) {
return false;
}
@@ -391,21 +412,14 @@
return !group.children.isEmpty() && Objects.equals(group.summary.getSbn(), sbn);
}
- /**
- * Get the summary of a specified status bar notification. For isolated notification this return
- * itself.
- */
- public NotificationEntry getGroupSummary(StatusBarNotification sbn) {
- return getGroupSummary(getGroupKey(sbn));
+ @Override
+ public NotificationEntry getGroupSummary(NotificationEntry entry) {
+ return getGroupSummary(getGroupKey(entry.getSbn()));
}
- /**
- * Similar to {@link #getGroupSummary(StatusBarNotification)} but doesn't get the visual summary
- * but the logical summary, i.e when a child is isolated, it still returns the summary as if
- * it wasn't isolated.
- */
- public NotificationEntry getLogicalGroupSummary(StatusBarNotification sbn) {
- return getGroupSummary(sbn.getGroupKey());
+ @Override
+ public NotificationEntry getLogicalGroupSummary(NotificationEntry entry) {
+ return getGroupSummary(entry.getSbn().getGroupKey());
}
@Nullable
@@ -436,14 +450,10 @@
return children;
}
- /**
- * Get the children that are in the summary's group, not including those isolated.
- *
- * @param summary summary of a group
- * @return list of the children
- */
- public @Nullable ArrayList<NotificationEntry> getChildren(StatusBarNotification summary) {
- NotificationGroup group = mGroupMap.get(summary.getGroupKey());
+ @Override
+ public @Nullable List<NotificationEntry> getChildren(ListEntry listEntrySummary) {
+ NotificationEntry summary = listEntrySummary.getRepresentativeEntry();
+ NotificationGroup group = mGroupMap.get(summary.getSbn().getGroupKey());
if (group == null) {
return null;
}
@@ -479,9 +489,9 @@
return groupKey;
}
- /** @return group expansion state after toggling. */
- public boolean toggleGroupExpansion(StatusBarNotification sbn) {
- NotificationGroup group = mGroupMap.get(getGroupKey(sbn));
+ @Override
+ public boolean toggleGroupExpansion(NotificationEntry entry) {
+ NotificationGroup group = mGroupMap.get(getGroupKey(entry.getSbn()));
if (group == null) {
return false;
}
@@ -494,10 +504,7 @@
}
/**
- * Whether a notification is visually a group summary.
- *
- * @param sbn notification to check
- * @return true if it is visually a group summary
+ * Is this notification the summary of a group?
*/
public boolean isGroupSummary(StatusBarNotification sbn) {
if (isIsolated(sbn.getKey())) {
@@ -536,14 +543,13 @@
* @param entry the notification to check
* @return true if the entry should be isolated
*/
-
private boolean shouldIsolate(NotificationEntry entry) {
StatusBarNotification sbn = entry.getSbn();
if (!sbn.isGroup() || sbn.getNotification().isGroupSummary()) {
return false;
}
- int peopleNotificationType = mPeopleNotificationIdentifier.get().getPeopleNotificationType(
- entry.getSbn(), entry.getRanking());
+ int peopleNotificationType =
+ mPeopleNotificationIdentifier.get().getPeopleNotificationType(entry);
if (peopleNotificationType == PeopleNotificationIdentifier.TYPE_IMPORTANT_PERSON) {
return true;
}
@@ -576,7 +582,7 @@
// When the notification gets added afterwards it is already isolated and therefore
// it doesn't lead to an update.
updateSuppression(mGroupMap.get(entry.getSbn().getGroupKey()));
- for (OnGroupChangeListener listener : mListeners) {
+ for (OnGroupChangeListener listener : mGroupChangeListeners) {
listener.onGroupsChanged();
}
}
@@ -607,7 +613,7 @@
onEntryRemovedInternal(entry, entry.getSbn());
mIsolatedEntries.remove(sbn.getKey());
onEntryAddedInternal(entry);
- for (OnGroupChangeListener listener : mListeners) {
+ for (OnGroupChangeListener listener : mGroupChangeListeners) {
listener.onGroupsChanged();
}
}
@@ -618,12 +624,16 @@
|| notificationGroup.summary.isGroupNotFullyVisible();
}
+ /**
+ * Directly set the heads up manager to avoid circular dependencies
+ */
public void setHeadsUpManager(HeadsUpManager headsUpManager) {
mHeadsUpManager = headsUpManager;
}
+ @Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- pw.println("GroupManager state:");
+ pw.println("GroupManagerLegacy state:");
pw.println(" number of groups: " + mGroupMap.size());
for (Map.Entry<String, NotificationGroup> entry : mGroupMap.entrySet()) {
pw.println("\n key: " + entry.getKey()); pw.println(entry.getValue());
@@ -640,6 +650,9 @@
setStatusBarState(newState);
}
+ /**
+ * Represents a notification group in the notification shade.
+ */
public static class NotificationGroup {
public final HashMap<String, NotificationEntry> children = new HashMap<>();
public NotificationEntry summary;
@@ -659,24 +672,29 @@
result += "\n children size: " + children.size();
for (NotificationEntry child : children.values()) {
result += "\n " + child.getSbn()
- + (child.getDebugThrowable() != null
- ? Log.getStackTraceString(child.getDebugThrowable())
- : "");
+ + (child.getDebugThrowable() != null
+ ? Log.getStackTraceString(child.getDebugThrowable())
+ : "");
}
result += "\n summary suppressed: " + suppressed;
return result;
}
}
+ /**
+ * Listener for group changes not including group expansion changes which are handled by
+ * {@link OnGroupExpansionChangeListener}.
+ */
public interface OnGroupChangeListener {
-
/**
* A new group has been created.
*
* @param group the group that was created
* @param groupKey the group's key
*/
- default void onGroupCreated(NotificationGroup group, String groupKey) {}
+ default void onGroupCreated(
+ NotificationGroup group,
+ String groupKey) {}
/**
* A group has been removed.
@@ -684,7 +702,9 @@
* @param group the group that was removed
* @param groupKey the group's key
*/
- default void onGroupRemoved(NotificationGroup group, String groupKey) {}
+ default void onGroupRemoved(
+ NotificationGroup group,
+ String groupKey) {}
/**
* The suppression of a group has changed.
@@ -692,16 +712,9 @@
* @param group the group that has changed
* @param suppressed true if the group is now suppressed, false o/w
*/
- default void onGroupSuppressionChanged(NotificationGroup group, boolean suppressed) {}
-
- /**
- * The expansion of a group has changed.
- *
- * @param changedRow the row for which the expansion has changed, which is also the summary
- * @param expanded a boolean indicating the new expanded state
- */
- default void onGroupExpansionChanged(ExpandableNotificationRow changedRow,
- boolean expanded) {}
+ default void onGroupSuppressionChanged(
+ NotificationGroup group,
+ boolean suppressed) {}
/**
* A group of children just received a summary notification and should therefore become
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java
index 8b803b5..18806ef 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java
@@ -20,11 +20,10 @@
import android.app.NotificationManager;
import com.android.systemui.dagger.SysUISingleton;
-import com.android.systemui.statusbar.notification.collection.GroupEntry;
import com.android.systemui.statusbar.notification.collection.ListEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
import java.util.List;
@@ -39,14 +38,14 @@
@SysUISingleton
public class HighPriorityProvider {
private final PeopleNotificationIdentifier mPeopleNotificationIdentifier;
- private final NotificationGroupManager mGroupManager;
+ private final GroupMembershipManager mGroupMembershipManager;
@Inject
public HighPriorityProvider(
PeopleNotificationIdentifier peopleNotificationIdentifier,
- NotificationGroupManager groupManager) {
+ GroupMembershipManager groupManager) {
mPeopleNotificationIdentifier = peopleNotificationIdentifier;
- mGroupManager = groupManager;
+ mGroupMembershipManager = groupManager;
}
/**
@@ -81,20 +80,15 @@
private boolean hasHighPriorityChild(ListEntry entry) {
- List<NotificationEntry> children = null;
-
- if (entry instanceof GroupEntry) {
- // New notification pipeline
- children = ((GroupEntry) entry).getChildren();
- } else if (entry.getRepresentativeEntry() != null
- && mGroupManager.isGroupSummary(entry.getRepresentativeEntry().getSbn())) {
- // Old notification pipeline
- children = mGroupManager.getChildren(entry.getRepresentativeEntry().getSbn());
+ if (entry instanceof NotificationEntry
+ && !mGroupMembershipManager.isGroupSummary((NotificationEntry) entry)) {
+ return false;
}
+ List<NotificationEntry> children = mGroupMembershipManager.getChildren(entry);
if (children != null) {
for (NotificationEntry child : children) {
- if (isHighPriority(child)) {
+ if (child != entry && isHighPriority(child)) {
return true;
}
}
@@ -122,8 +116,8 @@
}
private boolean isPeopleNotification(NotificationEntry entry) {
- return mPeopleNotificationIdentifier.getPeopleNotificationType(
- entry.getSbn(), entry.getRanking()) != PeopleNotificationIdentifier.TYPE_NON_PERSON;
+ return mPeopleNotificationIdentifier.getPeopleNotificationType(entry)
+ != PeopleNotificationIdentifier.TYPE_NON_PERSON;
}
private boolean hasUserSetImportance(NotificationEntry entry) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupExpansionManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupExpansionManager.java
new file mode 100644
index 0000000..d2df07e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupExpansionManager.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.collection.render;
+
+import com.android.systemui.Dumpable;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+
+/**
+ * Tracks expanded notification states for groups. This expanded state should not be confused by the
+ * expanded/collapsed state of a single notification which is tracked within each
+ * ExpandableNotificationRow.
+ */
+public interface GroupExpansionManager extends Dumpable {
+
+ /**
+ * Register a listener for group expansion changes
+ */
+ void registerGroupExpansionChangeListener(OnGroupExpansionChangeListener listener);
+
+ /**
+ * Whether the group associated with this notification is expanded.
+ * If this notification is not part of a group, it will always return false.
+ */
+ boolean isGroupExpanded(NotificationEntry entry);
+
+ /**
+ * Set whether the group associated with this notification is expanded or not.
+ */
+ void setGroupExpanded(NotificationEntry entry, boolean expanded);
+
+ /** @return group expansion state after toggling. */
+ boolean toggleGroupExpansion(NotificationEntry entry);
+
+ /**
+ * Set expanded=false for all groups
+ */
+ void collapseGroups();
+
+ /**
+ * Listener for group expansion changes.
+ */
+ interface OnGroupExpansionChangeListener {
+ /**
+ * The expansion of a group has changed.
+ *
+ * @param changedRow the row for which the expansion has changed, which is also the summary
+ * @param expanded a boolean indicating the new expanded state
+ */
+ void onGroupExpansionChange(ExpandableNotificationRow changedRow, boolean expanded);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupExpansionManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupExpansionManagerImpl.java
new file mode 100644
index 0000000..b9aa26f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupExpansionManagerImpl.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.collection.render;
+
+import com.android.systemui.statusbar.notification.collection.GroupEntry;
+import com.android.systemui.statusbar.notification.collection.ListEntry;
+import com.android.systemui.statusbar.notification.collection.NotifPipeline;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.coordinator.Coordinator;
+import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Provides grouping information for notification entries including information about a group's
+ * expanded state.
+ */
+public class GroupExpansionManagerImpl implements GroupExpansionManager, Coordinator {
+ private final GroupMembershipManager mGroupMembershipManager;
+ private final Set<OnGroupExpansionChangeListener> mOnGroupChangeListeners = new HashSet<>();
+
+ // Set of summary keys whose groups are expanded
+ private final Set<NotificationEntry> mExpandedGroups = new HashSet<>();
+
+ public GroupExpansionManagerImpl(GroupMembershipManager groupMembershipManager) {
+ mGroupMembershipManager = groupMembershipManager;
+ }
+
+ /**
+ * Cleanup entries from mExpandedGroups that no longer exist in the pipeline.
+ */
+ private final OnBeforeRenderListListener mNotifTracker = (entries) -> {
+ final Set<NotificationEntry> renderingSummaries = new HashSet<>();
+ for (ListEntry entry : entries) {
+ if (entry instanceof GroupEntry) {
+ renderingSummaries.add(entry.getRepresentativeEntry());
+ }
+ }
+ mExpandedGroups.removeIf(expandedGroup -> !renderingSummaries.contains(expandedGroup));
+ };
+
+ @Override
+ public void attach(NotifPipeline pipeline) {
+ pipeline.addOnBeforeRenderListListener(mNotifTracker);
+ }
+
+ @Override
+ public void registerGroupExpansionChangeListener(OnGroupExpansionChangeListener listener) {
+ mOnGroupChangeListeners.add(listener);
+ }
+
+ @Override
+ public boolean isGroupExpanded(NotificationEntry entry) {
+ return mExpandedGroups.contains(mGroupMembershipManager.getGroupSummary(entry));
+ }
+
+ @Override
+ public void setGroupExpanded(NotificationEntry entry, boolean expanded) {
+ final NotificationEntry groupSummary = mGroupMembershipManager.getGroupSummary(entry);
+ if (expanded) {
+ mExpandedGroups.add(groupSummary);
+ } else {
+ mExpandedGroups.remove(groupSummary);
+ }
+
+ sendOnGroupExpandedChange(entry, expanded);
+ }
+
+ @Override
+ public boolean toggleGroupExpansion(NotificationEntry entry) {
+ setGroupExpanded(entry, !isGroupExpanded(entry));
+ return isGroupExpanded(entry);
+ }
+
+ @Override
+ public void collapseGroups() {
+ for (NotificationEntry entry : mExpandedGroups) {
+ setGroupExpanded(entry, false);
+ }
+ }
+
+ @Override
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ pw.println("NotificationEntryExpansion state:");
+ pw.println(" # expanded groups: " + mExpandedGroups.size());
+ for (NotificationEntry entry : mExpandedGroups) {
+ pw.println(" summary key of expanded group: " + entry.getKey());
+ }
+ }
+
+ private void sendOnGroupExpandedChange(NotificationEntry entry, boolean expanded) {
+ for (OnGroupExpansionChangeListener listener : mOnGroupChangeListeners) {
+ listener.onGroupExpansionChange(entry.getRow(), expanded);
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupMembershipManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupMembershipManager.java
new file mode 100644
index 0000000..196cb8f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupMembershipManager.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.collection.render;
+
+import android.annotation.Nullable;
+
+import com.android.systemui.statusbar.notification.collection.ListEntry;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+
+import java.util.List;
+
+/**
+ * Helper that determines the group states (parent, summary, children) of a notification.
+ */
+public interface GroupMembershipManager {
+ /**
+ * @return whether a given notification is a top level entry or is the summary in a group which
+ * has children
+ */
+ boolean isGroupSummary(NotificationEntry entry);
+
+ /**
+ * Get the summary of a specified status bar notification. For an isolated notification this
+ * returns itself.
+ */
+ NotificationEntry getGroupSummary(NotificationEntry entry);
+
+ /**
+ * Similar to {@link #getGroupSummary(NotificationEntry)} but doesn't get the visual summary
+ * but the logical summary, i.e when a child is isolated, it still returns the summary as if
+ * it wasn't isolated.
+ * TODO: remove this when migrating to the new pipeline, this is taken care of in the
+ * dismissal logic built into NotifCollection
+ */
+ default NotificationEntry getLogicalGroupSummary(NotificationEntry entry) {
+ return getGroupSummary(entry);
+ }
+
+ /**
+ * @return whether a given notification is a child in a group
+ */
+ boolean isChildInGroup(NotificationEntry entry);
+
+ /**
+ * Whether this is the only child in a group
+ * TODO: remove this when migrating to the new pipeline, this is taken care of in the
+ * dismissal logic built into NotifCollection
+ */
+ boolean isOnlyChildInGroup(NotificationEntry entry);
+
+ /**
+ * Get the children that are in the summary's group, not including those isolated.
+ *
+ * @param summary summary of a group
+ * @return list of the children
+ */
+ @Nullable
+ List<NotificationEntry> getChildren(ListEntry summary);
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupMembershipManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupMembershipManagerImpl.java
new file mode 100644
index 0000000..c1f468a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupMembershipManagerImpl.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.collection.render;
+
+import static com.android.systemui.statusbar.notification.collection.GroupEntry.ROOT_ENTRY;
+
+import androidx.annotation.Nullable;
+
+import com.android.systemui.statusbar.notification.collection.GroupEntry;
+import com.android.systemui.statusbar.notification.collection.ListEntry;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+
+import java.util.List;
+
+/**
+ * ShadeListBuilder groups notifications from system server. This manager translates
+ * ShadeListBuilder's method of grouping to be used within SystemUI.
+ */
+public class GroupMembershipManagerImpl implements GroupMembershipManager {
+ @Override
+ public boolean isGroupSummary(NotificationEntry entry) {
+ return getGroupSummary(entry) == entry;
+ }
+
+ @Override
+ public NotificationEntry getGroupSummary(NotificationEntry entry) {
+ if (isEntryTopLevel(entry) || entry.getParent() == null) {
+ return null;
+ }
+
+ return entry.getParent().getRepresentativeEntry();
+ }
+
+ @Override
+ public boolean isChildInGroup(NotificationEntry entry) {
+ return !isEntryTopLevel(entry);
+ }
+
+ @Override
+ public boolean isOnlyChildInGroup(NotificationEntry entry) {
+ if (entry.getParent() == null) {
+ return false;
+ }
+
+ return entry.getParent().getChildren().size() == 1;
+ }
+
+ @Nullable
+ @Override
+ public List<NotificationEntry> getChildren(ListEntry entry) {
+ if (entry instanceof GroupEntry) {
+ return ((GroupEntry) entry).getChildren();
+ }
+
+ if (isGroupSummary(entry.getRepresentativeEntry())) {
+ // maybe we were actually passed the summary
+ return entry.getRepresentativeEntry().getParent().getChildren();
+ }
+
+ return null;
+ }
+
+ private boolean isEntryTopLevel(NotificationEntry entry) {
+ return entry.getParent() == ROOT_ENTRY;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt
index 3c35b7bd..5243854 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt
@@ -24,7 +24,6 @@
import com.android.systemui.statusbar.notification.collection.ShadeListBuilder
import com.android.systemui.statusbar.notification.stack.NotificationListContainer
import com.android.systemui.statusbar.phone.NotificationIconAreaController
-import java.lang.RuntimeException
import javax.inject.Inject
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
index f3ed95b..e2aae64 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
@@ -50,10 +50,15 @@
import com.android.systemui.statusbar.notification.collection.inflation.NotifInflater;
import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinder;
import com.android.systemui.statusbar.notification.collection.inflation.OnUserInteractionCallbackImpl;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.collection.legacy.OnUserInteractionCallbackImplLegacy;
import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager;
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection;
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
+import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager;
+import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManagerImpl;
+import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
+import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManagerImpl;
import com.android.systemui.statusbar.notification.init.NotificationsController;
import com.android.systemui.statusbar.notification.init.NotificationsControllerImpl;
import com.android.systemui.statusbar.notification.init.NotificationsControllerStub;
@@ -67,7 +72,6 @@
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.notification.row.OnUserInteractionCallback;
import com.android.systemui.statusbar.notification.row.PriorityOnboardingDialogController;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.util.leak.LeakDetector;
@@ -91,7 +95,7 @@
@Provides
static NotificationEntryManager provideNotificationEntryManager(
NotificationEntryManagerLogger logger,
- NotificationGroupManager groupManager,
+ NotificationGroupManagerLegacy groupManager,
NotificationRankingManager rankingManager,
NotificationEntryManager.KeyguardEnvironment keyguardEnvironment,
FeatureFlags featureFlags,
@@ -206,6 +210,29 @@
context, notificationGutsManager, notificationEntryManager, metricsLogger);
}
+ /** Provides an instance of {@link GroupMembershipManager} */
+ @SysUISingleton
+ @Provides
+ static GroupMembershipManager provideGroupMembershipManager(
+ FeatureFlags featureFlags,
+ Lazy<NotificationGroupManagerLegacy> groupManagerLegacy) {
+ return featureFlags.isNewNotifPipelineRenderingEnabled()
+ ? new GroupMembershipManagerImpl()
+ : groupManagerLegacy.get();
+ }
+
+ /** Provides an instance of {@link GroupExpansionManager} */
+ @SysUISingleton
+ @Provides
+ static GroupExpansionManager provideGroupExpansionManager(
+ FeatureFlags featureFlags,
+ Lazy<GroupMembershipManager> groupMembershipManager,
+ Lazy<NotificationGroupManagerLegacy> groupManagerLegacy) {
+ return featureFlags.isNewNotifPipelineRenderingEnabled()
+ ? new GroupExpansionManagerImpl(groupMembershipManager.get())
+ : groupManagerLegacy.get();
+ }
+
/** Initializes the notification data pipeline (can be disabled via config). */
@SysUISingleton
@Provides
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt
index 6460892..9fb2928 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt
@@ -30,12 +30,12 @@
import com.android.systemui.statusbar.notification.collection.TargetSdkResolver
import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl
import com.android.systemui.statusbar.notification.collection.init.NotifPipelineInitializer
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy
import com.android.systemui.statusbar.notification.interruption.HeadsUpController
import com.android.systemui.statusbar.notification.interruption.HeadsUpViewBinder
import com.android.systemui.statusbar.notification.row.NotifBindPipelineInitializer
import com.android.systemui.statusbar.notification.stack.NotificationListContainer
import com.android.systemui.statusbar.phone.NotificationGroupAlertTransferHelper
-import com.android.systemui.statusbar.phone.NotificationGroupManager
import com.android.systemui.statusbar.phone.StatusBar
import com.android.systemui.statusbar.policy.DeviceProvisionedController
import com.android.systemui.statusbar.policy.HeadsUpManager
@@ -65,7 +65,7 @@
private val deviceProvisionedController: DeviceProvisionedController,
private val notificationRowBinder: NotificationRowBinderImpl,
private val remoteInputUriController: RemoteInputUriController,
- private val groupManager: NotificationGroupManager,
+ private val groupManagerLegacy: Lazy<NotificationGroupManagerLegacy>,
private val groupAlertTransferHelper: NotificationGroupAlertTransferHelper,
private val headsUpManager: HeadsUpManager,
private val headsUpController: HeadsUpController,
@@ -111,11 +111,11 @@
} else {
targetSdkResolver.initialize(entryManager)
remoteInputUriController.attach(entryManager)
- groupAlertTransferHelper.bind(entryManager, groupManager)
- headsUpManager.addListener(groupManager)
+ groupAlertTransferHelper.bind(entryManager, groupManagerLegacy.get())
+ headsUpManager.addListener(groupManagerLegacy.get())
headsUpManager.addListener(groupAlertTransferHelper)
headsUpController.attach(entryManager, headsUpManager)
- groupManager.setHeadsUpManager(headsUpManager)
+ groupManagerLegacy.get().setHeadsUpManager(headsUpManager)
groupAlertTransferHelper.setHeadsUpManager(headsUpManager)
entryManager.attach(notificationListener)
@@ -131,7 +131,6 @@
if (dumpTruck) {
entryManager.dump(pw, " ")
}
- groupManager.dump(fd, pw, args)
}
// TODO: Convert all functions below this line into listeners instead of public methods
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubNotificationListener.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubNotificationListener.kt
index 743bf33..99b2fcc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubNotificationListener.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubNotificationListener.kt
@@ -214,7 +214,7 @@
}
private fun NotificationEntry.extractPerson(): PersonModel? {
- val type = peopleNotificationIdentifier.getPeopleNotificationType(sbn, ranking)
+ val type = peopleNotificationIdentifier.getPeopleNotificationType(this)
if (type == TYPE_NON_PERSON) {
return null
}
@@ -249,7 +249,7 @@
private fun NotificationEntry.extractPersonKey(): PersonKey? {
// TODO migrate to shortcut id when snoozing is conversation wide
- val type = peopleNotificationIdentifier.getPeopleNotificationType(sbn, ranking)
+ val type = peopleNotificationIdentifier.getPeopleNotificationType(this)
return if (type != TYPE_NON_PERSON) key else null
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt
index 1ac2cb5..0d92616 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt
@@ -20,12 +20,13 @@
import android.service.notification.NotificationListenerService.Ranking
import android.service.notification.StatusBarNotification
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier.Companion.PeopleNotificationType
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier.Companion.TYPE_FULL_PERSON
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier.Companion.TYPE_IMPORTANT_PERSON
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier.Companion.TYPE_NON_PERSON
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier.Companion.TYPE_PERSON
-import com.android.systemui.statusbar.phone.NotificationGroupManager
import javax.inject.Inject
import kotlin.math.max
@@ -40,10 +41,12 @@
* that users shortcuts.
*/
@PeopleNotificationType
- fun getPeopleNotificationType(sbn: StatusBarNotification, ranking: Ranking): Int
+ fun getPeopleNotificationType(entry: NotificationEntry): Int
- fun compareTo(@PeopleNotificationType a: Int,
- @PeopleNotificationType b: Int): Int
+ fun compareTo(
+ @PeopleNotificationType a: Int,
+ @PeopleNotificationType b: Int
+ ): Int
companion object {
@@ -62,24 +65,27 @@
@SysUISingleton
class PeopleNotificationIdentifierImpl @Inject constructor(
private val personExtractor: NotificationPersonExtractor,
- private val groupManager: NotificationGroupManager
+ private val groupManager: GroupMembershipManager
) : PeopleNotificationIdentifier {
@PeopleNotificationType
- override fun getPeopleNotificationType(sbn: StatusBarNotification, ranking: Ranking): Int =
- when (val type = ranking.personTypeInfo) {
+ override fun getPeopleNotificationType(entry: NotificationEntry): Int =
+ when (val type = entry.ranking.personTypeInfo) {
TYPE_IMPORTANT_PERSON -> TYPE_IMPORTANT_PERSON
else -> {
- when (val type = upperBound(type, extractPersonTypeInfo(sbn))) {
+ when (val type = upperBound(type, extractPersonTypeInfo(entry.sbn))) {
TYPE_IMPORTANT_PERSON -> TYPE_IMPORTANT_PERSON
- else -> upperBound(type, getPeopleTypeOfSummary(sbn))
+ else -> upperBound(type, getPeopleTypeOfSummary(entry))
}
}
}
- override fun compareTo(@PeopleNotificationType a: Int,
- @PeopleNotificationType b: Int): Int {
- return b.compareTo(a);
+ override fun compareTo(
+ @PeopleNotificationType a: Int,
+ @PeopleNotificationType b: Int
+ ): Int
+ {
+ return b.compareTo(a)
}
/**
@@ -105,14 +111,14 @@
private fun extractPersonTypeInfo(sbn: StatusBarNotification) =
if (personExtractor.isPersonNotification(sbn)) TYPE_PERSON else TYPE_NON_PERSON
- private fun getPeopleTypeOfSummary(statusBarNotification: StatusBarNotification): Int {
- if (!groupManager.isSummaryOfGroup(statusBarNotification)) {
+ private fun getPeopleTypeOfSummary(entry: NotificationEntry): Int {
+ if (!groupManager.isGroupSummary(entry)) {
return TYPE_NON_PERSON
}
- val childTypes = groupManager.getChildren(statusBarNotification)
+ val childTypes = groupManager.getChildren(entry)
?.asSequence()
- ?.map { getPeopleNotificationType(it.sbn, it.ranking) }
+ ?.map { getPeopleNotificationType(it) }
?: return TYPE_NON_PERSON
var groupType = TYPE_NON_PERSON
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index 46b4973..89f7205 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -86,6 +86,8 @@
import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager;
+import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager;
+import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
import com.android.systemui.statusbar.notification.logging.NotificationCounters;
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag;
@@ -97,7 +99,6 @@
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.notification.stack.SwipeableView;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.InflatedSmartReplies.SmartRepliesAndActions;
@@ -220,7 +221,8 @@
private boolean mNeedsRedaction;
private boolean mLastChronometerRunning = true;
private ViewStub mChildrenContainerStub;
- private NotificationGroupManager mGroupManager;
+ private GroupMembershipManager mGroupMembershipManager;
+ private GroupExpansionManager mGroupExpansionManager;
private boolean mChildrenExpanded;
private boolean mIsSummaryWithChildren;
private NotificationChildrenContainer mChildrenContainer;
@@ -269,10 +271,10 @@
@Override
public void onClick(View v) {
if (!shouldShowPublic() && (!mIsLowPriority || isExpanded())
- && mGroupManager.isSummaryOfGroup(mEntry.getSbn())) {
+ && mGroupMembershipManager.isGroupSummary(mEntry)) {
mGroupExpansionChanging = true;
- final boolean wasExpanded = mGroupManager.isGroupExpanded(mEntry.getSbn());
- boolean nowExpanded = mGroupManager.toggleGroupExpansion(mEntry.getSbn());
+ final boolean wasExpanded = mGroupExpansionManager.isGroupExpanded(mEntry);
+ boolean nowExpanded = mGroupExpansionManager.toggleGroupExpansion(mEntry);
mOnExpandClickListener.onExpandClicked(mEntry, nowExpanded);
MetricsLogger.action(mContext, MetricsEvent.ACTION_NOTIFICATION_GROUP_EXPANDER,
nowExpanded);
@@ -527,8 +529,7 @@
}
private boolean isConversation() {
- return mPeopleNotificationIdentifier
- .getPeopleNotificationType(mEntry.getSbn(), mEntry.getRanking())
+ return mPeopleNotificationIdentifier.getPeopleNotificationType(mEntry)
!= PeopleNotificationIdentifier.TYPE_NON_PERSON;
}
@@ -820,7 +821,7 @@
* @return whether this notification is the only child in the group summary
*/
public boolean isOnlyChildInGroup() {
- return mGroupManager.isOnlyChildInGroup(mEntry.getSbn());
+ return mGroupMembershipManager.isOnlyChildInGroup(mEntry);
}
public ExpandableNotificationRow getNotificationParent() {
@@ -1425,8 +1426,7 @@
public void performDismiss(boolean fromAccessibility) {
if (isOnlyChildInGroup()) {
- NotificationEntry groupSummary =
- mGroupManager.getLogicalGroupSummary(mEntry.getSbn());
+ NotificationEntry groupSummary = mGroupMembershipManager.getLogicalGroupSummary(mEntry);
if (groupSummary.isClearable()) {
// If this is the only child in the group, dismiss the group, but don't try to show
// the blocking helper affordance!
@@ -1579,7 +1579,8 @@
String notificationKey,
ExpansionLogger logger,
KeyguardBypassController bypassController,
- NotificationGroupManager groupManager,
+ GroupMembershipManager groupMembershipManager,
+ GroupExpansionManager groupExpansionManager,
HeadsUpManager headsUpManager,
RowContentBindStage rowContentBindStage,
OnExpandClickListener onExpandClickListener,
@@ -1600,8 +1601,9 @@
mLogger = logger;
mLoggingKey = notificationKey;
mBypassController = bypassController;
- mGroupManager = groupManager;
- mPrivateLayout.setGroupManager(groupManager);
+ mGroupMembershipManager = groupMembershipManager;
+ mGroupExpansionManager = groupExpansionManager;
+ mPrivateLayout.setGroupMembershipManager(groupMembershipManager);
mHeadsUpManager = headsUpManager;
mRowContentBindStage = rowContentBindStage;
mOnExpandClickListener = onExpandClickListener;
@@ -2184,8 +2186,8 @@
mFalsingManager.setNotificationExpanded();
if (mIsSummaryWithChildren && !shouldShowPublic() && allowChildExpansion
&& !mChildrenContainer.showingAsLowPriority()) {
- final boolean wasExpanded = mGroupManager.isGroupExpanded(mEntry.getSbn());
- mGroupManager.setGroupExpanded(mEntry.getSbn(), userExpanded);
+ final boolean wasExpanded = mGroupExpansionManager.isGroupExpanded(mEntry);
+ mGroupExpansionManager.setGroupExpanded(mEntry, userExpanded);
onExpansionChanged(true /* userAction */, wasExpanded);
return;
}
@@ -2328,7 +2330,7 @@
@Override
public boolean isGroupExpanded() {
- return mGroupManager.isGroupExpanded(mEntry.getSbn());
+ return mGroupExpansionManager.isGroupExpanded(mEntry);
}
private void onAttachedChildrenCountChanged() {
@@ -2574,7 +2576,7 @@
public void makeActionsVisibile() {
setUserExpanded(true, true);
if (isChildInGroup()) {
- mGroupManager.setGroupExpanded(mEntry.getSbn(), true);
+ mGroupExpansionManager.setGroupExpanded(mEntry, true);
}
notifyHeightChanged(false /* needsAnimation */);
}
@@ -2867,7 +2869,7 @@
public void onExpandedByGesture(boolean userExpanded) {
int event = MetricsEvent.ACTION_NOTIFICATION_GESTURE_EXPANDER;
- if (mGroupManager.isSummaryOfGroup(mEntry.getSbn())) {
+ if (mGroupMembershipManager.isGroupSummary(mEntry)) {
event = MetricsEvent.ACTION_NOTIFICATION_GROUP_GESTURE_EXPANDER;
}
MetricsLogger.action(mContext, event, userExpanded);
@@ -2912,7 +2914,7 @@
private void onExpansionChanged(boolean userAction, boolean wasExpanded) {
boolean nowExpanded = isExpanded();
if (mIsSummaryWithChildren && (!mIsLowPriority || wasExpanded)) {
- nowExpanded = mGroupManager.isGroupExpanded(mEntry.getSbn());
+ nowExpanded = mGroupExpansionManager.isGroupExpanded(mEntry);
}
if (nowExpanded != wasExpanded) {
updateShelfIconColor();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java
index ce760cb..05d9fe7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java
@@ -31,6 +31,8 @@
import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager;
+import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
import com.android.systemui.statusbar.notification.collection.render.NodeController;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
@@ -39,7 +41,6 @@
import com.android.systemui.statusbar.notification.row.dagger.NotificationRowScope;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.util.time.SystemClock;
@@ -62,7 +63,8 @@
private final String mAppName;
private final String mNotificationKey;
private final KeyguardBypassController mKeyguardBypassController;
- private final NotificationGroupManager mNotificationGroupManager;
+ private final GroupMembershipManager mGroupMembershipManager;
+ private final GroupExpansionManager mGroupExpansionManager;
private final RowContentBindStage mRowContentBindStage;
private final NotificationLogger mNotificationLogger;
private final HeadsUpManager mHeadsUpManager;
@@ -85,7 +87,8 @@
NotificationMediaManager mediaManager, PluginManager pluginManager,
SystemClock clock, @AppName String appName, @NotificationKey String notificationKey,
KeyguardBypassController keyguardBypassController,
- NotificationGroupManager notificationGroupManager,
+ GroupMembershipManager groupMembershipManager,
+ GroupExpansionManager groupExpansionManager,
RowContentBindStage rowContentBindStage,
NotificationLogger notificationLogger, HeadsUpManager headsUpManager,
ExpandableNotificationRow.OnExpandClickListener onExpandClickListener,
@@ -103,7 +106,8 @@
mAppName = appName;
mNotificationKey = notificationKey;
mKeyguardBypassController = keyguardBypassController;
- mNotificationGroupManager = notificationGroupManager;
+ mGroupMembershipManager = groupMembershipManager;
+ mGroupExpansionManager = groupExpansionManager;
mRowContentBindStage = rowContentBindStage;
mNotificationLogger = notificationLogger;
mHeadsUpManager = headsUpManager;
@@ -128,7 +132,8 @@
mNotificationKey,
mExpansionLogger,
mKeyguardBypassController,
- mNotificationGroupManager,
+ mGroupMembershipManager,
+ mGroupExpansionManager,
mHeadsUpManager,
mRowContentBindStage,
mOnExpandClickListener,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
index c7e44c5..1de9308 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
@@ -28,9 +28,7 @@
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.provider.Settings;
-import android.service.notification.StatusBarNotification;
import android.util.ArrayMap;
-import android.util.ArraySet;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
@@ -52,11 +50,10 @@
import com.android.systemui.statusbar.TransformableView;
import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
import com.android.systemui.statusbar.notification.row.wrapper.NotificationCustomViewWrapper;
-import com.android.systemui.statusbar.notification.row.wrapper.NotificationTemplateViewWrapper;
import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.policy.InflatedSmartReplies;
import com.android.systemui.statusbar.policy.InflatedSmartReplies.SmartRepliesAndActions;
import com.android.systemui.statusbar.policy.RemoteInputView;
@@ -122,8 +119,8 @@
private int mSmallHeight;
private int mHeadsUpHeight;
private int mNotificationMaxHeight;
- private StatusBarNotification mStatusBarNotification;
- private NotificationGroupManager mGroupManager;
+ private NotificationEntry mNotificationEntry;
+ private GroupMembershipManager mGroupMembershipManager;
private RemoteInputController mRemoteInputController;
private Runnable mExpandedVisibleListener;
private PeopleNotificationIdentifier mPeopleIdentifier;
@@ -778,7 +775,7 @@
}
private boolean isGroupExpanded() {
- return mGroupManager.isGroupExpanded(mStatusBarNotification);
+ return mContainingNotification.isGroupExpanded();
}
public void setClipTopAmount(int clipTopAmount) {
@@ -908,10 +905,10 @@
public int getBackgroundColorForExpansionState() {
// When expanding or user locked we want the new type, when collapsing we want
// the original type
- final int visibleType = (mContainingNotification.isGroupExpanded()
- || mContainingNotification.isUserLocked())
- ? calculateVisibleType()
- : getVisibleType();
+ final int visibleType = (
+ isGroupExpanded() || mContainingNotification.isUserLocked())
+ ? calculateVisibleType()
+ : getVisibleType();
return getBackgroundColor(visibleType);
}
@@ -1145,7 +1142,7 @@
}
public void onNotificationUpdated(NotificationEntry entry) {
- mStatusBarNotification = entry.getSbn();
+ mNotificationEntry = entry;
mBeforeN = entry.targetSdk < Build.VERSION_CODES.N;
updateAllSingleLineViews();
ExpandableNotificationRow row = entry.getRow();
@@ -1176,7 +1173,7 @@
if (mIsChildInGroup) {
boolean isNewView = mSingleLineView == null;
mSingleLineView = mHybridGroupManager.bindFromNotification(
- mSingleLineView, mContractedChild, mStatusBarNotification, this);
+ mSingleLineView, mContractedChild, mNotificationEntry.getSbn(), this);
if (isNewView) {
updateViewVisibility(mVisibleType, VISIBLE_TYPE_SINGLELINE,
mSingleLineView, mSingleLineView);
@@ -1363,7 +1360,7 @@
return;
}
boolean isPersonWithShortcut =
- mPeopleIdentifier.getPeopleNotificationType(entry.getSbn(), entry.getRanking())
+ mPeopleIdentifier.getPeopleNotificationType(entry)
>= PeopleNotificationIdentifier.TYPE_FULL_PERSON;
boolean showButton = isBubblesEnabled()
&& isPersonWithShortcut
@@ -1516,8 +1513,8 @@
}
}
- public void setGroupManager(NotificationGroupManager groupManager) {
- mGroupManager = groupManager;
+ public void setGroupMembershipManager(GroupMembershipManager groupMembershipManager) {
+ mGroupMembershipManager = groupMembershipManager;
}
public void setRemoteInputController(RemoteInputController r) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
index 205cecc..65a72cc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
@@ -24,7 +24,6 @@
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.annotation.Nullable;
-import android.app.Notification;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Point;
@@ -260,8 +259,7 @@
}
mFeedbackItem = createFeedbackItem(mContext);
NotificationEntry entry = mParent.getEntry();
- int personNotifType = mPeopleNotificationIdentifier
- .getPeopleNotificationType(entry.getSbn(), entry.getRanking());
+ int personNotifType = mPeopleNotificationIdentifier.getPeopleNotificationType(entry);
if (personNotifType == PeopleNotificationIdentifier.TYPE_PERSON) {
mInfoItem = createPartialConversationItem(mContext);
} else if (personNotifType >= PeopleNotificationIdentifier.TYPE_FULL_PERSON) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index 3370773..60883f0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -117,6 +117,8 @@
import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager;
import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
+import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager;
+import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
@@ -129,8 +131,6 @@
import com.android.systemui.statusbar.phone.HeadsUpTouchHelper;
import com.android.systemui.statusbar.phone.LockscreenGestureLogger;
import com.android.systemui.statusbar.phone.LockscreenGestureLogger.LockscreenUiEvent;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
-import com.android.systemui.statusbar.phone.NotificationGroupManager.OnGroupChangeListener;
import com.android.systemui.statusbar.phone.NotificationPanelViewController;
import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.phone.StatusBar;
@@ -233,7 +233,8 @@
private final StackScrollAlgorithm mStackScrollAlgorithm;
private final AmbientState mAmbientState;
- private NotificationGroupManager mGroupManager;
+ private GroupMembershipManager mGroupMembershipManager;
+ private GroupExpansionManager mGroupExpansionManager;
private NotificationActivityStarter mNotificationActivityStarter;
private HashSet<ExpandableView> mChildrenToAddAnimated = new HashSet<>();
private ArrayList<View> mAddedHeadsUpChildren = new ArrayList<>();
@@ -415,7 +416,6 @@
};
private PorterDuffXfermode mSrcMode = new PorterDuffXfermode(PorterDuff.Mode.SRC);
private boolean mPulsing;
- private boolean mGroupExpandedForMeasure;
private boolean mScrollable;
private View mForcedScroll;
@@ -560,7 +560,9 @@
NotifPipeline notifPipeline,
NotificationEntryManager entryManager,
NotifCollection notifCollection,
- UiEventLogger uiEventLogger
+ UiEventLogger uiEventLogger,
+ GroupMembershipManager groupMembershipManager,
+ GroupExpansionManager groupExpansionManager
) {
super(context, attrs, 0, 0);
Resources res = getResources();
@@ -636,6 +638,8 @@
}
});
}
+ mGroupMembershipManager = groupMembershipManager;
+ mGroupExpansionManager = groupExpansionManager;
mDynamicPrivacyController = dynamicPrivacyController;
mStatusbarStateController = statusbarStateController;
@@ -1440,7 +1444,7 @@
ExpandableNotificationRow row = mTopHeadsUpEntry.getRow();
if (row.isChildInGroup()) {
final NotificationEntry groupSummary =
- mGroupManager.getGroupSummary(row.getEntry().getSbn());
+ mGroupMembershipManager.getGroupSummary(row.getEntry());
if (groupSummary != null) {
row = groupSummary.getRow();
}
@@ -1617,9 +1621,7 @@
NotificationEntry entry = row.getEntry();
if (!mIsExpanded && row.isHeadsUp() && row.isPinned()
&& mTopHeadsUpEntry.getRow() != row
- && mGroupManager.getGroupSummary(
- mTopHeadsUpEntry.getSbn())
- != entry) {
+ && mGroupMembershipManager.getGroupSummary(mTopHeadsUpEntry) != entry) {
continue;
}
return row.getViewAtPosition(touchY - childTop);
@@ -3017,8 +3019,8 @@
@ShadeViewRefactor(RefactorComponent.ADAPTER)
private boolean isChildInGroup(View child) {
return child instanceof ExpandableNotificationRow
- && mGroupManager.isChildInGroupWithSummary(
- ((ExpandableNotificationRow) child).getEntry().getSbn());
+ && mGroupMembershipManager.isChildInGroup(
+ ((ExpandableNotificationRow) child).getEntry());
}
/**
@@ -3083,6 +3085,8 @@
return hasAddEvent;
}
+ // TODO (b/162832756): remove since this won't happen in new pipeline (we prune groups in
+ // ShadeListBuilder)
/**
* @param child the child to query
* @return whether a view is not a top level child but a child notification and that group is
@@ -3093,7 +3097,7 @@
if (child instanceof ExpandableNotificationRow) {
ExpandableNotificationRow row = (ExpandableNotificationRow) child;
NotificationEntry groupSummary =
- mGroupManager.getGroupSummary(row.getEntry().getSbn());
+ mGroupMembershipManager.getGroupSummary(row.getEntry());
if (groupSummary != null && groupSummary.getRow() != row) {
return row.getVisibility() == View.INVISIBLE;
}
@@ -4349,7 +4353,7 @@
if (changed) {
mWillExpand = false;
if (!mIsExpanded) {
- mGroupManager.collapseAllGroups();
+ mGroupExpansionManager.collapseGroups();
mExpandHelper.cancelImmediately();
}
updateNotificationAnimationStates();
@@ -4886,12 +4890,6 @@
this.mStatusBar = statusBar;
}
- @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
- public void setGroupManager(NotificationGroupManager groupManager) {
- this.mGroupManager = groupManager;
- mGroupManager.addOnGroupChangeListener(mOnGroupChangeListener);
- }
-
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
void requestAnimateEverything() {
if (mIsExpanded && mAnimationsEnabled) {
@@ -4990,17 +4988,29 @@
public void removeContainerView(View v) {
Assert.isMainThread();
removeView(v);
+ if (v instanceof ExpandableNotificationRow && !mController.isShowingEmptyShadeView()) {
+ mController.updateShowEmptyShadeView();
+ updateFooter();
+ }
}
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
public void addContainerView(View v) {
Assert.isMainThread();
addView(v);
+ if (v instanceof ExpandableNotificationRow && mController.isShowingEmptyShadeView()) {
+ mController.updateShowEmptyShadeView();
+ updateFooter();
+ }
}
public void addContainerViewAt(View v, int index) {
Assert.isMainThread();
addView(v, index);
+ if (v instanceof ExpandableNotificationRow && mController.isShowingEmptyShadeView()) {
+ mController.updateShowEmptyShadeView();
+ updateFooter();
+ }
}
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
@@ -5101,6 +5111,10 @@
updateScrollability();
}
+ boolean isQsExpanded() {
+ return mQsExpanded;
+ }
+
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
public void setQsExpansionFraction(float qsExpansionFraction) {
mQsExpansionFraction = qsExpansionFraction;
@@ -6296,39 +6310,22 @@
public HeadsUpTouchHelper.Callback getHeadsUpCallback() { return mHeadsUpCallback; }
+ void onGroupExpandChanged(ExpandableNotificationRow changedRow, boolean expanded) {
+ boolean animated = mAnimationsEnabled && (mIsExpanded || changedRow.isPinned());
+ if (animated) {
+ mExpandedGroupView = changedRow;
+ mNeedsAnimation = true;
+ }
+ changedRow.setChildrenExpanded(expanded, animated);
+ onChildHeightChanged(changedRow, false /* needsAnimation */);
- @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
- private final OnGroupChangeListener mOnGroupChangeListener = new OnGroupChangeListener() {
- @Override
- public void onGroupExpansionChanged(ExpandableNotificationRow changedRow, boolean expanded) {
- boolean animated = !mGroupExpandedForMeasure && mAnimationsEnabled
- && (mIsExpanded || changedRow.isPinned());
- if (animated) {
- mExpandedGroupView = changedRow;
- mNeedsAnimation = true;
+ runAfterAnimationFinished(new Runnable() {
+ @Override
+ public void run() {
+ changedRow.onFinishedExpansionChange();
}
- changedRow.setChildrenExpanded(expanded, animated);
- if (!mGroupExpandedForMeasure) {
- onChildHeightChanged(changedRow, false /* needsAnimation */);
- }
- runAfterAnimationFinished(new Runnable() {
- @Override
- public void run() {
- changedRow.onFinishedExpansionChange();
- }
- });
- }
-
- @Override
- public void onGroupCreatedFromChildren(NotificationGroupManager.NotificationGroup group) {
- mStatusBar.requestNotificationUpdate("onGroupCreatedFromChildren");
- }
-
- @Override
- public void onGroupsChanged() {
- mStatusBar.requestNotificationUpdate("onGroupsChanged");
- }
- };
+ });
+ }
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
private ExpandHelper.Callback mExpandHelperCallback = new ExpandHelper.Callback() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
index 70892e0..a0b49ac 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.notification.stack;
import static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME;
+import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
import android.content.res.Resources;
import android.graphics.Point;
@@ -56,6 +57,10 @@
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
import com.android.systemui.statusbar.notification.NotificationActivityStarter;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy.NotificationGroup;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy.OnGroupChangeListener;
+import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
@@ -67,7 +72,6 @@
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
import com.android.systemui.statusbar.phone.HeadsUpTouchHelper;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.NotificationPanelViewController;
import com.android.systemui.statusbar.phone.ScrimController;
import com.android.systemui.statusbar.phone.StatusBar;
@@ -117,6 +121,8 @@
private NotificationStackScrollLayout mView;
private boolean mFadeNotificationsOnDismiss;
private NotificationSwipeHelper mSwipeHelper;
+ private boolean mShowEmptyShadeView;
+ private int mBarState;
private final NotificationListContainerImpl mNotificationListContainer =
new NotificationListContainerImpl();
@@ -127,6 +133,8 @@
@Override
public void onViewAttachedToWindow(View v) {
mConfigurationController.addCallback(mConfigurationListener);
+ mZenModeController.addCallback(mZenModeControllerCallback);
+ mBarState = mStatusBarStateController.getState();
mStatusBarStateController.addCallback(
mStateListener, SysuiStatusBarStateController.RANK_STACK_SCROLLER);
}
@@ -134,6 +142,7 @@
@Override
public void onViewDetachedFromWindow(View v) {
mConfigurationController.removeCallback(mConfigurationListener);
+ mZenModeController.removeCallback(mZenModeControllerCallback);
mStatusBarStateController.removeCallback(mStateListener);
}
};
@@ -154,11 +163,13 @@
final ConfigurationListener mConfigurationListener = new ConfigurationListener() {
@Override
public void onDensityOrFontScaleChanged() {
+ updateShowEmptyShadeView();
mView.reinflateViews();
}
@Override
public void onOverlayChanged() {
+ updateShowEmptyShadeView();
mView.updateCornerRadius();
mView.reinflateViews();
}
@@ -179,14 +190,15 @@
@Override
public void onStatePreChange(int oldState, int newState) {
if (oldState == StatusBarState.SHADE_LOCKED
- && newState == StatusBarState.KEYGUARD) {
+ && newState == KEYGUARD) {
mView.requestAnimateEverything();
}
}
@Override
public void onStateChanged(int newState) {
- mView.setStatusBarState(newState);
+ mBarState = newState;
+ mView.setStatusBarState(mBarState);
}
@Override
@@ -480,6 +492,14 @@
}
};
+ private final ZenModeController.Callback mZenModeControllerCallback =
+ new ZenModeController.Callback() {
+ @Override
+ public void onZenChanged(int zen) {
+ updateShowEmptyShadeView();
+ }
+ };
+
@Inject
public NotificationStackScrollLayoutController(
@Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME) boolean allowLongPress,
@@ -501,7 +521,9 @@
@Main Resources resources,
NotificationSwipeHelper.Builder notificationSwipeHelperBuilder,
StatusBar statusBar,
- ScrimController scrimController) {
+ ScrimController scrimController,
+ NotificationGroupManagerLegacy legacyGroupManager,
+ GroupExpansionManager groupManager) {
mAllowLongPress = allowLongPress;
mNotificationGutsManager = notificationGutsManager;
mHeadsUpManager = headsUpManager;
@@ -522,12 +544,28 @@
mNotificationSwipeHelperBuilder = notificationSwipeHelperBuilder;
mStatusBar = statusBar;
mScrimController = scrimController;
+ groupManager.registerGroupExpansionChangeListener((changedRow, expanded) -> {
+ mView.onGroupExpandChanged(changedRow, expanded);
+ });
+
+ legacyGroupManager.registerGroupChangeListener(new OnGroupChangeListener() {
+ @Override
+ public void onGroupCreatedFromChildren(NotificationGroup group) {
+ mStatusBar.requestNotificationUpdate("onGroupCreatedFromChildren");
+ }
+
+ @Override
+ public void onGroupsChanged() {
+ mStatusBar.requestNotificationUpdate("onGroupsChanged");
+ }
+ });
}
public void attach(NotificationStackScrollLayout view) {
mView = view;
mView.setController(this);
mView.setTouchHandler(new TouchHandler());
+ mView.setStatusBar(mStatusBar);
mSwipeHelper = mNotificationSwipeHelperBuilder
.setSwipeDirection(SwipeHelper.X)
@@ -795,6 +833,7 @@
public void setQsExpanded(boolean expanded) {
mView.setQsExpanded(expanded);
+ updateShowEmptyShadeView();
}
public void setScrollingEnabled(boolean enabled) {
@@ -903,8 +942,21 @@
return mView.getFooterViewHeightWithPadding();
}
- public void updateEmptyShadeView(boolean visible) {
- mView.updateEmptyShadeView(visible, mZenModeController.areNotificationsHiddenInShade());
+ /**
+ * Update whether we should show the empty shade view (no notifications in the shade).
+ * If so, send the update to our view.
+ */
+ public void updateShowEmptyShadeView() {
+ mShowEmptyShadeView = mBarState != KEYGUARD
+ && !mView.isQsExpanded()
+ && mView.getVisibleNotificationCount() == 0;
+ mView.updateEmptyShadeView(
+ mShowEmptyShadeView,
+ mZenModeController.areNotificationsHiddenInShade());
+ }
+
+ public boolean isShowingEmptyShadeView() {
+ return mShowEmptyShadeView;
}
public void setHeadsUpAnimatingAway(boolean headsUpAnimatingAway) {
@@ -1012,14 +1064,6 @@
mView.setNotificationPanelController(notificationPanelViewController);
}
- public void setStatusBar(StatusBar statusBar) {
- mView.setStatusBar(statusBar);
- }
-
- public void setGroupManager(NotificationGroupManager groupManager) {
- mView.setGroupManager(groupManager);
- }
-
public void setShelfController(NotificationShelfController notificationShelfController) {
mView.setShelfController(notificationShelfController);
}
@@ -1095,6 +1139,7 @@
}
private class NotificationListContainerImpl implements NotificationListContainer {
+
@Override
public void setChildTransferInProgress(boolean childTransferInProgress) {
mView.setChildTransferInProgress(childTransferInProgress);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
index 8092cb9..3827123f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
@@ -33,6 +33,7 @@
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager;
+import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
@@ -55,7 +56,7 @@
@VisibleForTesting
final int mExtensionTime;
private final KeyguardBypassController mBypassController;
- private final NotificationGroupManager mGroupManager;
+ private final GroupMembershipManager mGroupMembershipManager;
private final List<OnHeadsUpPhoneListenerChange> mHeadsUpPhoneListeners = new ArrayList<>();
private final int mAutoHeadsUpNotificationDecay;
// TODO (b/162832756): remove visual stability manager when migrating to new pipeline
@@ -101,7 +102,7 @@
public HeadsUpManagerPhone(@NonNull final Context context,
StatusBarStateController statusBarStateController,
KeyguardBypassController bypassController,
- NotificationGroupManager groupManager,
+ GroupMembershipManager groupMembershipManager,
ConfigurationController configurationController) {
super(context);
Resources resources = mContext.getResources();
@@ -110,7 +111,7 @@
R.integer.auto_heads_up_notification_decay);
statusBarStateController.addCallback(mStatusBarStateListener);
mBypassController = bypassController;
- mGroupManager = groupManager;
+ mGroupMembershipManager = groupMembershipManager;
updateResources();
configurationController.addCallback(new ConfigurationController.ConfigurationListener() {
@@ -166,7 +167,7 @@
} else {
if (topEntry.isChildInGroup()) {
final NotificationEntry groupSummary =
- mGroupManager.getGroupSummary(topEntry.getSbn());
+ mGroupMembershipManager.getGroupSummary(topEntry);
if (groupSummary != null) {
topEntry = groupSummary;
}
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 b6a284c..09034c0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -40,6 +40,8 @@
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.keyguard.ViewMediatorCallback;
+import com.android.keyguard.dagger.ContainerView;
+import com.android.keyguard.dagger.KeyguardBouncerScope;
import com.android.systemui.DejankUtils;
import com.android.systemui.Dependency;
import com.android.systemui.R;
@@ -50,9 +52,12 @@
import java.io.PrintWriter;
+import javax.inject.Inject;
+
/**
* A class which manages the bouncer on the lockscreen.
*/
+@KeyguardBouncerScope
public class KeyguardBouncer {
private static final String TAG = "KeyguardBouncer";
@@ -95,8 +100,9 @@
private boolean mIsAnimatingAway;
private boolean mIsScrimmed;
+ @Inject
public KeyguardBouncer(Context context, ViewMediatorCallback callback,
- LockPatternUtils lockPatternUtils, ViewGroup container,
+ LockPatternUtils lockPatternUtils, @ContainerView ViewGroup container,
DismissCallbackRegistry dismissCallbackRegistry, FalsingManager falsingManager,
BouncerExpansionCallback expansionCallback,
KeyguardStateController keyguardStateController,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java
index dd9c820..3181f52 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java
@@ -31,11 +31,11 @@
import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy.NotificationGroup;
import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag;
import com.android.systemui.statusbar.notification.row.RowContentBindParams;
import com.android.systemui.statusbar.notification.row.RowContentBindStage;
-import com.android.systemui.statusbar.phone.NotificationGroupManager.NotificationGroup;
-import com.android.systemui.statusbar.phone.NotificationGroupManager.OnGroupChangeListener;
import com.android.systemui.statusbar.phone.dagger.StatusBarPhoneModule;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
@@ -44,8 +44,8 @@
import java.util.Objects;
/**
- * A helper class dealing with the alert interactions between {@link NotificationGroupManager} and
- * {@link HeadsUpManager}. In particular, this class deals with keeping
+ * A helper class dealing with the alert interactions between {@link NotificationGroupManagerLegacy}
+ * and {@link HeadsUpManager}. In particular, this class deals with keeping
* the correct notification in a group alerting based off the group suppression.
*/
public class NotificationGroupAlertTransferHelper implements OnHeadsUpChangedListener,
@@ -66,8 +66,8 @@
private HeadsUpManager mHeadsUpManager;
private final RowContentBindStage mRowContentBindStage;
- private final NotificationGroupManager mGroupManager =
- Dependency.get(NotificationGroupManager.class);
+ private final NotificationGroupManagerLegacy mGroupManager =
+ Dependency.get(NotificationGroupManagerLegacy.class);
private NotificationEntryManager mEntryManager;
@@ -83,7 +83,7 @@
/** Causes the TransferHelper to register itself as a listener to the appropriate classes. */
public void bind(NotificationEntryManager entryManager,
- NotificationGroupManager groupManager) {
+ NotificationGroupManagerLegacy groupManager) {
if (mEntryManager != null) {
throw new IllegalStateException("Already bound.");
}
@@ -95,7 +95,7 @@
mEntryManager = entryManager;
mEntryManager.addNotificationEntryListener(mNotificationEntryListener);
- groupManager.addOnGroupChangeListener(mOnGroupChangeListener);
+ groupManager.registerGroupChangeListener(mOnGroupChangeListener);
}
/**
@@ -128,7 +128,8 @@
mIsDozing = isDozing;
}
- private final OnGroupChangeListener mOnGroupChangeListener = new OnGroupChangeListener() {
+ private final NotificationGroupManagerLegacy.OnGroupChangeListener mOnGroupChangeListener =
+ new NotificationGroupManagerLegacy.OnGroupChangeListener() {
@Override
public void onGroupCreated(NotificationGroup group, String groupKey) {
mGroupAlertEntries.put(groupKey, new GroupAlertEntry(group));
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
index 1cd85e3..169058a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -107,6 +107,8 @@
import com.android.systemui.statusbar.notification.ViewGroupFadeHelper;
import com.android.systemui.statusbar.notification.collection.ListEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
+import com.android.systemui.statusbar.notification.collection.render.ShadeViewManager;
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.ExpandableView;
@@ -120,7 +122,6 @@
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
-import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.util.InjectionInflationController;
import java.io.FileDescriptor;
@@ -168,9 +169,6 @@
mOnHeadsUpChangedListener =
new MyOnHeadsUpChangedListener();
private final HeightListener mHeightListener = new HeightListener();
- private final ZenModeControllerCallback
- mZenModeControllerCallback =
- new ZenModeControllerCallback();
private final ConfigurationListener mConfigurationListener = new ConfigurationListener();
private final StatusBarStateListener mStatusBarStateListener = new StatusBarStateListener();
private final ExpansionCallback mExpansionCallback = new ExpansionCallback();
@@ -178,7 +176,6 @@
private final NotificationPanelView mView;
private final MetricsLogger mMetricsLogger;
private final ActivityManager mActivityManager;
- private final ZenModeController mZenModeController;
private final ConfigurationController mConfigurationController;
private final FlingAnimationUtils.Builder mFlingAnimationUtilsBuilder;
private final NotificationStackScrollLayoutController mNotificationStackScrollLayoutController;
@@ -342,8 +339,6 @@
private boolean mKeyguardStatusViewAnimating;
private ValueAnimator mQsSizeChangeAnimator;
- private boolean mShowEmptyShadeView;
-
private boolean mQsScrimEnabled = true;
private boolean mQsTouchAboveFalsingThreshold;
private int mQsFalsingThreshold;
@@ -367,7 +362,8 @@
setHeadsUpAnimatingAway(false);
notifyBarPanelExpansionChanged();
};
- private NotificationGroupManager mGroupManager;
+ // TODO (b/162832756): once migrated to the new pipeline, delete legacy group manager
+ private NotificationGroupManagerLegacy mGroupManager;
private boolean mShowIconsWhenExpanded;
private int mIndicationBottomPadding;
private int mAmbientIndicationBottomPadding;
@@ -505,7 +501,7 @@
LatencyTracker latencyTracker, PowerManager powerManager,
AccessibilityManager accessibilityManager, @DisplayId int displayId,
KeyguardUpdateMonitor keyguardUpdateMonitor, MetricsLogger metricsLogger,
- ActivityManager activityManager, ZenModeController zenModeController,
+ ActivityManager activityManager,
ConfigurationController configurationController,
FlingAnimationUtils.Builder flingAnimationUtilsBuilder,
StatusBarTouchableRegionManager statusBarTouchableRegionManager,
@@ -514,20 +510,21 @@
BiometricUnlockController biometricUnlockController,
StatusBarKeyguardViewManager statusBarKeyguardViewManager,
NotificationStackScrollLayoutController notificationStackScrollLayoutController,
- NotificationIconAreaController notificationIconAreaController,
- KeyguardStatusViewComponent.Factory keyguardStatusViewComponentFactory) {
+ KeyguardStatusViewComponent.Factory keyguardStatusViewComponentFactory,
+ NotificationGroupManagerLegacy groupManager,
+ NotificationIconAreaController notificationIconAreaController) {
super(view, falsingManager, dozeLog, keyguardStateController,
(SysuiStatusBarStateController) statusBarStateController, vibratorHelper,
latencyTracker, flingAnimationUtilsBuilder, statusBarTouchableRegionManager);
mView = view;
mMetricsLogger = metricsLogger;
mActivityManager = activityManager;
- mZenModeController = zenModeController;
mConfigurationController = configurationController;
mFlingAnimationUtilsBuilder = flingAnimationUtilsBuilder;
mMediaHierarchyManager = mediaHierarchyManager;
mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
mNotificationStackScrollLayoutController = notificationStackScrollLayoutController;
+ mGroupManager = groupManager;
mNotificationIconAreaController = notificationIconAreaController;
mKeyguardStatusViewComponentFactory = keyguardStatusViewComponentFactory;
mView.setWillNotDraw(!DEBUG);
@@ -724,8 +721,6 @@
}
private void reInflateViews() {
- updateShowEmptyShadeView();
-
// Re-inflate the status view group.
int index = mView.indexOfChild(mKeyguardStatusView);
mView.removeView(mKeyguardStatusView);
@@ -1727,7 +1722,6 @@
mNotificationStackScrollLayoutController.setScrollingEnabled(
mBarState != KEYGUARD && (!mQsExpanded
|| mQsExpansionFromOverscroll));
- updateEmptyShadeView();
mQsNavbarScrim.setVisibility(
mBarState == StatusBarState.SHADE && mQsExpanded && !mStackScrollerOverscrolling
@@ -2145,7 +2139,7 @@
// it in expanded QS state as well so we don't run into troubles when fading the view in/out
// and expanding/collapsing the whole panel from/to quick settings.
if (mNotificationStackScrollLayoutController.getNotGoneChildCount() == 0
- && mShowEmptyShadeView) {
+ && mNotificationStackScrollLayoutController.isShowingEmptyShadeView()) {
notificationHeight = mNotificationStackScrollLayoutController.getEmptyShadeViewHeight();
}
int maxQsHeight = mQsMaxExpansionHeight;
@@ -2561,17 +2555,6 @@
return mDozing;
}
- public void showEmptyShadeView(boolean emptyShadeViewVisible) {
- mShowEmptyShadeView = emptyShadeViewVisible;
- updateEmptyShadeView();
- }
-
- private void updateEmptyShadeView() {
- // Hide "No notifications" in QS.
- mNotificationStackScrollLayoutController.updateEmptyShadeView(
- mShowEmptyShadeView && !mQsExpanded);
- }
-
public void setQsScrimEnabled(boolean qsScrimEnabled) {
boolean changed = mQsScrimEnabled != qsScrimEnabled;
mQsScrimEnabled = qsScrimEnabled;
@@ -2873,10 +2856,6 @@
return !tasks.isEmpty() && pkgName.equals(tasks.get(0).topActivity.getPackageName());
}
- private void setGroupManager(NotificationGroupManager groupManager) {
- mGroupManager = groupManager;
- }
-
public boolean hideStatusBarIconsWhenExpanded() {
if (mLaunchingNotification) {
return mHideIconsDuringNotificationLaunch;
@@ -3078,22 +3057,21 @@
return mNotificationStackScrollLayoutController.hasActiveClearableNotifications(ROWS_ALL);
}
- private void updateShowEmptyShadeView() {
- boolean
- showEmptyShadeView =
- mBarState != KEYGUARD && !mEntryManager.hasActiveNotifications();
- showEmptyShadeView(showEmptyShadeView);
- }
-
public RemoteInputController.Delegate createRemoteInputDelegate() {
return mNotificationStackScrollLayoutController.createDelegate();
}
- void updateNotificationViews(String reason) {
+ /**
+ * Updates the notification views' sections and status bar icons. This is
+ * triggered by the NotificationPresenter whenever there are changes to the underlying
+ * notification data being displayed. In the new notification pipeline, this is handled in
+ * {@link ShadeViewManager}.
+ */
+ public void updateNotificationViews(String reason) {
mNotificationStackScrollLayoutController.updateSectionBoundaries(reason);
mNotificationStackScrollLayoutController.updateSpeedBumpIndex();
mNotificationStackScrollLayoutController.updateFooter();
- updateShowEmptyShadeView();
+
mNotificationIconAreaController.updateNotificationIcons(createVisibleEntriesList());
}
@@ -3139,15 +3117,10 @@
*/
public void initDependencies(
StatusBar statusBar,
- NotificationGroupManager groupManager,
NotificationShelfController notificationShelfController) {
setStatusBar(statusBar);
- setGroupManager(mGroupManager);
mNotificationStackScrollLayoutController.setNotificationPanelController(this);
- mNotificationStackScrollLayoutController.setStatusBar(statusBar);
- mNotificationStackScrollLayoutController.setGroupManager(groupManager);
mNotificationStackScrollLayoutController.setShelfController(notificationShelfController);
- updateShowEmptyShadeView();
mNotificationShelfController = notificationShelfController;
updateMaxDisplayedNotifications(true);
}
@@ -3602,20 +3575,8 @@
}
}
- private class ZenModeControllerCallback implements ZenModeController.Callback {
- @Override
- public void onZenChanged(int zen) {
- updateShowEmptyShadeView();
- }
- }
-
private class ConfigurationListener implements ConfigurationController.ConfigurationListener {
@Override
- public void onDensityOrFontScaleChanged() {
- updateShowEmptyShadeView();
- }
-
- @Override
public void onThemeChanged() {
final int themeResId = mView.getContext().getThemeResId();
if (mThemeResId == themeResId) {
@@ -3712,7 +3673,6 @@
public void onViewAttachedToWindow(View v) {
FragmentHostManager.get(mView).addTagListener(QS.TAG, mFragmentListener);
mStatusBarStateController.addCallback(mStatusBarStateListener);
- mZenModeController.addCallback(mZenModeControllerCallback);
mConfigurationController.addCallback(mConfigurationListener);
mUpdateMonitor.registerCallback(mKeyguardUpdateCallback);
// Theme might have changed between inflating this view and attaching it to the
@@ -3725,7 +3685,6 @@
public void onViewDetachedFromWindow(View v) {
FragmentHostManager.get(mView).removeTagListener(QS.TAG, mFragmentListener);
mStatusBarStateController.removeCallback(mStatusBarStateListener);
- mZenModeController.removeCallback(mZenModeControllerCallback);
mConfigurationController.removeCallback(mConfigurationListener);
mUpdateMonitor.removeCallback(mKeyguardUpdateCallback);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 5882879..2986727 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -699,7 +699,6 @@
SysuiStatusBarStateController statusBarStateController,
VibratorHelper vibratorHelper,
BubbleController bubbleController,
- NotificationGroupManager groupManager,
VisualStabilityManager visualStabilityManager,
DeviceProvisionedController deviceProvisionedController,
NavigationBarController navigationBarController,
@@ -780,7 +779,6 @@
mStatusBarStateController = statusBarStateController;
mVibratorHelper = vibratorHelper;
mBubbleController = bubbleController;
- mGroupManager = groupManager;
mVisualStabilityManager = visualStabilityManager;
mDeviceProvisionedController = deviceProvisionedController;
mNavigationBarController = navigationBarController;
@@ -1159,7 +1157,6 @@
mNotificationPanelViewController.initDependencies(
this,
- mGroupManager,
mNotificationShelfController);
BackDropView backdrop = mNotificationShadeWindowView.findViewById(R.id.backdrop);
@@ -1506,9 +1503,8 @@
mStatusBarKeyguardViewManager.registerStatusBar(
/* statusBar= */ this, getBouncerContainer(),
mNotificationPanelViewController, mBiometricUnlockController,
- mDismissCallbackRegistry,
mNotificationShadeWindowView.findViewById(R.id.lock_icon_container),
- mStackScroller, mKeyguardBypassController, mFalsingManager);
+ mStackScroller, mKeyguardBypassController);
mKeyguardIndicationController
.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
mBiometricUnlockController.setKeyguardViewController(mStatusBarKeyguardViewManager);
@@ -4084,8 +4080,6 @@
// all notifications
protected NotificationStackScrollLayout mStackScroller;
- private final NotificationGroupManager mGroupManager;
-
// handling reordering
private final VisualStabilityManager mVisualStabilityManager;
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 777bf3f7..b56993b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -44,15 +44,13 @@
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.keyguard.KeyguardViewController;
import com.android.keyguard.ViewMediatorCallback;
+import com.android.keyguard.dagger.KeyguardBouncerComponent;
import com.android.settingslib.animation.AppearAnimationUtils;
import com.android.systemui.DejankUtils;
-import com.android.systemui.SystemUIFactory;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dock.DockManager;
-import com.android.systemui.keyguard.DismissCallbackRegistry;
import com.android.systemui.keyguard.FaceAuthScreenBrightnessController;
import com.android.systemui.navigationbar.NavigationModeController;
-import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.shared.system.SysUiStatsLog;
@@ -106,6 +104,7 @@
private final NavigationModeController mNavigationModeController;
private final NotificationShadeWindowController mNotificationShadeWindowController;
private final Optional<FaceAuthScreenBrightnessController> mFaceAuthScreenBrightnessController;
+ private final KeyguardBouncerComponent.Factory mKeyguardBouncerComponentFactory;
private final BouncerExpansionCallback mExpansionCallback = new BouncerExpansionCallback() {
@Override
public void onFullyShown() {
@@ -216,7 +215,8 @@
NotificationShadeWindowController notificationShadeWindowController,
KeyguardStateController keyguardStateController,
Optional<FaceAuthScreenBrightnessController> faceAuthScreenBrightnessController,
- NotificationMediaManager notificationMediaManager) {
+ NotificationMediaManager notificationMediaManager,
+ KeyguardBouncerComponent.Factory keyguardBouncerComponentFactory) {
mContext = context;
mViewMediatorCallback = callback;
mLockPatternUtils = lockPatternUtils;
@@ -229,6 +229,7 @@
mStatusBarStateController = sysuiStatusBarStateController;
mDockManager = dockManager;
mFaceAuthScreenBrightnessController = faceAuthScreenBrightnessController;
+ mKeyguardBouncerComponentFactory = keyguardBouncerComponentFactory;
}
@Override
@@ -236,9 +237,8 @@
ViewGroup container,
NotificationPanelViewController notificationPanelViewController,
BiometricUnlockController biometricUnlockController,
- DismissCallbackRegistry dismissCallbackRegistry,
ViewGroup lockIconContainer, View notificationContainer,
- KeyguardBypassController bypassController, FalsingManager falsingManager) {
+ KeyguardBypassController bypassController) {
mStatusBar = statusBar;
mContainer = container;
mLockIconContainer = lockIconContainer;
@@ -246,9 +246,9 @@
mLastLockVisible = mLockIconContainer.getVisibility() == View.VISIBLE;
}
mBiometricUnlockController = biometricUnlockController;
- mBouncer = SystemUIFactory.getInstance().createKeyguardBouncer(mContext,
- mViewMediatorCallback, mLockPatternUtils, container, dismissCallbackRegistry,
- mExpansionCallback, mKeyguardStateController, falsingManager, bypassController);
+ mBouncer = mKeyguardBouncerComponentFactory
+ .build(container, mExpansionCallback)
+ .createKeyguardBouncer();
mNotificationPanelViewController = notificationPanelViewController;
notificationPanelViewController.addExpansionListener(this);
mBypassController = bypassController;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
index de11c90..f806567 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
@@ -66,10 +66,10 @@
import com.android.systemui.statusbar.notification.NotificationActivityStarter;
import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
-import com.android.systemui.statusbar.notification.collection.NotifCollection;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
+import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
@@ -96,7 +96,6 @@
private final NotificationEntryManager mEntryManager;
private final NotifPipeline mNotifPipeline;
- private final NotifCollection mNotifCollection;
private final HeadsUpManagerPhone mHeadsUpManager;
private final ActivityStarter mActivityStarter;
private final NotificationClickNotifier mClickNotifier;
@@ -107,7 +106,7 @@
private final BubbleController mBubbleController;
private final Lazy<AssistManager> mAssistManagerLazy;
private final NotificationRemoteInputManager mRemoteInputManager;
- private final NotificationGroupManager mGroupManager;
+ private final GroupMembershipManager mGroupMembershipManager;
private final NotificationLockscreenUserManager mLockscreenUserManager;
private final ShadeController mShadeController;
private final KeyguardStateController mKeyguardStateController;
@@ -135,7 +134,6 @@
Executor uiBgExecutor,
NotificationEntryManager entryManager,
NotifPipeline notifPipeline,
- NotifCollection notifCollection,
HeadsUpManagerPhone headsUpManager,
ActivityStarter activityStarter,
NotificationClickNotifier clickNotifier,
@@ -146,7 +144,7 @@
BubbleController bubbleController,
Lazy<AssistManager> assistManagerLazy,
NotificationRemoteInputManager remoteInputManager,
- NotificationGroupManager groupManager,
+ GroupMembershipManager groupMembershipManager,
NotificationLockscreenUserManager lockscreenUserManager,
ShadeController shadeController,
KeyguardStateController keyguardStateController,
@@ -170,7 +168,6 @@
mUiBgExecutor = uiBgExecutor;
mEntryManager = entryManager;
mNotifPipeline = notifPipeline;
- mNotifCollection = notifCollection;
mHeadsUpManager = headsUpManager;
mActivityStarter = activityStarter;
mClickNotifier = clickNotifier;
@@ -181,7 +178,7 @@
mBubbleController = bubbleController;
mAssistManagerLazy = assistManagerLazy;
mRemoteInputManager = remoteInputManager;
- mGroupManager = groupManager;
+ mGroupMembershipManager = groupMembershipManager;
mLockscreenUserManager = lockscreenUserManager;
mShadeController = shadeController;
mKeyguardStateController = keyguardStateController;
@@ -228,8 +225,9 @@
public void onNotificationClicked(StatusBarNotification sbn, ExpandableNotificationRow row) {
mLogger.logStartingActivityFromClick(sbn.getKey());
+ final NotificationEntry entry = row.getEntry();
RemoteInputController controller = mRemoteInputManager.getController();
- if (controller.isRemoteInputActive(row.getEntry())
+ if (controller.isRemoteInputActive(entry)
&& !TextUtils.isEmpty(row.getActiveRemoteInputText())) {
// We have an active remote input typed and the user clicked on the notification.
// this was probably unintentional, so we're closing the edit text instead.
@@ -240,7 +238,7 @@
final PendingIntent intent = notification.contentIntent != null
? notification.contentIntent
: notification.fullScreenIntent;
- final boolean isBubble = row.getEntry().isBubble();
+ final boolean isBubble = entry.isBubble();
// This code path is now executed for notification without a contentIntent.
// The only valid case is Bubble notifications. Guard against other cases
@@ -260,7 +258,7 @@
mLockscreenUserManager.getCurrentUserId());
ActivityStarter.OnDismissAction postKeyguardAction =
() -> handleNotificationClickAfterKeyguardDismissed(
- sbn, row, controller, intent,
+ entry, row, controller, intent,
isActivityIntent, wasOccluded, showOverLockscreen);
if (showOverLockscreen) {
mIsCollapsingToShowActivityOverLockscreen = true;
@@ -272,27 +270,27 @@
}
private boolean handleNotificationClickAfterKeyguardDismissed(
- StatusBarNotification sbn,
+ NotificationEntry entry,
ExpandableNotificationRow row,
RemoteInputController controller,
PendingIntent intent,
boolean isActivityIntent,
boolean wasOccluded,
boolean showOverLockscreen) {
- mLogger.logHandleClickAfterKeyguardDismissed(sbn.getKey());
+ mLogger.logHandleClickAfterKeyguardDismissed(entry.getKey());
// TODO: Some of this code may be able to move to NotificationEntryManager.
removeHUN(row);
NotificationEntry parentToCancel = null;
- if (shouldAutoCancel(sbn) && mGroupManager.isOnlyChildInGroup(sbn)) {
- NotificationEntry summarySbn = mGroupManager.getLogicalGroupSummary(sbn);
+ if (shouldAutoCancel(entry.getSbn()) && mGroupMembershipManager.isOnlyChildInGroup(entry)) {
+ NotificationEntry summarySbn = mGroupMembershipManager.getLogicalGroupSummary(entry);
if (shouldAutoCancel(summarySbn.getSbn())) {
parentToCancel = summarySbn;
}
}
final NotificationEntry parentToCancelFinal = parentToCancel;
final Runnable runnable = () -> handleNotificationClickAfterPanelCollapsed(
- sbn, row, controller, intent,
+ entry, row, controller, intent,
isActivityIntent, wasOccluded, parentToCancelFinal);
if (showOverLockscreen) {
@@ -309,16 +307,16 @@
}
private void handleNotificationClickAfterPanelCollapsed(
- StatusBarNotification sbn,
+ NotificationEntry entry,
ExpandableNotificationRow row,
RemoteInputController controller,
PendingIntent intent,
boolean isActivityIntent,
boolean wasOccluded,
NotificationEntry parentToCancelFinal) {
- mLogger.logHandleClickAfterPanelCollapsed(sbn.getKey());
+ String notificationKey = entry.getKey();
+ mLogger.logHandleClickAfterPanelCollapsed(notificationKey);
- String notificationKey = sbn.getKey();
try {
// The intent we are sending is for the application, which
// won't have permission to immediately start an activity after
@@ -346,7 +344,6 @@
}
}
Intent fillInIntent = null;
- NotificationEntry entry = row.getEntry();
CharSequence remoteInputText = null;
if (!TextUtils.isEmpty(entry.remoteInputText)) {
remoteInputText = entry.remoteInputText;
@@ -385,7 +382,7 @@
// necessary in the new pipeline due to group pruning in ShadeListBuilder.
removeNotification(parentToCancelFinal);
}
- if (shouldAutoCancel(sbn)
+ if (shouldAutoCancel(entry.getSbn())
|| mRemoteInputManager.isNotificationKeptForRemoteInputHistory(
notificationKey)) {
// Automatically remove all notifications that we may have kept around longer
@@ -605,7 +602,6 @@
private final Executor mUiBgExecutor;
private final NotificationEntryManager mEntryManager;
private final NotifPipeline mNotifPipeline;
- private final NotifCollection mNotifCollection;
private final HeadsUpManagerPhone mHeadsUpManager;
private final ActivityStarter mActivityStarter;
private final NotificationClickNotifier mClickNotifier;
@@ -616,7 +612,7 @@
private final BubbleController mBubbleController;
private final Lazy<AssistManager> mAssistManagerLazy;
private final NotificationRemoteInputManager mRemoteInputManager;
- private final NotificationGroupManager mGroupManager;
+ private final GroupMembershipManager mGroupMembershipManager;
private final NotificationLockscreenUserManager mLockscreenUserManager;
private final ShadeController mShadeController;
private final KeyguardStateController mKeyguardStateController;
@@ -643,7 +639,6 @@
@UiBackground Executor uiBgExecutor,
NotificationEntryManager entryManager,
NotifPipeline notifPipeline,
- NotifCollection notifCollection,
HeadsUpManagerPhone headsUpManager,
ActivityStarter activityStarter,
NotificationClickNotifier clickNotifier,
@@ -654,7 +649,7 @@
BubbleController bubbleController,
Lazy<AssistManager> assistManagerLazy,
NotificationRemoteInputManager remoteInputManager,
- NotificationGroupManager groupManager,
+ GroupMembershipManager groupMembershipManager,
NotificationLockscreenUserManager lockscreenUserManager,
ShadeController shadeController,
KeyguardStateController keyguardStateController,
@@ -674,7 +669,6 @@
mUiBgExecutor = uiBgExecutor;
mEntryManager = entryManager;
mNotifPipeline = notifPipeline;
- mNotifCollection = notifCollection;
mHeadsUpManager = headsUpManager;
mActivityStarter = activityStarter;
mClickNotifier = clickNotifier;
@@ -685,7 +679,7 @@
mBubbleController = bubbleController;
mAssistManagerLazy = assistManagerLazy;
mRemoteInputManager = remoteInputManager;
- mGroupManager = groupManager;
+ mGroupMembershipManager = groupMembershipManager;
mLockscreenUserManager = lockscreenUserManager;
mShadeController = shadeController;
mKeyguardStateController = keyguardStateController;
@@ -731,7 +725,6 @@
mUiBgExecutor,
mEntryManager,
mNotifPipeline,
- mNotifCollection,
mHeadsUpManager,
mActivityStarter,
mClickNotifier,
@@ -742,7 +735,7 @@
mBubbleController,
mAssistManagerLazy,
mRemoteInputManager,
- mGroupManager,
+ mGroupMembershipManager,
mLockscreenUserManager,
mShadeController,
mKeyguardStateController,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java
index 8a89429..36519ac 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java
@@ -45,6 +45,7 @@
import com.android.systemui.statusbar.NotificationRemoteInputManager.Callback;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
+import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -65,7 +66,7 @@
private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
private final ShadeController mShadeController;
private final ActivityIntentHelper mActivityIntentHelper;
- private final NotificationGroupManager mGroupManager;
+ private final GroupExpansionManager mGroupExpansionManager;
private View mPendingWorkRemoteInputView;
private View mPendingRemoteInputView;
private KeyguardManager mKeyguardManager;
@@ -78,12 +79,15 @@
/**
*/
@Inject
- public StatusBarRemoteInputCallback(Context context, NotificationGroupManager groupManager,
+ public StatusBarRemoteInputCallback(
+ Context context,
+ GroupExpansionManager groupExpansionManager,
NotificationLockscreenUserManager notificationLockscreenUserManager,
KeyguardStateController keyguardStateController,
StatusBarStateController statusBarStateController,
StatusBarKeyguardViewManager statusBarKeyguardViewManager,
- ActivityStarter activityStarter, ShadeController shadeController,
+ ActivityStarter activityStarter,
+ ShadeController shadeController,
CommandQueue commandQueue,
ActionClickLogger clickLogger) {
mContext = context;
@@ -101,7 +105,7 @@
mCommandQueue.addCallback(this);
mActionClickLogger = clickLogger;
mActivityIntentHelper = new ActivityIntentHelper(mContext);
- mGroupManager = groupManager;
+ mGroupExpansionManager = groupExpansionManager;
}
@Override
@@ -182,7 +186,7 @@
} else {
if (row.isChildInGroup() && !row.areChildrenExpanded()) {
// The group isn't expanded, let's make sure it's visible!
- mGroupManager.toggleGroupExpansion(row.getEntry().getSbn());
+ mGroupExpansionManager.toggleGroupExpansion(row.getEntry());
}
row.setUserExpanded(true);
row.getPrivateLayout().setOnExpandedVisibleListener(clickedView::performClick);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
index 72067d3..16c3dc4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
@@ -80,7 +80,6 @@
import com.android.systemui.statusbar.phone.LightsOutNotifController;
import com.android.systemui.statusbar.phone.LockscreenLockIconController;
import com.android.systemui.statusbar.phone.LockscreenWallpaper;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.NotificationIconAreaController;
import com.android.systemui.statusbar.phone.PhoneStatusBarPolicy;
import com.android.systemui.statusbar.phone.ScrimController;
@@ -158,7 +157,6 @@
SysuiStatusBarStateController statusBarStateController,
VibratorHelper vibratorHelper,
BubbleController bubbleController,
- NotificationGroupManager groupManager,
VisualStabilityManager visualStabilityManager,
DeviceProvisionedController deviceProvisionedController,
NavigationBarController navigationBarController,
@@ -238,7 +236,6 @@
statusBarStateController,
vibratorHelper,
bubbleController,
- groupManager,
visualStabilityManager,
deviceProvisionedController,
navigationBarController,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java
index 9b4e165..485b1b1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java
@@ -15,8 +15,6 @@
package com.android.systemui.statusbar.policy;
import android.app.ActivityManager;
-import android.content.ContentResolver;
-import android.content.Context;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Handler;
@@ -30,6 +28,8 @@
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.settings.CurrentUserTracker;
+import com.android.systemui.util.settings.GlobalSettings;
+import com.android.systemui.util.settings.SecureSettings;
import java.util.ArrayList;
@@ -43,8 +43,8 @@
protected static final String TAG = DeviceProvisionedControllerImpl.class.getSimpleName();
protected final ArrayList<DeviceProvisionedListener> mListeners = new ArrayList<>();
- private final ContentResolver mContentResolver;
- private final Context mContext;
+ private final GlobalSettings mGlobalSettings;
+ private final SecureSettings mSecureSettings;
private final Uri mDeviceProvisionedUri;
private final Uri mUserSetupUri;
protected final ContentObserver mSettingsObserver;
@@ -52,13 +52,14 @@
/**
*/
@Inject
- public DeviceProvisionedControllerImpl(Context context, @Main Handler mainHandler,
- BroadcastDispatcher broadcastDispatcher) {
+ public DeviceProvisionedControllerImpl(@Main Handler mainHandler,
+ BroadcastDispatcher broadcastDispatcher, GlobalSettings globalSettings,
+ SecureSettings secureSettings) {
super(broadcastDispatcher);
- mContext = context;
- mContentResolver = context.getContentResolver();
- mDeviceProvisionedUri = Global.getUriFor(Global.DEVICE_PROVISIONED);
- mUserSetupUri = Secure.getUriFor(Secure.USER_SETUP_COMPLETE);
+ mGlobalSettings = globalSettings;
+ mSecureSettings = secureSettings;
+ mDeviceProvisionedUri = mGlobalSettings.getUriFor(Global.DEVICE_PROVISIONED);
+ mUserSetupUri = mSecureSettings.getUriFor(Secure.USER_SETUP_COMPLETE);
mSettingsObserver = new ContentObserver(mainHandler) {
@Override
public void onChange(boolean selfChange, Uri uri, int flags) {
@@ -74,13 +75,12 @@
@Override
public boolean isDeviceProvisioned() {
- return Global.getInt(mContentResolver, Global.DEVICE_PROVISIONED, 0) != 0;
+ return mGlobalSettings.getInt(Global.DEVICE_PROVISIONED, 0) != 0;
}
@Override
public boolean isUserSetup(int currentUser) {
- return Secure.getIntForUser(mContentResolver, Secure.USER_SETUP_COMPLETE, 0, currentUser)
- != 0;
+ return mSecureSettings.getIntForUser(Secure.USER_SETUP_COMPLETE, 0, currentUser) != 0;
}
@Override
@@ -107,24 +107,24 @@
}
protected void startListening(int user) {
- mContentResolver.registerContentObserver(mDeviceProvisionedUri, true,
+ mGlobalSettings.registerContentObserverForUser(mDeviceProvisionedUri, true,
mSettingsObserver, 0);
- mContentResolver.registerContentObserver(mUserSetupUri, true,
+ mSecureSettings.registerContentObserverForUser(mUserSetupUri, true,
mSettingsObserver, user);
startTracking();
}
protected void stopListening() {
stopTracking();
- mContentResolver.unregisterContentObserver(mSettingsObserver);
+ mGlobalSettings.unregisterContentObserver(mSettingsObserver);
}
@Override
public void onUserSwitched(int newUserId) {
- mContentResolver.unregisterContentObserver(mSettingsObserver);
- mContentResolver.registerContentObserver(mDeviceProvisionedUri, true,
+ mGlobalSettings.unregisterContentObserver(mSettingsObserver);
+ mGlobalSettings.registerContentObserverForUser(mDeviceProvisionedUri, true,
mSettingsObserver, 0);
- mContentResolver.registerContentObserver(mUserSetupUri, true,
+ mSecureSettings.registerContentObserverForUser(mUserSetupUri, true,
mSettingsObserver, newUserId);
notifyUserChanged();
}
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 f9ac760..17fcb1d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -206,7 +206,7 @@
@Override
protected ArrayList<UserRecord> doInBackground(SparseArray<Bitmap>... params) {
final SparseArray<Bitmap> bitmaps = params[0];
- List<UserInfo> infos = mUserManager.getUsers(true);
+ List<UserInfo> infos = mUserManager.getAliveUsers();
if (infos == null) {
return null;
}
diff --git a/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java b/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java
index e7c10f1..d727bfb 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java
@@ -47,11 +47,11 @@
import com.android.systemui.statusbar.NotificationLockscreenUserManagerImpl;
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.phone.DozeServiceHost;
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.KeyguardEnvironmentImpl;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.NotificationShadeWindowControllerImpl;
import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.phone.ShadeControllerImpl;
@@ -136,7 +136,7 @@
Context context,
StatusBarStateController statusBarStateController,
KeyguardBypassController bypassController,
- NotificationGroupManager groupManager,
+ NotificationGroupManagerLegacy groupManager,
ConfigurationController configurationController) {
return new HeadsUpManagerPhone(context, statusBarStateController, bypassController,
groupManager, configurationController);
diff --git a/packages/SystemUI/src/com/android/systemui/util/concurrency/GlobalConcurrencyModule.java b/packages/SystemUI/src/com/android/systemui/util/concurrency/GlobalConcurrencyModule.java
new file mode 100644
index 0000000..5946af3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/util/concurrency/GlobalConcurrencyModule.java
@@ -0,0 +1,70 @@
+/*
+ * 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.util.concurrency;
+
+import android.content.Context;
+import android.os.Handler;
+import android.os.Looper;
+
+import com.android.systemui.dagger.qualifiers.Main;
+
+import java.util.concurrent.Executor;
+
+import dagger.Binds;
+import dagger.Module;
+import dagger.Provides;
+
+/**
+ * Dagger Module for classes found within the concurrent package.
+ */
+@Module
+public abstract class GlobalConcurrencyModule {
+
+ /**
+ * Binds {@link ThreadFactoryImpl} to {@link ThreadFactory}.
+ */
+ @Binds
+ public abstract ThreadFactory bindExecutorFactory(ThreadFactoryImpl impl);
+
+ /** Main Looper */
+ @Provides
+ @Main
+ public static Looper provideMainLooper() {
+ return Looper.getMainLooper();
+ }
+
+ /**
+ * Main Handler.
+ *
+ * Prefer the Main Executor when possible.
+ */
+ @Provides
+ @Main
+ public static Handler provideMainHandler(@Main Looper mainLooper) {
+ return new Handler(mainLooper);
+ }
+
+ /**
+ * Provide a Main-Thread Executor.
+ */
+ @Provides
+ @Main
+ public static Executor provideMainExecutor(Context context) {
+ return context.getMainExecutor();
+ }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/util/concurrency/ConcurrencyModule.java b/packages/SystemUI/src/com/android/systemui/util/concurrency/SysUIConcurrencyModule.java
similarity index 85%
rename from packages/SystemUI/src/com/android/systemui/util/concurrency/ConcurrencyModule.java
rename to packages/SystemUI/src/com/android/systemui/util/concurrency/SysUIConcurrencyModule.java
index 628c808..b9b20c7 100644
--- a/packages/SystemUI/src/com/android/systemui/util/concurrency/ConcurrencyModule.java
+++ b/packages/SystemUI/src/com/android/systemui/util/concurrency/SysUIConcurrencyModule.java
@@ -16,7 +16,6 @@
package com.android.systemui.util.concurrency;
-import android.content.Context;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
@@ -31,7 +30,6 @@
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
-import dagger.Binds;
import dagger.Module;
import dagger.Provides;
@@ -39,7 +37,7 @@
* Dagger Module for classes found within the concurrent package.
*/
@Module
-public abstract class ConcurrencyModule {
+public abstract class SysUIConcurrencyModule {
/** Background Looper */
@Provides
@SysUISingleton
@@ -62,13 +60,6 @@
return thread.getLooper();
}
- /** Main Looper */
- @Provides
- @Main
- public static Looper provideMainLooper() {
- return Looper.getMainLooper();
- }
-
/**
* Background Handler.
*
@@ -81,17 +72,6 @@
}
/**
- * Main Handler.
- *
- * Prefer the Main Executor when possible.
- */
- @Provides
- @Main
- public static Handler provideMainHandler(@Main Looper mainLooper) {
- return new Handler(mainLooper);
- }
-
- /**
* Provide a Background-Thread Executor by default.
*/
@Provides
@@ -121,15 +101,6 @@
}
/**
- * Provide a Main-Thread Executor.
- */
- @Provides
- @Main
- public static Executor provideMainExecutor(Context context) {
- return context.getMainExecutor();
- }
-
- /**
* Provide a Background-Thread Executor by default.
*/
@Provides
@@ -199,10 +170,4 @@
public static Executor provideUiBackgroundExecutor() {
return Executors.newSingleThreadExecutor();
}
-
- /**
- * Binds {@link ThreadFactoryImpl} to {@link ThreadFactory}.
- */
- @Binds
- public abstract ThreadFactory bindExecutorFactory(ThreadFactoryImpl impl);
}
diff --git a/packages/SystemUI/src/com/android/systemui/util/settings/SettingsProxy.java b/packages/SystemUI/src/com/android/systemui/util/settings/SettingsProxy.java
index 5c37f79..5aaf7f6 100644
--- a/packages/SystemUI/src/com/android/systemui/util/settings/SettingsProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/util/settings/SettingsProxy.java
@@ -67,7 +67,35 @@
* Implicitly calls {@link #getUriFor(String)} on the passed in name.
*/
default void registerContentObserver(String name, ContentObserver settingsObserver) {
- registerContentObserverForUser(name, settingsObserver, getUserId());
+ registerContentObserver(getUriFor(name), settingsObserver);
+ }
+
+ /**
+ * Convenience wrapper around
+ * {@link ContentResolver#registerContentObserver(Uri, boolean, ContentObserver)}.'
+ */
+ default void registerContentObserver(Uri uri, ContentObserver settingsObserver) {
+ registerContentObserverForUser(uri, settingsObserver, getUserId());
+ }
+
+ /**
+ * Convenience wrapper around
+ * {@link ContentResolver#registerContentObserver(Uri, boolean, ContentObserver)}.'
+ *
+ * Implicitly calls {@link #getUriFor(String)} on the passed in name.
+ */
+ default void registerContentObserver(String name, boolean notifyForDescendents,
+ ContentObserver settingsObserver) {
+ registerContentObserver(getUriFor(name), notifyForDescendents, settingsObserver);
+ }
+
+ /**
+ * Convenience wrapper around
+ * {@link ContentResolver#registerContentObserver(Uri, boolean, ContentObserver)}.'
+ */
+ default void registerContentObserver(Uri uri, boolean notifyForDescendents,
+ ContentObserver settingsObserver) {
+ registerContentObserverForUser(uri, notifyForDescendents, settingsObserver, getUserId());
}
/**
@@ -78,8 +106,42 @@
*/
default void registerContentObserverForUser(
String name, ContentObserver settingsObserver, int userHandle) {
+ registerContentObserverForUser(
+ getUriFor(name), settingsObserver, userHandle);
+ }
+
+ /**
+ * Convenience wrapper around
+ * {@link ContentResolver#registerContentObserver(Uri, boolean, ContentObserver, int)}
+ */
+ default void registerContentObserverForUser(
+ Uri uri, ContentObserver settingsObserver, int userHandle) {
+ registerContentObserverForUser(
+ uri, false, settingsObserver, userHandle);
+ }
+
+ /**
+ * Convenience wrapper around
+ * {@link ContentResolver#registerContentObserver(Uri, boolean, ContentObserver, int)}
+ *
+ * Implicitly calls {@link #getUriFor(String)} on the passed in name.
+ */
+ default void registerContentObserverForUser(
+ String name, boolean notifyForDescendents, ContentObserver settingsObserver,
+ int userHandle) {
+ registerContentObserverForUser(
+ getUriFor(name), notifyForDescendents, settingsObserver, userHandle);
+ }
+
+ /**
+ * Convenience wrapper around
+ * {@link ContentResolver#registerContentObserver(Uri, boolean, ContentObserver, int)}
+ */
+ default void registerContentObserverForUser(
+ Uri uri, boolean notifyForDescendents, ContentObserver settingsObserver,
+ int userHandle) {
getContentResolver().registerContentObserver(
- getUriFor(name), false, settingsObserver, userHandle);
+ uri, notifyForDescendents, settingsObserver, userHandle);
}
/** See {@link ContentResolver#unregisterContentObserver(ContentObserver)}. */
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index 51ad30e..78f83d3 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -49,6 +49,7 @@
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.PixelFormat;
+import android.graphics.Region;
import android.graphics.drawable.ColorDrawable;
import android.media.AudioManager;
import android.media.AudioSystem;
@@ -71,6 +72,7 @@
import android.view.ViewGroup;
import android.view.ViewPropertyAnimator;
import android.view.ViewStub;
+import android.view.ViewTreeObserver;
import android.view.Window;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityEvent;
@@ -109,7 +111,8 @@
* Methods ending in "H" must be called on the (ui) handler.
*/
public class VolumeDialogImpl implements VolumeDialog,
- ConfigurationController.ConfigurationListener {
+ ConfigurationController.ConfigurationListener,
+ ViewTreeObserver.OnComputeInternalInsetsListener {
private static final String TAG = Util.logTag(VolumeDialogImpl.class);
private static final long USER_ATTEMPT_GRACE_PERIOD = 1000;
@@ -126,6 +129,7 @@
private final H mHandler = new H();
private final VolumeDialogController mController;
private final DeviceProvisionedController mDeviceProvisionedController;
+ private final Region mTouchableRegion = new Region();
private Window mWindow;
private CustomDialog mDialog;
@@ -204,6 +208,33 @@
Dependency.get(ConfigurationController.class).removeCallback(this);
}
+ @Override
+ public void onComputeInternalInsets(ViewTreeObserver.InternalInsetsInfo internalInsetsInfo) {
+ // Set touchable region insets on the root dialog view. This tells WindowManager that
+ // touches outside of this region should not be delivered to the volume window, and instead
+ // go to the window below. This is the only way to do this - returning false in
+ // onDispatchTouchEvent results in the event being ignored entirely, rather than passed to
+ // the next window.
+ internalInsetsInfo.setTouchableInsets(
+ ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION);
+
+ mTouchableRegion.setEmpty();
+
+ // Set the touchable region to the union of all child view bounds. We don't use touches on
+ // the volume dialog container itself, so this is fine.
+ for (int i = 0; i < mDialogView.getChildCount(); i++) {
+ final View view = mDialogView.getChildAt(i);
+ mTouchableRegion.op(
+ view.getLeft(),
+ view.getTop(),
+ view.getRight(),
+ view.getBottom(),
+ Region.Op.UNION);
+ }
+
+ internalInsetsInfo.touchableRegion.set(mTouchableRegion);
+ }
+
private void initDialog() {
mDialog = new CustomDialog(mContext);
@@ -235,6 +266,7 @@
mDialogView.setAlpha(0);
mDialog.setCanceledOnTouchOutside(true);
mDialog.setOnShowListener(dialog -> {
+ mDialogView.getViewTreeObserver().addOnComputeInternalInsetsListener(this);
if (!isLandscape()) mDialogView.setTranslationX(mDialogView.getWidth() / 2.0f);
mDialogView.setAlpha(0);
mDialogView.animate()
@@ -253,6 +285,11 @@
.start();
});
+ mDialog.setOnDismissListener(dialogInterface ->
+ mDialogView
+ .getViewTreeObserver()
+ .removeOnComputeInternalInsetsListener(VolumeDialogImpl.this));
+
mDialogView.setOnHoverListener((v, event) -> {
int action = event.getActionMasked();
mHovering = (action == MotionEvent.ACTION_HOVER_ENTER)
@@ -1369,6 +1406,11 @@
super(context, R.style.volume_dialog_theme);
}
+ /**
+ * NOTE: This will only be called for touches within the touchable region of the volume
+ * dialog, as returned by {@link #onComputeInternalInsets}. Other touches, even if they are
+ * within the bounds of the volume dialog, will fall through to the window below.
+ */
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
rescheduleTimeoutH();
@@ -1387,6 +1429,12 @@
mHandler.sendEmptyMessage(H.RECHECK_ALL);
}
+ /**
+ * NOTE: This will be called with ACTION_OUTSIDE MotionEvents for touches that occur outside
+ * of the touchable region of the volume dialog (as returned by
+ * {@link #onComputeInternalInsets}) even if those touches occurred within the bounds of the
+ * volume dialog.
+ */
@Override
public boolean onTouchEvent(MotionEvent event) {
if (mShowing) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
index a7808ad..f65c2c9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
@@ -77,13 +77,13 @@
import com.android.systemui.statusbar.notification.NotificationFilter;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationTestHelper;
import com.android.systemui.statusbar.notification.row.dagger.NotificationShelfComponent;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.LockscreenLockIconController;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.NotificationShadeWindowControllerImpl;
import com.android.systemui.statusbar.phone.NotificationShadeWindowView;
import com.android.systemui.statusbar.phone.ShadeController;
@@ -118,7 +118,7 @@
@Mock
private NotificationEntryManager mNotificationEntryManager;
@Mock
- private NotificationGroupManager mNotificationGroupManager;
+ private NotificationGroupManagerLegacy mNotificationGroupManager;
@Mock
private WindowManager mWindowManager;
@Mock
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java
index 4936360..dd191e9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java
@@ -75,6 +75,7 @@
import com.android.systemui.statusbar.notification.NotificationFilter;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationTestHelper;
@@ -82,7 +83,6 @@
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.LockscreenLockIconController;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.NotificationShadeWindowControllerImpl;
import com.android.systemui.statusbar.phone.NotificationShadeWindowView;
import com.android.systemui.statusbar.phone.ShadeController;
@@ -116,7 +116,7 @@
@Mock
private NotificationEntryManager mNotificationEntryManager;
@Mock
- private NotificationGroupManager mNotificationGroupManager;
+ private NotificationGroupManagerLegacy mNotificationGroupManager;
@Mock
private BubbleController.NotifCallback mNotifCallback;
@Mock
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/TestableBubbleController.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/TestableBubbleController.java
index 51ca2a4..58b27f2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/TestableBubbleController.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/TestableBubbleController.java
@@ -30,8 +30,8 @@
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.ZenModeController;
@@ -52,7 +52,7 @@
NotificationInterruptStateProvider interruptionStateProvider,
ZenModeController zenModeController,
NotificationLockscreenUserManager lockscreenUserManager,
- NotificationGroupManager groupManager,
+ NotificationGroupManagerLegacy groupManager,
NotificationEntryManager entryManager,
NotifPipeline notifPipeline,
FeatureFlags featureFlags,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
index d2bf483..d041ee0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
@@ -45,6 +45,7 @@
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.inflation.LowPriorityInflationHelper;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
@@ -53,7 +54,6 @@
import com.android.systemui.statusbar.notification.stack.ForegroundServiceSectionController;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.google.android.collect.Lists;
@@ -76,7 +76,7 @@
// Dependency mocks:
@Mock private NotificationEntryManager mEntryManager;
@Mock private NotificationLockscreenUserManager mLockscreenUserManager;
- @Mock private NotificationGroupManager mGroupManager;
+ @Mock private NotificationGroupManagerLegacy mGroupManager;
@Mock private VisualStabilityManager mVisualStabilityManager;
private TestableLooper mTestableLooper;
@@ -95,7 +95,7 @@
mDependency.injectTestDependency(NotificationEntryManager.class, mEntryManager);
mDependency.injectTestDependency(NotificationLockscreenUserManager.class,
mLockscreenUserManager);
- mDependency.injectTestDependency(NotificationGroupManager.class, mGroupManager);
+ mDependency.injectTestDependency(NotificationGroupManagerLegacy.class, mGroupManager);
mDependency.injectTestDependency(VisualStabilityManager.class, mVisualStabilityManager);
when(mVisualStabilityManager.areGroupChangesAllowed()).thenReturn(true);
when(mVisualStabilityManager.isReorderingAllowed()).thenReturn(true);
@@ -136,11 +136,11 @@
Lists.newArrayList(entry0, entry1, entry2));
// Set up group manager to report that they should be bundled now.
- when(mGroupManager.isChildInGroupWithSummary(entry0.getSbn())).thenReturn(false);
- when(mGroupManager.isChildInGroupWithSummary(entry1.getSbn())).thenReturn(true);
- when(mGroupManager.isChildInGroupWithSummary(entry2.getSbn())).thenReturn(true);
- when(mGroupManager.getGroupSummary(entry1.getSbn())).thenReturn(entry0);
- when(mGroupManager.getGroupSummary(entry2.getSbn())).thenReturn(entry0);
+ when(mGroupManager.isChildInGroup(entry0)).thenReturn(false);
+ when(mGroupManager.isChildInGroup(entry1)).thenReturn(true);
+ when(mGroupManager.isChildInGroup(entry2)).thenReturn(true);
+ when(mGroupManager.getGroupSummary(entry1)).thenReturn(entry0);
+ when(mGroupManager.getGroupSummary(entry2)).thenReturn(entry0);
// Run updateNotifications - the view hierarchy should be reorganized.
mViewHierarchyManager.updateNotificationViews();
@@ -165,9 +165,9 @@
Lists.newArrayList(entry0, entry1, entry2));
// Set up group manager to report that they should not be bundled now.
- when(mGroupManager.isChildInGroupWithSummary(entry0.getSbn())).thenReturn(false);
- when(mGroupManager.isChildInGroupWithSummary(entry1.getSbn())).thenReturn(false);
- when(mGroupManager.isChildInGroupWithSummary(entry2.getSbn())).thenReturn(false);
+ when(mGroupManager.isChildInGroup(entry0)).thenReturn(false);
+ when(mGroupManager.isChildInGroup(entry1)).thenReturn(false);
+ when(mGroupManager.isChildInGroup(entry2)).thenReturn(false);
// Run updateNotifications - the view hierarchy should be reorganized.
mViewHierarchyManager.updateNotificationViews();
@@ -194,8 +194,8 @@
Lists.newArrayList(entry0, entry1));
// Set up group manager to report a suppressed summary now.
- when(mGroupManager.isChildInGroupWithSummary(entry0.getSbn())).thenReturn(false);
- when(mGroupManager.isChildInGroupWithSummary(entry1.getSbn())).thenReturn(false);
+ when(mGroupManager.isChildInGroup(entry0)).thenReturn(false);
+ when(mGroupManager.isChildInGroup(entry1)).thenReturn(false);
when(mGroupManager.isSummaryOfSuppressedGroup(entry0.getSbn())).thenReturn(true);
// Run updateNotifications - the view hierarchy should be reorganized.
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
index fc0201a..3e1616c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
@@ -75,13 +75,13 @@
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.collection.NotificationRankingManager;
import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinder;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats;
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationEntryManagerInflationTest;
import com.android.systemui.statusbar.notification.row.RowInflaterTask;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.util.leak.LeakDetector;
@@ -119,7 +119,7 @@
@Mock private NotificationRemoveInterceptor mRemoveInterceptor;
@Mock private HeadsUpManager mHeadsUpManager;
@Mock private RankingMap mRankingMap;
- @Mock private NotificationGroupManager mGroupManager;
+ @Mock private NotificationGroupManagerLegacy mGroupManager;
@Mock private NotificationRemoteInputManager mRemoteInputManager;
@Mock private DeviceProvisionedController mDeviceProvisionedController;
@Mock private RowInflaterTask mAsyncInflationTask;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationFilterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationFilterTest.java
index 5a81d36..dfe006d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationFilterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationFilterTest.java
@@ -48,10 +48,10 @@
import com.android.systemui.statusbar.notification.NotificationEntryManager.KeyguardEnvironment;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationTestHelper;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.ShadeController;
import org.junit.After;
@@ -109,8 +109,8 @@
eq(UID_ALLOW_DURING_SETUP)))
.thenReturn(PackageManager.PERMISSION_GRANTED);
mDependency.injectTestDependency(ForegroundServiceController.class, mFsc);
- mDependency.injectTestDependency(NotificationGroupManager.class,
- new NotificationGroupManager(
+ mDependency.injectTestDependency(NotificationGroupManagerLegacy.class,
+ new NotificationGroupManagerLegacy(
mock(StatusBarStateController.class),
() -> mock(PeopleNotificationIdentifier.class)));
mDependency.injectMockDependency(ShadeController.class);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/HighPriorityProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/HighPriorityProviderTest.java
index 386c866c..14877ee 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/HighPriorityProviderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/HighPriorityProviderTest.java
@@ -37,8 +37,8 @@
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.RankingBuilder;
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
+import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
import org.junit.Before;
import org.junit.Test;
@@ -48,12 +48,13 @@
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.List;
@SmallTest
@RunWith(AndroidTestingRunner.class)
public class HighPriorityProviderTest extends SysuiTestCase {
@Mock private PeopleNotificationIdentifier mPeopleNotificationIdentifier;
- @Mock private NotificationGroupManager mGroupManager;
+ @Mock private GroupMembershipManager mGroupMembershipManager;
private HighPriorityProvider mHighPriorityProvider;
@Before
@@ -61,7 +62,7 @@
MockitoAnnotations.initMocks(this);
mHighPriorityProvider = new HighPriorityProvider(
mPeopleNotificationIdentifier,
- mGroupManager);
+ mGroupMembershipManager);
}
@Test
@@ -71,7 +72,7 @@
.setImportance(IMPORTANCE_HIGH)
.build();
when(mPeopleNotificationIdentifier
- .getPeopleNotificationType(entry.getSbn(), entry.getRanking()))
+ .getPeopleNotificationType(entry))
.thenReturn(TYPE_NON_PERSON);
// THEN it has high priority
@@ -88,7 +89,7 @@
.setImportance(IMPORTANCE_LOW)
.build();
when(mPeopleNotificationIdentifier
- .getPeopleNotificationType(entry.getSbn(), entry.getRanking()))
+ .getPeopleNotificationType(entry))
.thenReturn(TYPE_PERSON);
// THEN it has high priority
@@ -105,7 +106,7 @@
.setNotification(notification)
.build();
when(mPeopleNotificationIdentifier
- .getPeopleNotificationType(entry.getSbn(), entry.getRanking()))
+ .getPeopleNotificationType(entry))
.thenReturn(TYPE_NON_PERSON);
// THEN it has high priority
@@ -123,7 +124,7 @@
.setImportance(IMPORTANCE_LOW)
.build();
when(mPeopleNotificationIdentifier
- .getPeopleNotificationType(entry.getSbn(), entry.getRanking()))
+ .getPeopleNotificationType(entry))
.thenReturn(TYPE_NON_PERSON);
// THEN it has high priority
@@ -141,7 +142,7 @@
.setImportance(IMPORTANCE_MIN)
.build();
when(mPeopleNotificationIdentifier
- .getPeopleNotificationType(entry.getSbn(), entry.getRanking()))
+ .getPeopleNotificationType(entry))
.thenReturn(TYPE_NON_PERSON);
// THEN it does NOT have high priority
@@ -165,7 +166,7 @@
.setChannel(channel)
.build();
when(mPeopleNotificationIdentifier
- .getPeopleNotificationType(entry.getSbn(), entry.getRanking()))
+ .getPeopleNotificationType(entry))
.thenReturn(TYPE_PERSON);
// THEN it does NOT have high priority
@@ -173,13 +174,13 @@
}
@Test
- public void testIsHighPriority_checkChildrenToCalculatePriority() {
+ public void testIsHighPriority_checkChildrenToCalculatePriority_legacy() {
// GIVEN: a summary with low priority has a highPriorityChild and a lowPriorityChild
final NotificationEntry summary = createNotifEntry(false);
final NotificationEntry lowPriorityChild = createNotifEntry(false);
final NotificationEntry highPriorityChild = createNotifEntry(true);
- when(mGroupManager.isGroupSummary(summary.getSbn())).thenReturn(true);
- when(mGroupManager.getChildren(summary.getSbn())).thenReturn(
+ when(mGroupMembershipManager.isGroupSummary(summary)).thenReturn(true);
+ when(mGroupMembershipManager.getChildren(summary)).thenReturn(
new ArrayList<>(Arrays.asList(lowPriorityChild, highPriorityChild)));
// THEN the summary is high priority since it has a high priority child
@@ -210,16 +211,20 @@
}
@Test
- public void testIsHighPriority_checkChildrenToCalculatePriorityOf() {
+ public void testIsHighPriority_checkChildrenToCalculatePriority() {
// GIVEN:
- // GroupEntry = parentEntry, summary = lowPrioritySummary
+ // parent with summary = lowPrioritySummary
// NotificationEntry = lowPriorityChild
// NotificationEntry = highPriorityChild
+ final NotificationEntry lowPrioritySummary = createNotifEntry(false);
final GroupEntry parentEntry = new GroupEntryBuilder()
- .setSummary(createNotifEntry(false))
- .addChild(createNotifEntry(false))
- .addChild(createNotifEntry(true))
+ .setSummary(lowPrioritySummary)
.build();
+ when(mGroupMembershipManager.getChildren(parentEntry)).thenReturn(
+ new ArrayList<>(
+ List.of(
+ createNotifEntry(false),
+ createNotifEntry(true))));
// THEN the GroupEntry parentEntry is high priority since it has a high priority child
assertTrue(mHighPriorityProvider.isHighPriority(parentEntry));
@@ -228,13 +233,15 @@
@Test
public void testIsHighPriority_childEntryRankingUpdated() {
// GIVEN:
- // GroupEntry = parentEntry, summary = lowPrioritySummary
+ // parent with summary = lowPrioritySummary
// NotificationEntry = lowPriorityChild
- final NotificationEntry lowPriorityChild = createNotifEntry(false);
+ final NotificationEntry lowPrioritySummary = createNotifEntry(false);
final GroupEntry parentEntry = new GroupEntryBuilder()
- .setSummary(createNotifEntry(false))
- .addChild(lowPriorityChild)
+ .setSummary(lowPrioritySummary)
.build();
+ final NotificationEntry lowPriorityChild = createNotifEntry(false);
+ when(mGroupMembershipManager.getChildren(parentEntry)).thenReturn(
+ new ArrayList<>(List.of(lowPriorityChild)));
// WHEN the child entry ranking changes to high priority
lowPriorityChild.setRanking(
@@ -243,9 +250,8 @@
.setImportance(IMPORTANCE_HIGH)
.build());
- // THEN the parent entry's high priority value is updated - but not the parent's summary
+ // THEN the parent entry's high priority value is updated
assertTrue(mHighPriorityProvider.isHighPriority(parentEntry));
- assertFalse(mHighPriorityProvider.isHighPriority(parentEntry.getSummary()));
}
private NotificationEntry createNotifEntry(boolean highPriority) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManagerTest.kt
index 82a7774..c832fe4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManagerTest.kt
@@ -40,7 +40,7 @@
import com.android.systemui.statusbar.notification.stack.BUCKET_ALERTING
import com.android.systemui.statusbar.notification.stack.BUCKET_FOREGROUND_SERVICE
import com.android.systemui.statusbar.notification.stack.BUCKET_SILENT
-import com.android.systemui.statusbar.phone.NotificationGroupManager
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy
import com.android.systemui.statusbar.policy.HeadsUpManager
import com.google.common.truth.Truth.assertThat
import dagger.Lazy
@@ -71,14 +71,14 @@
notificationFilter = mock(NotificationFilter::class.java)
rankingManager = TestableNotificationRankingManager(
lazyMedia,
- mock(NotificationGroupManager::class.java),
+ mock(NotificationGroupManagerLegacy::class.java),
mock(HeadsUpManager::class.java),
notificationFilter,
mock(NotificationEntryManagerLogger::class.java),
sectionsManager,
personNotificationIdentifier,
HighPriorityProvider(personNotificationIdentifier,
- mock(NotificationGroupManager::class.java))
+ mock(NotificationGroupManagerLegacy::class.java))
)
}
@@ -174,7 +174,7 @@
.setOverrideGroupKey("")
.build()
- whenever(personNotificationIdentifier.getPeopleNotificationType(a.sbn, a.ranking))
+ whenever(personNotificationIdentifier.getPeopleNotificationType(a))
.thenReturn(TYPE_IMPORTANT_PERSON)
val bN = Notification.Builder(mContext, "test")
@@ -194,7 +194,7 @@
whenever(it.isHeadsUp).thenReturn(true)
}
- whenever(personNotificationIdentifier.getPeopleNotificationType(a.sbn, a.ranking))
+ whenever(personNotificationIdentifier.getPeopleNotificationType(a))
.thenReturn(TYPE_PERSON)
assertEquals(listOf(b, a), rankingManager.updateRanking(null, listOf(a, b), "test"))
@@ -216,7 +216,7 @@
.setUser(mContext.user)
.setOverrideGroupKey("")
.build()
- whenever(personNotificationIdentifier.getPeopleNotificationType(a.sbn, a.ranking))
+ whenever(personNotificationIdentifier.getPeopleNotificationType(a))
.thenReturn(TYPE_PERSON)
val bN = Notification.Builder(mContext, "test")
@@ -232,7 +232,7 @@
.setUser(mContext.user)
.setOverrideGroupKey("")
.build()
- whenever(personNotificationIdentifier.getPeopleNotificationType(b.sbn, b.ranking))
+ whenever(personNotificationIdentifier.getPeopleNotificationType(b))
.thenReturn(TYPE_IMPORTANT_PERSON)
whenever(personNotificationIdentifier.compareTo(TYPE_PERSON, TYPE_IMPORTANT_PERSON))
@@ -261,7 +261,7 @@
.setUser(mContext.user)
.setOverrideGroupKey("")
.build()
- whenever(personNotificationIdentifier.getPeopleNotificationType(a.sbn, a.ranking))
+ whenever(personNotificationIdentifier.getPeopleNotificationType(a))
.thenReturn(TYPE_PERSON)
val bN = Notification.Builder(mContext, "test")
@@ -277,7 +277,7 @@
.setUser(mContext.user)
.setOverrideGroupKey("")
.build()
- whenever(personNotificationIdentifier.getPeopleNotificationType(b.sbn, b.ranking))
+ whenever(personNotificationIdentifier.getPeopleNotificationType(b))
.thenReturn(TYPE_FULL_PERSON)
whenever(personNotificationIdentifier.compareTo(TYPE_PERSON, TYPE_FULL_PERSON))
@@ -400,7 +400,7 @@
.setUser(mContext.user)
.setOverrideGroupKey("")
.build()
- whenever(personNotificationIdentifier.getPeopleNotificationType(a.sbn, a.ranking))
+ whenever(personNotificationIdentifier.getPeopleNotificationType(a))
.thenReturn(TYPE_IMPORTANT_PERSON)
assertThat(rankingManager.updateRanking(null, listOf(a, b, c), "test"))
@@ -410,7 +410,7 @@
internal class TestableNotificationRankingManager(
mediaManager: Lazy<NotificationMediaManager>,
- groupManager: NotificationGroupManager,
+ groupManager: NotificationGroupManagerLegacy,
headsUpManager: HeadsUpManager,
filter: NotificationFilter,
logger: NotificationEntryManagerLogger,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinatorTest.kt
index c49393d..09c9bcd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinatorTest.kt
@@ -84,8 +84,8 @@
@Test
fun testInPeopleSection() {
- whenever(peopleNotificationIdentifier.getPeopleNotificationType(
- entry.sbn, entry.ranking)).thenReturn(TYPE_PERSON)
+ whenever(peopleNotificationIdentifier.getPeopleNotificationType(entry))
+ .thenReturn(TYPE_PERSON)
// only put people notifications in this section
assertTrue(peopleSectioner.isInSection(entry))
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java
index 7a0a19b..aff8ade 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java
@@ -67,6 +67,7 @@
import com.android.systemui.statusbar.notification.collection.NotificationRankingManager;
import com.android.systemui.statusbar.notification.collection.inflation.LowPriorityInflationHelper;
import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
import com.android.systemui.statusbar.notification.icon.IconBuilder;
import com.android.systemui.statusbar.notification.icon.IconManager;
@@ -77,7 +78,6 @@
import com.android.systemui.statusbar.notification.row.dagger.NotificationRowComponent;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.SmartReplyConstants;
import com.android.systemui.util.concurrency.FakeExecutor;
@@ -130,7 +130,8 @@
@Mock private KeyguardBypassController mKeyguardBypassController;
@Mock private StatusBarStateController mStatusBarStateController;
- @Mock private NotificationGroupManager mGroupManager;
+ @Mock private NotificationGroupManagerLegacy mGroupMembershipManager;
+ @Mock private NotificationGroupManagerLegacy mGroupExpansionManager;
@Mock private FeatureFlags mFeatureFlags;
@Mock private LeakDetector mLeakDetector;
@@ -170,10 +171,10 @@
mEntryManager = new NotificationEntryManager(
mock(NotificationEntryManagerLogger.class),
- mGroupManager,
+ mGroupMembershipManager,
new NotificationRankingManager(
() -> mock(NotificationMediaManager.class),
- mGroupManager,
+ mGroupMembershipManager,
mHeadsUpManager,
mock(NotificationFilter.class),
mock(NotificationEntryManagerLogger.class),
@@ -228,7 +229,8 @@
new FakeSystemClock(),
"FOOBAR", "FOOBAR",
mKeyguardBypassController,
- mGroupManager,
+ mGroupMembershipManager,
+ mGroupExpansionManager,
mRowContentBindStage,
mock(NotificationLogger.class),
mHeadsUpManager,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
index df26c5b..b952c05 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
@@ -57,6 +57,7 @@
import com.android.systemui.statusbar.notification.ConversationNotificationProcessor;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
import com.android.systemui.statusbar.notification.icon.IconBuilder;
@@ -68,7 +69,6 @@
import com.android.systemui.statusbar.phone.ConfigurationControllerImpl;
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.policy.SmartReplyConstants;
import org.mockito.ArgumentCaptor;
@@ -96,7 +96,8 @@
private final Context mContext;
private final TestableLooper mTestLooper;
private int mId;
- private final NotificationGroupManager mGroupManager;
+ private final NotificationGroupManagerLegacy mGroupMembershipManager;
+ private final NotificationGroupManagerLegacy mGroupExpansionManager;
private ExpandableNotificationRow mRow;
private HeadsUpManagerPhone mHeadsUpManager;
private final NotifBindPipeline mBindPipeline;
@@ -116,13 +117,14 @@
dependency.injectMockDependency(BubbleController.class);
dependency.injectMockDependency(NotificationShadeWindowController.class);
mStatusBarStateController = mock(StatusBarStateController.class);
- mGroupManager = new NotificationGroupManager(
+ mGroupMembershipManager = new NotificationGroupManagerLegacy(
mStatusBarStateController,
() -> mock(PeopleNotificationIdentifier.class));
+ mGroupExpansionManager = mGroupMembershipManager;
mHeadsUpManager = new HeadsUpManagerPhone(mContext, mStatusBarStateController,
- mock(KeyguardBypassController.class), mock(NotificationGroupManager.class),
+ mock(KeyguardBypassController.class), mock(NotificationGroupManagerLegacy.class),
mock(ConfigurationControllerImpl.class));
- mGroupManager.setHeadsUpManager(mHeadsUpManager);
+ mGroupMembershipManager.setHeadsUpManager(mHeadsUpManager);
mIconManager = new IconManager(
mock(CommonNotifCollection.class),
mock(LauncherApps.class),
@@ -416,7 +418,8 @@
entry.getKey(),
mock(ExpansionLogger.class),
mock(KeyguardBypassController.class),
- mGroupManager,
+ mGroupMembershipManager,
+ mGroupExpansionManager,
mHeadsUpManager,
mBindStage,
mock(OnExpandClickListener.class),
@@ -434,7 +437,7 @@
// This would be done as part of onAsyncInflationFinished, but we skip large amounts of
// the callback chain, so we need to make up for not adding it to the group manager
// here.
- mGroupManager.onEntryAdded(entry);
+ mGroupMembershipManager.onEntryAdded(entry);
return row;
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
index 62b741c..5264458 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
@@ -47,9 +47,6 @@
import com.android.systemui.ExpandHelper;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.classifier.FalsingManagerFake;
-import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
-import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.EmptyShadeView;
import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.statusbar.NotificationMediaManager;
@@ -72,6 +69,7 @@
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.collection.NotificationRankingManager;
import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinder;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager;
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
@@ -80,8 +78,6 @@
import com.android.systemui.statusbar.notification.row.NotificationBlockingHelperManager;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.KeyguardBypassEnabledProvider;
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
-import com.android.systemui.statusbar.phone.NotificationIconAreaController;
import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.util.leak.LeakDetector;
@@ -115,7 +111,8 @@
@Mock private SysuiStatusBarStateController mBarState;
@Mock private HeadsUpManagerPhone mHeadsUpManager;
@Mock private NotificationBlockingHelperManager mBlockingHelperManager;
- @Mock private NotificationGroupManager mGroupManager;
+ @Mock private NotificationGroupManagerLegacy mGroupMembershipManger;
+ @Mock private NotificationGroupManagerLegacy mGroupExpansionManager;
@Mock private ExpandHelper mExpandHelper;
@Mock private EmptyShadeView mEmptyShadeView;
@Mock private NotificationRemoteInputManager mRemoteInputManager;
@@ -128,6 +125,7 @@
@Mock private FeatureFlags mFeatureFlags;
@Mock private SysuiStatusBarStateController mStatusBarStateController;
@Mock private NotificationSwipeHelper mNotificationSwipeHelper;
+ @Mock NotificationStackScrollLayoutController mStackScrollLayoutController;
private NotificationEntryManager mEntryManager;
private int mOriginalInterruptionModelSetting;
private UiEventLoggerFake mUiEventLoggerFake = new UiEventLoggerFake();
@@ -159,10 +157,10 @@
mEntryManager = new NotificationEntryManager(
mock(NotificationEntryManagerLogger.class),
- mock(NotificationGroupManager.class),
+ mock(NotificationGroupManagerLegacy.class),
new NotificationRankingManager(
() -> mock(NotificationMediaManager.class),
- mGroupManager,
+ mGroupMembershipManger,
mHeadsUpManager,
mock(NotificationFilter.class),
mock(NotificationEntryManagerLogger.class),
@@ -207,15 +205,19 @@
mock(NotifPipeline.class),
mEntryManager,
mock(NotifCollection.class),
- mUiEventLoggerFake
+ mUiEventLoggerFake,
+ mGroupMembershipManger,
+ mGroupExpansionManager
);
mStackScrollerInternal.initView(getContext(), mKeyguardBypassEnabledProvider,
mNotificationSwipeHelper);
mStackScroller = spy(mStackScrollerInternal);
mStackScroller.setShelfController(notificationShelfController);
mStackScroller.setStatusBar(mBar);
- mStackScroller.setGroupManager(mGroupManager);
mStackScroller.setEmptyShadeView(mEmptyShadeView);
+ when(mStackScrollLayoutController.getNoticationRoundessManager())
+ .thenReturn(mock(NotificationRoundnessManager.class));
+ mStackScroller.setController(mStackScrollLayoutController);
// Stub out functionality that isn't necessary to test.
doNothing().when(mBar)
@@ -224,7 +226,7 @@
anyBoolean(),
anyBoolean(),
anyBoolean());
- doNothing().when(mGroupManager).collapseAllGroups();
+ doNothing().when(mGroupExpansionManager).collapseGroups();
doNothing().when(mExpandHelper).cancelImmediately();
doNothing().when(notificationShelf).setAnimationsEnabled(anyBoolean());
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollerControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollerControllerTest.java
index f5d9fa0..32c6828 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollerControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollerControllerTest.java
@@ -16,6 +16,9 @@
package com.android.systemui.statusbar.notification.stack;
+import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
+import static com.android.systemui.statusbar.StatusBarState.SHADE;
+
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.argThat;
@@ -45,11 +48,11 @@
import com.android.systemui.statusbar.NotificationLockscreenUserManager.UserChangedListener;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
-import com.android.systemui.statusbar.phone.LockscreenGestureLogger;
import com.android.systemui.statusbar.phone.ScrimController;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -62,6 +65,7 @@
import org.mockito.Answers;
import org.mockito.ArgumentCaptor;
import org.mockito.ArgumentMatcher;
+import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -114,6 +118,11 @@
private StatusBar mStatusBar;
@Mock
private ScrimController mScrimController;
+ @Mock
+ private NotificationGroupManagerLegacy mLegacyGroupManager;
+
+ @Captor
+ ArgumentCaptor<StatusBarStateController.StateListener> mStateListenerArgumentCaptor;
private NotificationStackScrollLayoutController mController;
@@ -143,7 +152,9 @@
mResources,
mNotificationSwipeHelperBuilder,
mStatusBar,
- mScrimController
+ mScrimController,
+ mLegacyGroupManager,
+ mLegacyGroupManager
);
when(mNotificationStackScrollLayout.isAttachedToWindow()).thenReturn(true);
@@ -181,32 +192,49 @@
}
@Test
- public void testUpdateEmptyShadeView_notificationsVisible() {
+ public void testUpdateEmptyShadeView_notificationsVisible_zenHiding() {
when(mZenModeController.areNotificationsHiddenInShade()).thenReturn(true);
mController.attach(mNotificationStackScrollLayout);
+ verify(mSysuiStatusBarStateController).addCallback(
+ mStateListenerArgumentCaptor.capture(), anyInt());
+ StatusBarStateController.StateListener stateListener =
+ mStateListenerArgumentCaptor.getValue();
- mController.updateEmptyShadeView(true /* visible */);
+ setupShowEmptyShadeViewState(stateListener, true);
+ reset(mNotificationStackScrollLayout);
+ mController.updateShowEmptyShadeView();
verify(mNotificationStackScrollLayout).updateEmptyShadeView(
true /* visible */,
+
true /* notifVisibleInShade */);
+
+ setupShowEmptyShadeViewState(stateListener, false);
reset(mNotificationStackScrollLayout);
- mController.updateEmptyShadeView(false /* visible */);
+ mController.updateShowEmptyShadeView();
verify(mNotificationStackScrollLayout).updateEmptyShadeView(
false /* visible */,
true /* notifVisibleInShade */);
}
@Test
- public void testUpdateEmptyShadeView_notificationsHidden() {
+ public void testUpdateEmptyShadeView_notificationsHidden_zenNotHiding() {
when(mZenModeController.areNotificationsHiddenInShade()).thenReturn(false);
mController.attach(mNotificationStackScrollLayout);
+ verify(mSysuiStatusBarStateController).addCallback(
+ mStateListenerArgumentCaptor.capture(), anyInt());
+ StatusBarStateController.StateListener stateListener =
+ mStateListenerArgumentCaptor.getValue();
- mController.updateEmptyShadeView(true /* visible */);
+ setupShowEmptyShadeViewState(stateListener, true);
+ reset(mNotificationStackScrollLayout);
+ mController.updateShowEmptyShadeView();
verify(mNotificationStackScrollLayout).updateEmptyShadeView(
true /* visible */,
false /* notifVisibleInShade */);
+
+ setupShowEmptyShadeViewState(stateListener, false);
reset(mNotificationStackScrollLayout);
- mController.updateEmptyShadeView(false /* visible */);
+ mController.updateShowEmptyShadeView();
verify(mNotificationStackScrollLayout).updateEmptyShadeView(
false /* visible */,
false /* notifVisibleInShade */);
@@ -234,15 +262,12 @@
public void testOnStatePostChange_verifyIfProfileIsPublic() {
when(mNotificationLockscreenUserManager.isAnyProfilePublicMode()).thenReturn(true);
- ArgumentCaptor<StatusBarStateController.StateListener> stateListenerArgumentCaptor =
- ArgumentCaptor.forClass(StatusBarStateController.StateListener.class);
-
mController.attach(mNotificationStackScrollLayout);
verify(mSysuiStatusBarStateController).addCallback(
- stateListenerArgumentCaptor.capture(), anyInt());
+ mStateListenerArgumentCaptor.capture(), anyInt());
StatusBarStateController.StateListener stateListener =
- stateListenerArgumentCaptor.getValue();
+ mStateListenerArgumentCaptor.getValue();
stateListener.onStatePostChange();
verify(mNotificationStackScrollLayout).updateSensitiveness(false, true);
@@ -299,6 +324,20 @@
return argThat(new LogMatcher(category, type));
}
+ private void setupShowEmptyShadeViewState(
+ StatusBarStateController.StateListener statusBarStateListener,
+ boolean toShow) {
+ if (toShow) {
+ statusBarStateListener.onStateChanged(SHADE);
+ mController.setQsExpanded(false);
+ mController.getView().removeAllViews();
+ } else {
+ statusBarStateListener.onStateChanged(KEYGUARD);
+ mController.setQsExpanded(true);
+ mController.getView().addContainerView(mock(ExpandableNotificationRow.class));
+ }
+ }
+
static class LogMatcher implements ArgumentMatcher<LogMaker> {
private int mCategory, mType;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java
index 2239b1b..57020eb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java
@@ -36,6 +36,7 @@
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager;
import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -57,7 +58,7 @@
private HeadsUpManagerPhone mHeadsUpManager;
- @Mock private NotificationGroupManager mGroupManager;
+ @Mock private NotificationGroupManagerLegacy mGroupManager;
@Mock private View mNotificationShadeWindowView;
@Mock private VisualStabilityManager mVSManager;
@Mock private StatusBar mBar;
@@ -69,7 +70,7 @@
private final class TestableHeadsUpManagerPhone extends HeadsUpManagerPhone {
TestableHeadsUpManagerPhone(
Context context,
- NotificationGroupManager groupManager,
+ NotificationGroupManagerLegacy groupManager,
VisualStabilityManager vsManager,
StatusBarStateController statusBarStateController,
KeyguardBypassController keyguardBypassController,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelperTest.java
index 885dff3..2ece8be 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelperTest.java
@@ -42,6 +42,7 @@
import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
import com.android.systemui.statusbar.notification.row.NotifBindPipeline.BindCallback;
import com.android.systemui.statusbar.notification.row.RowContentBindParams;
@@ -68,7 +69,7 @@
@Rule public MockitoRule rule = MockitoJUnit.rule();
private NotificationGroupAlertTransferHelper mGroupAlertTransferHelper;
- private NotificationGroupManager mGroupManager;
+ private NotificationGroupManagerLegacy mGroupManager;
private HeadsUpManager mHeadsUpManager;
@Mock private NotificationEntryManager mNotificationEntryManager;
@Mock private RowContentBindStage mBindStage;
@@ -88,10 +89,10 @@
when(mNotificationEntryManager.getPendingNotificationsIterator())
.thenReturn(mPendingEntries.values());
- mGroupManager = new NotificationGroupManager(
+ mGroupManager = new NotificationGroupManagerLegacy(
mock(StatusBarStateController.class),
() -> mock(PeopleNotificationIdentifier.class));
- mDependency.injectTestDependency(NotificationGroupManager.class, mGroupManager);
+ mDependency.injectTestDependency(NotificationGroupManagerLegacy.class, mGroupManager);
mGroupManager.setHeadsUpManager(mHeadsUpManager);
when(mBindStage.getStageParams(any())).thenReturn(new RowContentBindParams());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupManagerLegacyTest.java
similarity index 87%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupManagerTest.java
rename to packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupManagerLegacyTest.java
index 5a6f74a..0aa0091 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupManagerLegacyTest.java
@@ -33,6 +33,7 @@
import com.android.systemui.bubbles.BubbleController;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
import com.android.systemui.statusbar.policy.HeadsUpManager;
@@ -47,11 +48,11 @@
@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
-public class NotificationGroupManagerTest extends SysuiTestCase {
+public class NotificationGroupManagerLegacyTest extends SysuiTestCase {
@Rule
public MockitoRule rule = MockitoJUnit.rule();
- private NotificationGroupManager mGroupManager;
+ private NotificationGroupManagerLegacy mGroupManager;
private final NotificationGroupTestHelper mGroupTestHelper =
new NotificationGroupTestHelper(mContext);
@@ -64,7 +65,7 @@
}
private void initializeGroupManager() {
- mGroupManager = new NotificationGroupManager(
+ mGroupManager = new NotificationGroupManagerLegacy(
mock(StatusBarStateController.class),
() -> mock(PeopleNotificationIdentifier.class));
mGroupManager.setHeadsUpManager(mHeadsUpManager);
@@ -78,7 +79,7 @@
mGroupManager.onEntryAdded(summaryEntry);
mGroupManager.onEntryAdded(childEntry);
- assertTrue(mGroupManager.isOnlyChildInGroup(childEntry.getSbn()));
+ assertTrue(mGroupManager.isOnlyChildInGroup(childEntry));
}
@Test
@@ -90,7 +91,7 @@
mGroupManager.onEntryAdded(childEntry);
mGroupManager.onEntryAdded(mGroupTestHelper.createChildNotification());
- assertTrue(mGroupManager.isChildInGroupWithSummary(childEntry.getSbn()));
+ assertTrue(mGroupManager.isChildInGroup(childEntry));
}
@Test
@@ -102,8 +103,8 @@
mGroupManager.onEntryAdded(childEntry);
mGroupManager.onEntryAdded(mGroupTestHelper.createChildNotification());
- assertTrue(mGroupManager.isSummaryOfGroup(summaryEntry.getSbn()));
- assertEquals(summaryEntry, mGroupManager.getGroupSummary(childEntry.getSbn()));
+ assertTrue(mGroupManager.isGroupSummary(summaryEntry));
+ assertEquals(summaryEntry, mGroupManager.getGroupSummary(childEntry));
}
@Test
@@ -116,7 +117,7 @@
mGroupManager.onEntryRemoved(childEntry);
- assertFalse(mGroupManager.isChildInGroupWithSummary(childEntry.getSbn()));
+ assertFalse(mGroupManager.isChildInGroup(childEntry));
}
@Test
@@ -129,8 +130,8 @@
mGroupManager.onEntryRemoved(summaryEntry);
- assertNull(mGroupManager.getGroupSummary(childEntry.getSbn()));
- assertFalse(mGroupManager.isSummaryOfGroup(summaryEntry.getSbn()));
+ assertNull(mGroupManager.getGroupSummary(childEntry));
+ assertFalse(mGroupManager.isGroupSummary(summaryEntry));
}
@Test
@@ -146,7 +147,7 @@
// Child entries that are heads upped should be considered separate groups visually even if
// they are the same group logically
- assertEquals(childEntry, mGroupManager.getGroupSummary(childEntry.getSbn()));
- assertEquals(summaryEntry, mGroupManager.getLogicalGroupSummary(childEntry.getSbn()));
+ assertEquals(childEntry, mGroupManager.getGroupSummary(childEntry));
+ assertEquals(summaryEntry, mGroupManager.getLogicalGroupSummary(childEntry));
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
index 453baa5..cf64ff2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
@@ -74,12 +74,12 @@
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.stack.NotificationRoundnessManager;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
-import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.util.InjectionInflationController;
import org.junit.Before;
@@ -118,7 +118,7 @@
@Mock
private NotificationShelfController mNotificationShelfController;
@Mock
- private NotificationGroupManager mGroupManager;
+ private NotificationGroupManagerLegacy mGroupManager;
@Mock
private KeyguardStatusBarView mKeyguardStatusBar;
@Mock
@@ -174,8 +174,6 @@
private KeyguardClockSwitch mKeyguardClockSwitch;
private PanelViewController.TouchHandler mTouchHandler;
@Mock
- private ZenModeController mZenModeController;
- @Mock
private ConfigurationController mConfigurationController;
@Mock
private MediaHierarchyManager mMediaHiearchyManager;
@@ -259,16 +257,16 @@
mKeyguardStateController, mStatusBarStateController, mDozeLog,
mDozeParameters, mCommandQueue, mVibratorHelper,
mLatencyTracker, mPowerManager, mAccessibilityManager, 0, mUpdateMonitor,
- mMetricsLogger, mActivityManager, mZenModeController, mConfigurationController,
+ mMetricsLogger, mActivityManager, mConfigurationController,
flingAnimationUtilsBuilder, mStatusBarTouchableRegionManager,
mConversationNotificationManager, mMediaHiearchyManager,
mBiometricUnlockController, mStatusBarKeyguardViewManager,
mNotificationStackScrollLayoutController,
- mNotificationAreaController,
- mKeyguardStatusViewComponentFactory);
+ mKeyguardStatusViewComponentFactory,
+ mGroupManager,
+ mNotificationAreaController);
mNotificationPanelViewController.initDependencies(
mStatusBar,
- mGroupManager,
mNotificationShelfController);
mNotificationPanelViewController.setHeadsUpManager(mHeadsUpManager);
mNotificationPanelViewController.setBar(mPanelBar);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
index 2f45113..1083273 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.phone;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.ArgumentMatchers.eq;
@@ -27,7 +28,6 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import android.content.Context;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.view.View;
@@ -39,14 +39,13 @@
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.ViewMediatorCallback;
+import com.android.keyguard.dagger.KeyguardBouncerComponent;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.dock.DockManager;
import com.android.systemui.keyguard.DismissCallbackRegistry;
import com.android.systemui.keyguard.FaceAuthScreenBrightnessController;
import com.android.systemui.navigationbar.NavigationModeController;
import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
-import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
@@ -71,8 +70,6 @@
@Mock
private LockPatternUtils mLockPatternUtils;
@Mock
- private KeyguardBouncer mBouncer;
- @Mock
private KeyguardStateController mKeyguardStateController;
@Mock
private StatusBar mStatusBar;
@@ -94,6 +91,13 @@
private KeyguardBypassController mBypassController;
@Mock
private FaceAuthScreenBrightnessController mFaceAuthScreenBrightnessController;
+ @Mock
+ private KeyguardBouncerComponent.Factory mKeyguardBouncerComponentFactory;
+ @Mock
+ private KeyguardBouncerComponent mKeyguardBouncerComponent;
+ @Mock
+ private KeyguardBouncer mBouncer;
+
private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
@Before
@@ -102,7 +106,14 @@
when(mLockIconContainer.getParent()).thenReturn(mock(ViewGroup.class));
when(mLockIconContainer.animate()).thenReturn(mock(ViewPropertyAnimator.class,
RETURNS_DEEP_STUBS));
- mStatusBarKeyguardViewManager = new TestableStatusBarKeyguardViewManager(
+
+ when(mKeyguardBouncerComponentFactory.build(
+ any(ViewGroup.class),
+ any(KeyguardBouncer.BouncerExpansionCallback.class)))
+ .thenReturn(mKeyguardBouncerComponent);
+ when(mKeyguardBouncerComponent.createKeyguardBouncer()).thenReturn(mBouncer);
+
+ mStatusBarKeyguardViewManager = new StatusBarKeyguardViewManager(
getContext(),
mViewMediatorCallback,
mLockPatternUtils,
@@ -113,12 +124,12 @@
mock(DockManager.class),
mock(NotificationShadeWindowController.class),
mKeyguardStateController,
- mFaceAuthScreenBrightnessController,
- mock(NotificationMediaManager.class));
+ Optional.of(mFaceAuthScreenBrightnessController),
+ mock(NotificationMediaManager.class),
+ mKeyguardBouncerComponentFactory);
mStatusBarKeyguardViewManager.registerStatusBar(mStatusBar, mContainer,
- mNotificationPanelView, mBiometrucUnlockController, mDismissCallbackRegistry,
- mLockIconContainer, mNotificationContainer, mBypassController,
- new FalsingManagerFake());
+ mNotificationPanelView, mBiometrucUnlockController,
+ mLockIconContainer, mNotificationContainer, mBypassController);
mStatusBarKeyguardViewManager.show(null);
}
@@ -267,38 +278,4 @@
verify(action).onDismiss();
verify(cancelAction, never()).run();
}
-
- private class TestableStatusBarKeyguardViewManager extends StatusBarKeyguardViewManager {
-
- public TestableStatusBarKeyguardViewManager(Context context,
- ViewMediatorCallback callback,
- LockPatternUtils lockPatternUtils,
- SysuiStatusBarStateController sysuiStatusBarStateController,
- ConfigurationController configurationController,
- KeyguardUpdateMonitor keyguardUpdateMonitor,
- NavigationModeController navigationModeController,
- DockManager dockManager,
- NotificationShadeWindowController notificationShadeWindowController,
- KeyguardStateController keyguardStateController,
- FaceAuthScreenBrightnessController faceAuthScreenBrightnessController,
- NotificationMediaManager notificationMediaManager) {
- super(context, callback, lockPatternUtils, sysuiStatusBarStateController,
- configurationController, keyguardUpdateMonitor, navigationModeController,
- dockManager, notificationShadeWindowController, keyguardStateController,
- Optional.of(faceAuthScreenBrightnessController), notificationMediaManager);
- }
-
- @Override
- public void registerStatusBar(StatusBar statusBar, ViewGroup container,
- NotificationPanelViewController notificationPanelViewController,
- BiometricUnlockController fingerprintUnlockController,
- DismissCallbackRegistry dismissCallbackRegistry,
- ViewGroup lockIconContainer, View notificationContainer,
- KeyguardBypassController bypassController, FalsingManager falsingManager) {
- super.registerStatusBar(statusBar, container, notificationPanelViewController,
- fingerprintUnlockController, dismissCallbackRegistry, lockIconContainer,
- notificationContainer, bypassController, falsingManager);
- mBouncer = StatusBarKeyguardViewManagerTest.this.mBouncer;
- }
- }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
index 3f631b1..792637d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
@@ -67,9 +67,9 @@
import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
import com.android.systemui.statusbar.notification.NotificationActivityStarter;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
-import com.android.systemui.statusbar.notification.collection.NotifCollection;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationTestHelper;
@@ -122,8 +122,6 @@
private FeatureFlags mFeatureFlags;
@Mock
private NotifPipeline mNotifPipeline;
- @Mock
- private NotifCollection mNotifCollection;
@Mock
private ActivityIntentHelper mActivityIntentHelper;
@@ -187,7 +185,6 @@
mUiBgExecutor,
mEntryManager,
mNotifPipeline,
- mNotifCollection,
mock(HeadsUpManagerPhone.class),
mActivityStarter,
mClickNotifier,
@@ -198,7 +195,7 @@
mBubbleController,
() -> mAssistManager,
mRemoteInputManager,
- mock(NotificationGroupManager.class),
+ mock(NotificationGroupManagerLegacy.class),
mock(NotificationLockscreenUserManager.class),
mShadeController,
mKeyguardStateController,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallbackTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallbackTest.java
index bf2bd38..6fbbee2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallbackTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallbackTest.java
@@ -36,6 +36,7 @@
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -72,7 +73,7 @@
mNotificationLockscreenUserManager);
mRemoteInputCallback = spy(new StatusBarRemoteInputCallback(mContext,
- mock(NotificationGroupManager.class), mNotificationLockscreenUserManager,
+ mock(NotificationGroupManagerLegacy.class), mNotificationLockscreenUserManager,
mKeyguardStateController, mStatusBarStateController, mStatusBarKeyguardViewManager,
mActivityStarter, mShadeController, new CommandQueue(mContext),
mock(ActionClickLogger.class)));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index 87aee3f..5143596 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -220,7 +220,6 @@
@Mock private NetworkController mNetworkController;
@Mock private VibratorHelper mVibratorHelper;
@Mock private BubbleController mBubbleController;
- @Mock private NotificationGroupManager mGroupManager;
@Mock private NotificationShadeWindowController mNotificationShadeWindowController;
@Mock private NotificationIconAreaController mNotificationIconAreaController;
@Mock private NotificationShadeWindowViewController mNotificationShadeWindowViewController;
@@ -376,7 +375,6 @@
mStatusBarStateController,
mVibratorHelper,
mBubbleController,
- mGroupManager,
mVisualStabilityManager,
mDeviceProvisionedController,
mNavigationBarController,
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/MultiFingerSwipe.java b/services/accessibility/java/com/android/server/accessibility/gestures/MultiFingerSwipe.java
index 07e8211..5b46cb4 100644
--- a/services/accessibility/java/com/android/server/accessibility/gestures/MultiFingerSwipe.java
+++ b/services/accessibility/java/com/android/server/accessibility/gestures/MultiFingerSwipe.java
@@ -294,7 +294,7 @@
+ Float.toString(mGestureDetectionThresholdPixels));
}
if (getState() == STATE_CLEAR) {
- if (moveDelta < mTouchSlop) {
+ if (moveDelta < (mTargetFingerCount * mTouchSlop)) {
// This still counts as a touch not a swipe.
continue;
} else if (mStrokeBuffers[pointerIndex].size() == 0) {
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
index e9c6882..8305be3 100644
--- a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
+++ b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
@@ -608,7 +608,7 @@
mReceivedPointerTracker.getReceivedPointerDownY(id)
- rawEvent.getY(index);
final double moveDelta = Math.hypot(deltaX, deltaY);
- if (moveDelta < mTouchSlop) {
+ if (moveDelta < (2 * mTouchSlop)) {
return;
}
}
diff --git a/services/companion/TEST_MAPPING b/services/companion/TEST_MAPPING
new file mode 100644
index 0000000..63f54fa
--- /dev/null
+++ b/services/companion/TEST_MAPPING
@@ -0,0 +1,12 @@
+{
+ "presubmit": [
+ {
+ "name": "CtsOsTestCases",
+ "options": [
+ {
+ "include-filter": "android.os.cts.CompanionDeviceManagerTest"
+ }
+ ]
+ }
+ ]
+}
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 35e88eb..7d81d41 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -2114,7 +2114,7 @@
* Owner or system user account was renamed, rename the account for
* those users with which the account was shared.
*/
- List<UserInfo> users = getUserManager().getUsers(true);
+ List<UserInfo> users = getUserManager().getAliveUsers();
for (UserInfo user : users) {
if (user.isRestricted()
&& (user.restrictedProfileParentId == parentUserId)) {
@@ -2373,7 +2373,7 @@
int parentUserId = accounts.userId;
if (canHaveProfile(parentUserId)) {
// Remove from any restricted profiles that are sharing this account.
- List<UserInfo> users = getUserManager().getUsers(true);
+ List<UserInfo> users = getUserManager().getAliveUsers();
for (UserInfo user : users) {
if (user.isRestricted() && parentUserId == (user.restrictedProfileParentId)) {
removeSharedAccountAsUser(account, user.id, callingUid);
@@ -4267,7 +4267,7 @@
*/
@NonNull
public AccountAndUser[] getAllAccounts() {
- final List<UserInfo> users = getUserManager().getUsers(true);
+ final List<UserInfo> users = getUserManager().getAliveUsers();
final int[] userIds = new int[users.size()];
for (int i = 0; i < userIds.length; i++) {
userIds[i] = users.get(i).id;
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 2d803437..1502b7e 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -17144,8 +17144,7 @@
@Override
public int checkContentProviderUriPermission(Uri uri, int userId,
int callingUid, int modeFlags) {
- return mCpHelper.checkContentProviderUriPermission(uri,
- userId, callingUid, modeFlags);
+ return mCpHelper.checkContentProviderUriPermission(uri, userId, callingUid, modeFlags);
}
@Override
diff --git a/services/core/java/com/android/server/am/ContentProviderHelper.java b/services/core/java/com/android/server/am/ContentProviderHelper.java
index bfba4af..05a731d 100644
--- a/services/core/java/com/android/server/am/ContentProviderHelper.java
+++ b/services/core/java/com/android/server/am/ContentProviderHelper.java
@@ -198,22 +198,10 @@
if (providerRunning) {
cpi = cpr.info;
- String msg;
if (r != null && cpr.canRunHere(r)) {
- if ((msg = checkContentProviderAssociation(r, callingUid, cpi)) != null) {
- throw new SecurityException("Content provider lookup "
- + cpr.name.flattenToShortString()
- + " failed: association not allowed with package " + msg);
- }
- checkTime(startTime,
- "getContentProviderImpl: before checkContentProviderPermission");
- if ((msg = checkContentProviderPermissionLocked(cpi, r, userId, checkCrossUser))
- != null) {
- throw new SecurityException(msg);
- }
- checkTime(startTime,
- "getContentProviderImpl: after checkContentProviderPermission");
+ checkAssociationAndPermissionLocked(r, cpi, callingUid, userId, checkCrossUser,
+ cpr.name.flattenToShortString(), startTime);
// This provider has been published or is in the process
// of being published... but it is also allowed to run
@@ -234,26 +222,14 @@
} catch (RemoteException e) {
}
- if ((msg = checkContentProviderAssociation(r, callingUid, cpi)) != null) {
- throw new SecurityException(
- "Content provider lookup " + cpr.name.flattenToShortString()
- + " failed: association not allowed with package " + msg);
- }
- checkTime(startTime,
- "getContentProviderImpl: before checkContentProviderPermission");
- if ((msg = checkContentProviderPermissionLocked(cpi, r, userId, checkCrossUser))
- != null) {
- throw new SecurityException(msg);
- }
- checkTime(startTime,
- "getContentProviderImpl: after checkContentProviderPermission");
+ checkAssociationAndPermissionLocked(r, cpi, callingUid, userId, checkCrossUser,
+ cpr.name.flattenToShortString(), startTime);
final long origId = Binder.clearCallingIdentity();
checkTime(startTime, "getContentProviderImpl: incProviderCountLocked");
- // In this case the provider instance already exists, so we can
- // return it right away.
+ // In this case the provider instance already exists so we can return it right away.
conn = incProviderCountLocked(r, cpr, token, callingUid, callingPackage, callingTag,
stable, true, startTime, mService.mProcessList);
@@ -328,19 +304,8 @@
cpi.applicationInfo = mService.getAppInfoForUser(cpi.applicationInfo, userId);
checkTime(startTime, "getContentProviderImpl: got app info for user");
- String msg;
- if ((msg = checkContentProviderAssociation(r, callingUid, cpi)) != null) {
- throw new SecurityException("Content provider lookup " + name
- + " failed: association not allowed with package " + msg);
- }
- checkTime(startTime,
- "getContentProviderImpl: before checkContentProviderPermission");
- if ((msg = checkContentProviderPermissionLocked(cpi, r, userId, !singleton))
- != null) {
- throw new SecurityException(msg);
- }
- checkTime(startTime,
- "getContentProviderImpl: after checkContentProviderPermission");
+ checkAssociationAndPermissionLocked(r, cpi, callingUid, userId, !singleton,
+ name, startTime);
if (!mService.mProcessesReady && !cpi.processName.equals("system")) {
// If this content provider does not run in the system
@@ -352,10 +317,12 @@
// If system providers are not installed yet we aggressively crash to avoid
// creating multiple instance of these providers and then bad things happen!
- if (!mSystemProvidersInstalled && cpi.applicationInfo.isSystemApp()
- && "system".equals(cpi.processName)) {
- throw new IllegalStateException("Cannot access system provider: '"
- + cpi.authority + "' before system providers are installed!");
+ synchronized (this) {
+ if (!mSystemProvidersInstalled && cpi.applicationInfo.isSystemApp()
+ && "system".equals(cpi.processName)) {
+ throw new IllegalStateException("Cannot access system provider: '"
+ + cpi.authority + "' before system providers are installed!");
+ }
}
// Make sure that the user who owns this provider is running. If not,
@@ -605,6 +572,23 @@
return cpr.newHolder(conn, false);
}
+ private void checkAssociationAndPermissionLocked(ProcessRecord callingApp, ProviderInfo cpi,
+ int callingUid, int userId, boolean checkUser, String cprName, long startTime) {
+ String msg;
+ if ((msg = checkContentProviderAssociation(callingApp, callingUid, cpi)) != null) {
+ throw new SecurityException("Content provider lookup " + cprName
+ + " failed: association not allowed with package " + msg);
+ }
+ checkTime(startTime, "getContentProviderImpl: before checkContentProviderPermission");
+ if ((msg = checkContentProviderPermission(
+ cpi, Binder.getCallingPid(), Binder.getCallingUid(), userId, checkUser,
+ callingApp != null ? callingApp.toString() : null))
+ != null) {
+ throw new SecurityException(msg);
+ }
+ checkTime(startTime, "getContentProviderImpl: after checkContentProviderPermission");
+ }
+
void publishContentProviders(IApplicationThread caller, List<ContentProviderHolder> providers) {
if (providers == null) {
return;
@@ -623,7 +607,7 @@
}
final long origId = Binder.clearCallingIdentity();
-
+ boolean providersPublished = false;
for (int i = 0, size = providers.size(); i < size; i++) {
ContentProviderHolder src = providers.get(i);
if (src == null || src.info == null || src.provider == null) {
@@ -636,6 +620,7 @@
if (DEBUG_MU) {
Slog.v(TAG_MU, "ContentProviderRecord uid = " + dst.uid);
}
+ providersPublished = true;
ComponentName comp = new ComponentName(dst.info.packageName, dst.info.name);
mProviderMap.putProviderByClass(comp, dst);
@@ -673,8 +658,19 @@
dst.onProviderPublishStatusLocked(true);
}
dst.mRestartCount = 0;
+ }
+
+ // update the app's oom adj value and each provider's usage stats
+ if (providersPublished) {
mService.updateOomAdjLocked(r, true, OomAdjuster.OOM_ADJ_REASON_GET_PROVIDER);
- maybeUpdateProviderUsageStatsLocked(r, src.info.packageName, src.info.authority);
+ for (int i = 0, size = providers.size(); i < size; i++) {
+ ContentProviderHolder src = providers.get(i);
+ if (src == null || src.info == null || src.provider == null) {
+ continue;
+ }
+ maybeUpdateProviderUsageStatsLocked(r,
+ src.info.packageName, src.info.authority);
+ }
}
Binder.restoreCallingIdentity(origId);
@@ -997,17 +993,19 @@
+ "; expected to find a valid ContentProvider for this authority";
}
+ final int callingPid = Binder.getCallingPid();
ProcessRecord r;
+ final String appName;
synchronized (mService.mPidsSelfLocked) {
- r = mService.mPidsSelfLocked.get(Binder.getCallingPid());
- }
- if (r == null) {
- return "Failed to find PID " + Binder.getCallingPid();
+ r = mService.mPidsSelfLocked.get(callingPid);
+ if (r == null) {
+ return "Failed to find PID " + callingPid;
+ }
+ appName = r.toString();
}
- synchronized (mService) {
- return checkContentProviderPermissionLocked(cpi, r, userId, true);
- }
+ return checkContentProviderPermission(cpi, callingPid, Binder.getCallingUid(),
+ userId, true, appName);
}
int checkContentProviderUriPermission(Uri uri, int userId, int callingUid, int modeFlags) {
@@ -1163,13 +1161,14 @@
}
}
}
- if (providers != null) {
- mService.mSystemThread.installSystemProviders(providers);
- }
- synchronized (mService) {
+ synchronized (this) {
+ if (providers != null) {
+ mService.mSystemThread.installSystemProviders(providers);
+ }
mSystemProvidersInstalled = true;
}
+
mService.mConstants.start(mService.mContext.getContentResolver());
mService.mCoreSettingsObserver = new CoreSettingsObserver(mService);
mService.mActivityTaskManager.installSystemProviders();
@@ -1305,10 +1304,8 @@
* given {@link ProviderInfo}. Final permission checking is always done
* in {@link ContentProvider}.
*/
- private String checkContentProviderPermissionLocked(ProviderInfo cpi, ProcessRecord r,
- int userId, boolean checkUser) {
- final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
- final int callingUid = (r != null) ? r.uid : Binder.getCallingUid();
+ private String checkContentProviderPermission(ProviderInfo cpi, int callingPid, int callingUid,
+ int userId, boolean checkUser, String appName) {
boolean checkedGrants = false;
if (checkUser) {
// Looking for cross-user grants before enforcing the typical cross-users permissions
@@ -1376,8 +1373,8 @@
suffix = " requires " + cpi.readPermission + " or " + cpi.writePermission;
}
final String msg = "Permission Denial: opening provider " + cpi.name
- + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
- + ", uid=" + callingUid + ")" + suffix;
+ + " from " + (appName != null ? appName : "(null)")
+ + " (pid=" + callingPid + ", uid=" + callingUid + ")" + suffix;
Slog.w(TAG, msg);
return msg;
}
@@ -1398,18 +1395,17 @@
}
ProviderInfo getProviderInfoLocked(String authority, @UserIdInt int userId, int pmFlags) {
- ProviderInfo pi = null;
ContentProviderRecord cpr = mProviderMap.getProviderByName(authority, userId);
if (cpr != null) {
- pi = cpr.info;
+ return cpr.info;
} else {
try {
- pi = AppGlobals.getPackageManager().resolveContentProvider(
+ return AppGlobals.getPackageManager().resolveContentProvider(
authority, PackageManager.GET_URI_PERMISSION_PATTERNS | pmFlags, userId);
} catch (RemoteException ex) {
+ return null;
}
}
- return pi;
}
private void maybeUpdateProviderUsageStatsLocked(ProcessRecord app, String providerPkgName,
@@ -1419,7 +1415,6 @@
return;
}
-
UserState userState = mService.mUserController.getStartedUserState(app.userId);
if (userState == null) return;
final long now = SystemClock.elapsedRealtime();
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index d59780d..3f29eb5 100755
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -6528,8 +6528,8 @@
CHECK_MODE_FOR_UID_PERIOD_MS);
break;
}
- // For now just log the fact that an app is hogging the audio mode.
- // TODO(b/160260850): remove abusive app from audio mode stack.
+ setModeInt(AudioSystem.MODE_NORMAL, h.getBinder(), h.getPid(), h.getUid(),
+ h.isPrivileged(), "MSG_CHECK_MODE_FOR_UID");
mModeLogger.log(new PhoneStateEvent(h.getPackage(), h.getPid()));
}
break;
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/Face10.java b/services/core/java/com/android/server/biometrics/sensors/face/Face10.java
index 32bb2db..d9c62df 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/Face10.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/Face10.java
@@ -29,7 +29,6 @@
import android.hardware.biometrics.face.V1_0.IBiometricsFace;
import android.hardware.biometrics.face.V1_0.IBiometricsFaceClientCallback;
import android.hardware.face.Face;
-import android.hardware.face.FaceManager;
import android.hardware.face.FaceSensorProperties;
import android.hardware.face.IFaceServiceReceiver;
import android.os.Build;
@@ -383,7 +382,7 @@
// is safe because authenticatorIds only change when A) new template has been enrolled,
// or B) all templates are removed.
mHandler.post(() -> {
- for (UserInfo user : UserManager.get(mContext).getUsers(true /* excludeDying */)) {
+ for (UserInfo user : UserManager.get(mContext).getAliveUsers()) {
final int targetUserId = user.id;
if (!mAuthenticatorIds.containsKey(targetUserId)) {
scheduleUpdateActiveUserWithoutHandler(targetUserId);
@@ -480,7 +479,8 @@
* notifying the previous caller that the interrupting operation is complete (e.g. the
* interrupting client's challenge has been revoked, so that the interrupted client can
* start retry logic if necessary). See
- * {@link FaceManager.GenerateChallengeCallback#onChallengeInterruptFinished(int)}
+ * {@link
+ *android.hardware.face.FaceManager.GenerateChallengeCallback#onChallengeInterruptFinished(int)}
* The only case of conflicting challenges is currently resetLockout --> enroll. So, the second
* option seems better as it prioritizes the new operation, which is user-facing.
*/
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/Fingerprint21.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/Fingerprint21.java
index c5c2822..3754bd7 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/Fingerprint21.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/Fingerprint21.java
@@ -440,7 +440,7 @@
// is safe because authenticatorIds only change when A) new template has been enrolled,
// or B) all templates are removed.
mHandler.post(() -> {
- for (UserInfo user : UserManager.get(mContext).getUsers(true /* excludeDying */)) {
+ for (UserInfo user : UserManager.get(mContext).getAliveUsers()) {
final int targetUserId = user.id;
if (!mAuthenticatorIds.containsKey(targetUserId)) {
scheduleUpdateActiveUserWithoutHandler(targetUserId);
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index ec12a97..b33aa0a 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -367,7 +367,7 @@
}
private void removeStaleAccounts() {
- for (UserInfo user : mUserManager.getUsers(true)) {
+ for (UserInfo user : mUserManager.getAliveUsers()) {
// Skip any partially created/removed users
if (user.partial) continue;
Account[] accountsForUser = AccountManagerService.getSingleton().getAccounts(
@@ -777,7 +777,7 @@
if (!mSyncStorageEngine.shouldGrantSyncAdaptersAccountAccess()) {
return;
}
- List<UserInfo> users = mUserManager.getUsers(true);
+ List<UserInfo> users = mUserManager.getAliveUsers();
final int userCount = users.size();
for (int i = 0; i < userCount; i++) {
UserHandle userHandle = users.get(i).getUserHandle();
diff --git a/services/core/java/com/android/server/inputmethod/TEST_MAPPING b/services/core/java/com/android/server/inputmethod/TEST_MAPPING
new file mode 100644
index 0000000..0ccd75d
--- /dev/null
+++ b/services/core/java/com/android/server/inputmethod/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "imports": [
+ {
+ "path": "frameworks/base/core/java/android/view/inputmethod"
+ }
+ ]
+}
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsStorage.java b/services/core/java/com/android/server/locksettings/LockSettingsStorage.java
index e9a05a8..715e41c 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsStorage.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsStorage.java
@@ -746,7 +746,7 @@
public void dump(IndentingPrintWriter pw) {
final UserManager um = UserManager.get(mContext);
- for (UserInfo user : um.getUsers(false)) {
+ for (UserInfo user : um.getUsers()) {
File userPath = getSyntheticPasswordDirectoryForUser(user.id);
pw.println(String.format("User %d [%s]:", user.id, userPath.getAbsolutePath()));
pw.increaseIndent();
diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java
index a604625..74b7bd7 100644
--- a/services/core/java/com/android/server/notification/ManagedServices.java
+++ b/services/core/java/com/android/server/notification/ManagedServices.java
@@ -1554,7 +1554,7 @@
if (!isEnabledForCurrentProfiles()) {
return false;
}
- return this.userid == userId;
+ return userId == USER_ALL || userId == this.userid;
}
public boolean enabledAndUserMatches(int nid) {
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 0465855..12419a9 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -262,7 +262,6 @@
import com.android.server.IoThread;
import com.android.server.LocalServices;
import com.android.server.SystemService;
-import com.android.server.SystemService.TargetUser;
import com.android.server.UiThread;
import com.android.server.lights.LightsManager;
import com.android.server.lights.LogicalLight;
@@ -966,8 +965,7 @@
nv.recycle();
}
reportUserInteraction(r);
- mAssistants.notifyAssistantActionClicked(
- r.getSbn(), actionIndex, action, generatedByAssistant);
+ mAssistants.notifyAssistantActionClicked(r.getSbn(), action, generatedByAssistant);
}
}
@@ -8629,12 +8627,25 @@
ServiceManager.getService(Context.COMPANION_DEVICE_SERVICE));
}
- private boolean isVisibleToListener(StatusBarNotification sbn, ManagedServiceInfo listener) {
+ @VisibleForTesting
+ boolean isVisibleToListener(StatusBarNotification sbn, ManagedServiceInfo listener) {
if (!listener.enabledAndUserMatches(sbn.getUserId())) {
return false;
}
- // TODO: remove this for older listeners.
- return true;
+ return isInteractionVisibleToListener(listener, sbn.getUserId());
+ }
+
+ /**
+ * Returns whether the given assistant should be informed about interactions on the given user.
+ *
+ * Normally an assistant would be able to see all interactions on the current user and any
+ * associated profiles because they are notification listeners, but since NASes have one
+ * instance per user, we want to filter out interactions that are not for the user that the
+ * given NAS is bound in.
+ */
+ private boolean isInteractionVisibleToListener(ManagedServiceInfo info, int userId) {
+ boolean isAssistantService = mAssistants.isServiceTokenValidLocked(info.service);
+ return !isAssistantService || info.isSameUser(userId);
}
private boolean isPackageSuspendedForUser(String pkg, int uid) {
@@ -8856,8 +8867,6 @@
}
protected void onNotificationsSeenLocked(ArrayList<NotificationRecord> records) {
- // There should be only one, but it's a list, so while we enforce
- // singularity elsewhere, we keep it general here, to avoid surprises.
for (final ManagedServiceInfo info : NotificationAssistants.this.getServices()) {
ArrayList<String> keys = new ArrayList<>(records.size());
for (NotificationRecord r : records) {
@@ -8875,6 +8884,8 @@
}
protected void onPanelRevealed(int items) {
+ // send to all currently bounds NASes since notifications from both users will appear in
+ // the panel
for (final ManagedServiceInfo info : NotificationAssistants.this.getServices()) {
mHandler.post(() -> {
final INotificationListener assistant = (INotificationListener) info.service;
@@ -8888,6 +8899,8 @@
}
protected void onPanelHidden() {
+ // send to all currently bounds NASes since notifications from both users will appear in
+ // the panel
for (final ManagedServiceInfo info : NotificationAssistants.this.getServices()) {
mHandler.post(() -> {
final INotificationListener assistant = (INotificationListener) info.service;
@@ -8976,7 +8989,7 @@
}
notifyAssistantLocked(
sbn,
- false /* sameUserOnly */,
+ true /* sameUserOnly */,
(assistant, sbnHolder) -> {
try {
assistant.onNotificationVisibilityChanged(key, isVisible);
@@ -8994,7 +9007,7 @@
final String key = sbn.getKey();
notifyAssistantLocked(
sbn,
- false /* sameUserOnly */,
+ true /* sameUserOnly */,
(assistant, sbnHolder) -> {
try {
assistant.onNotificationExpansionChanged(key, isUserAction, isExpanded);
@@ -9010,7 +9023,7 @@
final String key = sbn.getKey();
notifyAssistantLocked(
sbn,
- false /* sameUserOnly */,
+ true /* sameUserOnly */,
(assistant, sbnHolder) -> {
try {
assistant.onNotificationDirectReply(key);
@@ -9026,7 +9039,7 @@
final String key = sbn.getKey();
notifyAssistantLocked(
sbn,
- false /* sameUserOnly */,
+ true /* sameUserOnly */,
(assistant, sbnHolder) -> {
try {
assistant.onSuggestedReplySent(
@@ -9043,12 +9056,12 @@
@GuardedBy("mNotificationLock")
void notifyAssistantActionClicked(
- final StatusBarNotification sbn, int actionIndex, Notification.Action action,
+ final StatusBarNotification sbn, Notification.Action action,
boolean generatedByAssistant) {
final String key = sbn.getKey();
notifyAssistantLocked(
sbn,
- false /* sameUserOnly */,
+ true /* sameUserOnly */,
(assistant, sbnHolder) -> {
try {
assistant.onActionClicked(
@@ -9072,7 +9085,7 @@
final StatusBarNotification sbn, final String snoozeCriterionId) {
notifyAssistantLocked(
sbn,
- false /* sameUserOnly */,
+ true /* sameUserOnly */,
(assistant, sbnHolder) -> {
try {
assistant.onNotificationSnoozedUntilContext(
@@ -9129,7 +9142,7 @@
}
protected void resetDefaultAssistantsIfNecessary() {
- final List<UserInfo> activeUsers = mUm.getUsers(true);
+ final List<UserInfo> activeUsers = mUm.getAliveUsers();
for (UserInfo userInfo : activeUsers) {
int userId = userInfo.getUserHandle().getIdentifier();
if (!hasUserSet(userId)) {
@@ -9293,10 +9306,12 @@
}
public void onStatusBarIconsBehaviorChanged(boolean hideSilentStatusIcons) {
+ // send to all currently bounds NASes since notifications from both users will appear in
+ // the status bar
for (final ManagedServiceInfo info : getServices()) {
mHandler.post(() -> {
final INotificationListener listener = (INotificationListener) info.service;
- try {
+ try {
listener.onStatusBarIconsBehaviorChanged(hideSilentStatusIcons);
} catch (RemoteException ex) {
Slog.e(TAG, "unable to notify listener "
@@ -9470,7 +9485,8 @@
&& changedHiddenNotifications.size() > 0;
for (final ManagedServiceInfo serviceInfo : getServices()) {
- if (!serviceInfo.isEnabledForCurrentProfiles()) {
+ if (!serviceInfo.isEnabledForCurrentProfiles() || !isInteractionVisibleToListener(
+ serviceInfo, ActivityManager.getCurrentUser())) {
continue;
}
@@ -9489,12 +9505,7 @@
final NotificationRankingUpdate update = makeRankingUpdateLocked(
serviceInfo);
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- notifyRankingUpdate(serviceInfo, update);
- }
- });
+ mHandler.post(() -> notifyRankingUpdate(serviceInfo, update));
}
}
}
@@ -9502,15 +9513,11 @@
@GuardedBy("mNotificationLock")
public void notifyListenerHintsChangedLocked(final int hints) {
for (final ManagedServiceInfo serviceInfo : getServices()) {
- if (!serviceInfo.isEnabledForCurrentProfiles()) {
+ if (!serviceInfo.isEnabledForCurrentProfiles() || !isInteractionVisibleToListener(
+ serviceInfo, ActivityManager.getCurrentUser())) {
continue;
}
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- notifyListenerHintsChanged(serviceInfo, hints);
- }
- });
+ mHandler.post(() -> notifyListenerHintsChanged(serviceInfo, hints));
}
}
@@ -9562,15 +9569,12 @@
public void notifyInterruptionFilterChanged(final int interruptionFilter) {
for (final ManagedServiceInfo serviceInfo : getServices()) {
- if (!serviceInfo.isEnabledForCurrentProfiles()) {
+ if (!serviceInfo.isEnabledForCurrentProfiles() || !isInteractionVisibleToListener(
+ serviceInfo, ActivityManager.getCurrentUser())) {
continue;
}
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- notifyInterruptionFilterChanged(serviceInfo, interruptionFilter);
- }
- });
+ mHandler.post(
+ () -> notifyInterruptionFilterChanged(serviceInfo, interruptionFilter));
}
}
@@ -9579,15 +9583,16 @@
if (channel == null) {
return;
}
- for (final ManagedServiceInfo serviceInfo : getServices()) {
- if (!serviceInfo.enabledAndUserMatches(UserHandle.getCallingUserId())) {
+ for (final ManagedServiceInfo info : getServices()) {
+ if (!info.enabledAndUserMatches(UserHandle.getCallingUserId())
+ || !isInteractionVisibleToListener(info, UserHandle.getCallingUserId())) {
continue;
}
BackgroundThread.getHandler().post(() -> {
- if (serviceInfo.isSystem || hasCompanionDevice(serviceInfo)) {
+ if (info.isSystem || hasCompanionDevice(info)) {
notifyNotificationChannelChanged(
- serviceInfo, pkg, user, channel, modificationType);
+ info, pkg, user, channel, modificationType);
}
});
}
@@ -9599,15 +9604,16 @@
if (group == null) {
return;
}
- for (final ManagedServiceInfo serviceInfo : getServices()) {
- if (!serviceInfo.enabledAndUserMatches(UserHandle.getCallingUserId())) {
+ for (final ManagedServiceInfo info : getServices()) {
+ if (!info.enabledAndUserMatches(UserHandle.getCallingUserId())
+ || !isInteractionVisibleToListener(info, UserHandle.getCallingUserId())) {
continue;
}
BackgroundThread.getHandler().post(() -> {
- if (serviceInfo.isSystem || hasCompanionDevice(serviceInfo)) {
+ if (info.isSystem || hasCompanionDevice(info)) {
notifyNotificationChannelGroupChanged(
- serviceInfo, pkg, user, group, modificationType);
+ info, pkg, user, group, modificationType);
}
});
}
@@ -9626,9 +9632,6 @@
private void notifyRemoved(ManagedServiceInfo info, StatusBarNotification sbn,
NotificationRankingUpdate rankingUpdate, NotificationStats stats, int reason) {
- if (!info.enabledAndUserMatches(sbn.getUserId())) {
- return;
- }
final INotificationListener listener = (INotificationListener) info.service;
StatusBarNotificationHolder sbnHolder = new StatusBarNotificationHolder(sbn);
try {
diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java
index a4debc1..d7a1ba2 100644
--- a/services/core/java/com/android/server/om/OverlayManagerService.java
+++ b/services/core/java/com/android/server/om/OverlayManagerService.java
@@ -288,7 +288,7 @@
private void initIfNeeded() {
final UserManager um = getContext().getSystemService(UserManager.class);
- final List<UserInfo> users = um.getUsers(true /*excludeDying*/);
+ final List<UserInfo> users = um.getAliveUsers();
synchronized (mLock) {
final int userCount = users.size();
for (int i = 0; i < userCount; i++) {
diff --git a/services/core/java/com/android/server/pm/ApkChecksums.java b/services/core/java/com/android/server/pm/ApkChecksums.java
index d8745ab..0338ed8 100644
--- a/services/core/java/com/android/server/pm/ApkChecksums.java
+++ b/services/core/java/com/android/server/pm/ApkChecksums.java
@@ -16,6 +16,7 @@
package com.android.server.pm;
+import static android.content.pm.PackageManager.EXTRA_CHECKSUMS;
import static android.content.pm.PackageManager.PARTIAL_MERKLE_ROOT_1M_SHA256;
import static android.content.pm.PackageManager.PARTIAL_MERKLE_ROOT_1M_SHA512;
import static android.content.pm.PackageManager.WHOLE_MD5;
@@ -27,11 +28,20 @@
import static android.util.apk.ApkSigningBlockUtils.CONTENT_DIGEST_CHUNKED_SHA512;
import static android.util.apk.ApkSigningBlockUtils.CONTENT_DIGEST_VERITY_CHUNKED_SHA256;
+import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentSender;
import android.content.pm.FileChecksum;
import android.content.pm.PackageManager;
import android.content.pm.PackageParser;
+import android.os.Handler;
+import android.os.SystemClock;
+import android.os.incremental.IncrementalManager;
+import android.os.incremental.IncrementalStorage;
import android.util.ArrayMap;
+import android.util.Pair;
import android.util.Slog;
import android.util.apk.ApkSignatureSchemeV2Verifier;
import android.util.apk.ApkSignatureSchemeV3Verifier;
@@ -43,6 +53,7 @@
import android.util.apk.SignatureNotFoundException;
import android.util.apk.VerityBuilder;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.server.security.VerityUtils;
import java.io.BufferedInputStream;
@@ -72,32 +83,163 @@
static final String ALGO_SHA512 = "SHA512";
/**
- * Fetch or calculate checksums for the specific file.
+ * Check back in 1 second after we detected we needed to wait for the APK to be fully available.
+ */
+ private static final long PROCESS_REQUIRED_CHECKSUMS_DELAY_MILLIS = 1000;
+
+ /**
+ * 24 hours timeout to wait till all files are loaded.
+ */
+ private static final long PROCESS_REQUIRED_CHECKSUMS_TIMEOUT_MILLIS = 1000 * 3600 * 24;
+
+ /**
+ * Unit tests will instantiate, extend and/or mock to mock dependencies / behaviors.
*
- * @param split split name, null for base
- * @param file to fetch checksums for
+ * NOTE: All getters should return the same instance for every call.
+ */
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ static class Injector {
+
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ interface Producer<T> {
+ /** Produce an instance of type {@link T} */
+ T produce();
+ }
+
+ private final Producer<Context> mContext;
+ private final Producer<Handler> mHandlerProducer;
+ private final Producer<IncrementalManager> mIncrementalManagerProducer;
+
+ Injector(Producer<Context> context, Producer<Handler> handlerProducer,
+ Producer<IncrementalManager> incrementalManagerProducer) {
+ mContext = context;
+ mHandlerProducer = handlerProducer;
+ mIncrementalManagerProducer = incrementalManagerProducer;
+ }
+
+ public Context getContext() {
+ return mContext.produce();
+ }
+
+ public Handler getHandler() {
+ return mHandlerProducer.produce();
+ }
+
+ public IncrementalManager getIncrementalManager() {
+ return mIncrementalManagerProducer.produce();
+ }
+ }
+
+ /**
+ * Fetch or calculate checksums for the collection of files.
+ *
+ * @param filesToChecksum split name, null for base and File to fetch checksums for
* @param optional mask to fetch readily available checksums
* @param required mask to forcefully calculate if not available
* @param trustedInstallers array of certificate to trust, two specific cases:
* null - trust anybody,
* [] - trust nobody.
+ * @param statusReceiver to receive the resulting checksums
*/
- public static List<FileChecksum> getFileChecksums(String split, File file,
+ public static void getChecksums(List<Pair<String, File>> filesToChecksum,
@PackageManager.FileChecksumKind int optional,
@PackageManager.FileChecksumKind int required,
- @Nullable Certificate[] trustedInstallers) {
+ @Nullable Certificate[] trustedInstallers,
+ @NonNull IntentSender statusReceiver,
+ @NonNull Injector injector) {
+ List<Map<Integer, FileChecksum>> result = new ArrayList<>(filesToChecksum.size());
+ for (int i = 0, size = filesToChecksum.size(); i < size; ++i) {
+ final String split = filesToChecksum.get(i).first;
+ final File file = filesToChecksum.get(i).second;
+ Map<Integer, FileChecksum> checksums = new ArrayMap<>();
+ result.add(checksums);
+
+ try {
+ getAvailableFileChecksums(split, file, optional | required, trustedInstallers,
+ checksums);
+ } catch (Throwable e) {
+ Slog.e(TAG, "Preferred checksum calculation error", e);
+ }
+ }
+
+ long startTime = SystemClock.uptimeMillis();
+ processRequiredChecksums(filesToChecksum, result, required, statusReceiver, injector,
+ startTime);
+ }
+
+ private static void processRequiredChecksums(List<Pair<String, File>> filesToChecksum,
+ List<Map<Integer, FileChecksum>> result,
+ @PackageManager.FileChecksumKind int required,
+ @NonNull IntentSender statusReceiver,
+ @NonNull Injector injector,
+ long startTime) {
+ final boolean timeout =
+ SystemClock.uptimeMillis() - startTime >= PROCESS_REQUIRED_CHECKSUMS_TIMEOUT_MILLIS;
+ List<FileChecksum> allChecksums = new ArrayList<>();
+ for (int i = 0, size = filesToChecksum.size(); i < size; ++i) {
+ final String split = filesToChecksum.get(i).first;
+ final File file = filesToChecksum.get(i).second;
+ Map<Integer, FileChecksum> checksums = result.get(i);
+
+ try {
+ if (!timeout || required != 0) {
+ if (needToWait(file, required, checksums, injector)) {
+ // Not ready, come back later.
+ injector.getHandler().postDelayed(() -> {
+ processRequiredChecksums(filesToChecksum, result, required,
+ statusReceiver, injector, startTime);
+ }, PROCESS_REQUIRED_CHECKSUMS_DELAY_MILLIS);
+ return;
+ }
+
+ getRequiredFileChecksums(split, file, required, checksums);
+ }
+ allChecksums.addAll(checksums.values());
+ } catch (Throwable e) {
+ Slog.e(TAG, "Required checksum calculation error", e);
+ }
+ }
+
+ final Intent intent = new Intent();
+ intent.putExtra(EXTRA_CHECKSUMS,
+ allChecksums.toArray(new FileChecksum[allChecksums.size()]));
+
+ try {
+ statusReceiver.sendIntent(injector.getContext(), 1, intent, null, null);
+ } catch (IntentSender.SendIntentException e) {
+ Slog.w(TAG, e);
+ }
+ }
+
+ /**
+ * Fetch readily available checksums - enforced by kernel or provided by Installer.
+ *
+ * @param split split name, null for base
+ * @param file to fetch checksums for
+ * @param kinds mask to fetch checksums
+ * @param trustedInstallers array of certificate to trust, two specific cases:
+ * null - trust anybody,
+ * [] - trust nobody.
+ * @param checksums resulting checksums
+ */
+ private static void getAvailableFileChecksums(String split, File file,
+ @PackageManager.FileChecksumKind int kinds,
+ @Nullable Certificate[] trustedInstallers,
+ Map<Integer, FileChecksum> checksums) {
final String filePath = file.getAbsolutePath();
- Map<Integer, FileChecksum> checksums = new ArrayMap<>();
- final int kinds = (optional | required);
- // System enforced: FSI or v2/v3/v4 signatures.
- if ((kinds & WHOLE_MERKLE_ROOT_4K_SHA256) != 0) {
+
+ // Always available: FSI or IncFs.
+ if (isRequired(WHOLE_MERKLE_ROOT_4K_SHA256, kinds, checksums)) {
// Hashes in fs-verity and IncFS are always verified.
FileChecksum checksum = extractHashFromFS(split, filePath);
if (checksum != null) {
checksums.put(checksum.getKind(), checksum);
}
}
- if ((kinds & (PARTIAL_MERKLE_ROOT_1M_SHA256 | PARTIAL_MERKLE_ROOT_1M_SHA512)) != 0) {
+
+ // System enforced: v2/v3.
+ if (isRequired(PARTIAL_MERKLE_ROOT_1M_SHA256, kinds, checksums) || isRequired(
+ PARTIAL_MERKLE_ROOT_1M_SHA512, kinds, checksums)) {
Map<Integer, FileChecksum> v2v3checksums = extractHashFromV2V3Signature(
split, filePath, kinds);
if (v2v3checksums != null) {
@@ -106,11 +248,58 @@
}
// TODO(b/160605420): Installer provided.
- // TODO(b/160605420): Wait for Incremental to be fully loaded.
+ }
+
+ /**
+ * Whether the file is available for checksumming or we need to wait.
+ */
+ private static boolean needToWait(File file,
+ @PackageManager.FileChecksumKind int kinds,
+ Map<Integer, FileChecksum> checksums,
+ @NonNull Injector injector) throws IOException {
+ if (!isRequired(WHOLE_MERKLE_ROOT_4K_SHA256, kinds, checksums)
+ && !isRequired(WHOLE_MD5, kinds, checksums)
+ && !isRequired(WHOLE_SHA1, kinds, checksums)
+ && !isRequired(WHOLE_SHA256, kinds, checksums)
+ && !isRequired(WHOLE_SHA512, kinds, checksums)
+ && !isRequired(PARTIAL_MERKLE_ROOT_1M_SHA256, kinds, checksums)
+ && !isRequired(PARTIAL_MERKLE_ROOT_1M_SHA512, kinds, checksums)) {
+ return false;
+ }
+
+ final String filePath = file.getAbsolutePath();
+ if (!IncrementalManager.isIncrementalPath(filePath)) {
+ return false;
+ }
+
+ IncrementalManager manager = injector.getIncrementalManager();
+ if (manager == null) {
+ throw new IllegalStateException("IncrementalManager is missing.");
+ }
+ IncrementalStorage storage = manager.openStorage(filePath);
+ if (storage == null) {
+ throw new IllegalStateException(
+ "IncrementalStorage is missing for a path on IncFs: " + filePath);
+ }
+
+ return !storage.isFileFullyLoaded(filePath);
+ }
+
+ /**
+ * Fetch or calculate checksums for the specific file.
+ *
+ * @param split split name, null for base
+ * @param file to fetch checksums for
+ * @param kinds mask to forcefully calculate if not available
+ * @param checksums resulting checksums
+ */
+ private static void getRequiredFileChecksums(String split, File file,
+ @PackageManager.FileChecksumKind int kinds,
+ Map<Integer, FileChecksum> checksums) {
+ final String filePath = file.getAbsolutePath();
// Manually calculating required checksums if not readily available.
- if ((required & WHOLE_MERKLE_ROOT_4K_SHA256) != 0 && !checksums.containsKey(
- WHOLE_MERKLE_ROOT_4K_SHA256)) {
+ if (isRequired(WHOLE_MERKLE_ROOT_4K_SHA256, kinds, checksums)) {
try {
byte[] generatedRootHash = VerityBuilder.generateFsVerityRootHash(
filePath, /*salt=*/null,
@@ -127,14 +316,23 @@
}
}
- calculateChecksumIfRequested(checksums, split, file, required, WHOLE_MD5);
- calculateChecksumIfRequested(checksums, split, file, required, WHOLE_SHA1);
- calculateChecksumIfRequested(checksums, split, file, required, WHOLE_SHA256);
- calculateChecksumIfRequested(checksums, split, file, required, WHOLE_SHA512);
+ calculateChecksumIfRequested(checksums, split, file, kinds, WHOLE_MD5);
+ calculateChecksumIfRequested(checksums, split, file, kinds, WHOLE_SHA1);
+ calculateChecksumIfRequested(checksums, split, file, kinds, WHOLE_SHA256);
+ calculateChecksumIfRequested(checksums, split, file, kinds, WHOLE_SHA512);
- calculatePartialChecksumsIfRequested(checksums, split, file, required);
+ calculatePartialChecksumsIfRequested(checksums, split, file, kinds);
+ }
- return new ArrayList<>(checksums.values());
+ private static boolean isRequired(@PackageManager.FileChecksumKind int kind,
+ @PackageManager.FileChecksumKind int kinds, Map<Integer, FileChecksum> checksums) {
+ if ((kinds & kind) == 0) {
+ return false;
+ }
+ if (checksums.containsKey(kind)) {
+ return false;
+ }
+ return true;
}
private static FileChecksum extractHashFromFS(String split, String filePath) {
@@ -170,7 +368,9 @@
PackageParser.SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V2,
false).contentDigests;
} catch (PackageParser.PackageParserException e) {
- Slog.e(TAG, "Signature verification error", e);
+ if (!(e.getCause() instanceof SignatureNotFoundException)) {
+ Slog.e(TAG, "Signature verification error", e);
+ }
}
if (contentDigests == null) {
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 4b246c3..162bfee 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -743,9 +743,8 @@
mStagingManager.createSession(session);
}
- if ((session.params.installFlags & PackageManager.INSTALL_DRY_RUN) == 0) {
- mCallbacks.notifySessionCreated(session.sessionId, session.userId);
- }
+ mCallbacks.notifySessionCreated(session.sessionId, session.userId);
+
writeSessionsAsync();
return sessionId;
}
@@ -1355,25 +1354,18 @@
class InternalCallback {
public void onSessionBadgingChanged(PackageInstallerSession session) {
- if ((session.params.installFlags & PackageManager.INSTALL_DRY_RUN) == 0) {
- mCallbacks.notifySessionBadgingChanged(session.sessionId, session.userId);
- }
-
+ mCallbacks.notifySessionBadgingChanged(session.sessionId, session.userId);
writeSessionsAsync();
}
public void onSessionActiveChanged(PackageInstallerSession session, boolean active) {
- if ((session.params.installFlags & PackageManager.INSTALL_DRY_RUN) == 0) {
- mCallbacks.notifySessionActiveChanged(session.sessionId, session.userId,
- active);
- }
+ mCallbacks.notifySessionActiveChanged(session.sessionId, session.userId,
+ active);
}
public void onSessionProgressChanged(PackageInstallerSession session, float progress) {
- if ((session.params.installFlags & PackageManager.INSTALL_DRY_RUN) == 0) {
- mCallbacks.notifySessionProgressChanged(session.sessionId, session.userId,
- progress);
- }
+ mCallbacks.notifySessionProgressChanged(session.sessionId, session.userId,
+ progress);
}
public void onStagedSessionChanged(PackageInstallerSession session) {
@@ -1389,17 +1381,13 @@
}
public void onSessionFinished(final PackageInstallerSession session, boolean success) {
- if ((session.params.installFlags & PackageManager.INSTALL_DRY_RUN) == 0) {
- mCallbacks.notifySessionFinished(session.sessionId, session.userId, success);
- }
+ mCallbacks.notifySessionFinished(session.sessionId, session.userId, success);
mInstallHandler.post(new Runnable() {
@Override
public void run() {
- if (session.isStaged()) {
- if (!success) {
- mStagingManager.abortSession(session);
- }
+ if (session.isStaged() && !success) {
+ mStagingManager.abortSession(session);
}
synchronized (mSessions) {
if (!session.isStaged() || !success) {
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index ed62362..51164ba 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -1561,19 +1561,20 @@
dispatchSessionFinished(error, detailMessage, null);
}
- private void onSessionVerificationFailure(int error, String detailMessage) {
- Slog.e(TAG, "Failed to verify session " + sessionId + " [" + detailMessage + "]");
+ private void onSessionVerificationFailure(int error, String msg) {
+ final String msgWithErrorCode = PackageManager.installStatusToString(error, msg);
+ Slog.e(TAG, "Failed to verify session " + sessionId + " [" + msgWithErrorCode + "]");
// Session is sealed and committed but could not be verified, we need to destroy it.
destroyInternal();
if (isStaged()) {
setStagedSessionFailed(
- SessionInfo.STAGED_SESSION_VERIFICATION_FAILED, detailMessage);
+ SessionInfo.STAGED_SESSION_VERIFICATION_FAILED, msgWithErrorCode);
// TODO(b/136257624): Remove this once all verification logic has been transferred out
// of StagingManager.
mStagingManager.notifyVerificationComplete(sessionId);
} else {
// Dispatch message to remove session from PackageInstallerService.
- dispatchSessionFinished(error, detailMessage, null);
+ dispatchSessionFinished(error, msg, null);
}
}
@@ -3306,8 +3307,7 @@
// Send broadcast to default launcher only if it's a new install
// TODO(b/144270665): Secure the usage of this broadcast.
final boolean isNewInstall = extras == null || !extras.getBoolean(Intent.EXTRA_REPLACING);
- if (success && isNewInstall && mPm.mInstallerService.okToSendBroadcasts()
- && (params.installFlags & PackageManager.INSTALL_DRY_RUN) == 0) {
+ if (success && isNewInstall && mPm.mInstallerService.okToSendBroadcasts()) {
mPm.sendSessionCommitBroadcast(generateInfoScrubbed(true /*icon*/), userId);
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 344f9cf..b6b7e93 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -40,7 +40,6 @@
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
-import static android.content.pm.PackageManager.EXTRA_CHECKSUMS;
import static android.content.pm.PackageManager.EXTRA_VERIFICATION_ID;
import static android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
import static android.content.pm.PackageManager.FLAG_PERMISSION_POLICY_FIXED;
@@ -169,7 +168,6 @@
import android.content.pm.DataLoaderType;
import android.content.pm.FallbackCategoryProvider;
import android.content.pm.FeatureInfo;
-import android.content.pm.FileChecksum;
import android.content.pm.IDexModuleRegisterCallback;
import android.content.pm.IPackageChangeObserver;
import android.content.pm.IPackageDataObserver;
@@ -933,6 +931,7 @@
private final Object mLock;
private final Installer mInstaller;
private final Object mInstallLock;
+ private final Handler mBackgroundHandler;
private final Executor mBackgroundExecutor;
// ----- producers -----
@@ -955,7 +954,7 @@
Injector(Context context, Object lock, Installer installer,
Object installLock, PackageAbiHelper abiHelper,
- Executor backgroundExecutor,
+ Handler backgroundHandler,
Producer<ComponentResolver> componentResolverProducer,
Producer<PermissionManagerServiceInternal> permissionManagerProducer,
Producer<UserManagerService> userManagerProducer,
@@ -977,7 +976,8 @@
mInstaller = installer;
mAbiHelper = abiHelper;
mInstallLock = installLock;
- mBackgroundExecutor = backgroundExecutor;
+ mBackgroundHandler = backgroundHandler;
+ mBackgroundExecutor = new HandlerExecutor(backgroundHandler);
mComponentResolverProducer = new Singleton<>(componentResolverProducer);
mPermissionManagerProducer = new Singleton<>(permissionManagerProducer);
mUserManagerProducer = new Singleton<>(userManagerProducer);
@@ -1092,6 +1092,10 @@
return mPlatformCompatProducer.get(this, mPackageManager);
}
+ public Handler getBackgroundHandler() {
+ return mBackgroundHandler;
+ }
+
public Executor getBackgroundExecutor() {
return mBackgroundExecutor;
}
@@ -2489,29 +2493,14 @@
final Certificate[] trustedCerts = (trustedInstallers != null) ? decodeCertificates(
trustedInstallers) : null;
- final Context context = mContext;
mInjector.getBackgroundExecutor().execute(() -> {
- final Intent intent = new Intent();
- List<FileChecksum> result = new ArrayList<>();
- for (int i = 0, size = filesToChecksum.size(); i < size; ++i) {
- final String split = filesToChecksum.get(i).first;
- final File file = filesToChecksum.get(i).second;
- try {
- result.addAll(ApkChecksums.getFileChecksums(split, file, optional, required,
- trustedCerts));
- } catch (Throwable e) {
- Slog.e(TAG, "Checksum calculation error", e);
- }
- }
- intent.putExtra(EXTRA_CHECKSUMS,
- result.toArray(new FileChecksum[result.size()]));
-
- try {
- statusReceiver.sendIntent(context, 1, intent, null, null);
- } catch (SendIntentException e) {
- Slog.w(TAG, e);
- }
+ ApkChecksums.Injector injector = new ApkChecksums.Injector(
+ () -> mContext,
+ () -> mInjector.getBackgroundHandler(),
+ () -> mContext.getSystemService(IncrementalManager.class));
+ ApkChecksums.getChecksums(filesToChecksum, optional, required, trustedCerts,
+ statusReceiver, injector);
});
}
@@ -2684,7 +2673,7 @@
Injector injector = new Injector(
context, lock, installer, installLock, new PackageAbiHelperImpl(),
- new HandlerExecutor(backgroundHandler),
+ backgroundHandler,
(i, pm) ->
new ComponentResolver(i.getUserManagerService(), pm.mPmInternal, lock),
(i, pm) ->
@@ -14541,13 +14530,11 @@
Log.v(TAG, "restoreAndPostInstall userId=" + userId + " package=" + res.pkg);
}
- // A restore should be performed at this point if (a) the install
- // succeeded, (b) the operation is not an update, and (c) the new
- // package has not opted out of backup participation.
+ // A restore should be requested at this point if (a) the install
+ // succeeded, (b) the operation is not an update.
final boolean update = res.removedInfo != null
&& res.removedInfo.removedPackage != null;
- boolean allowBackup = res.pkg != null && res.pkg.isAllowBackup();
- boolean doRestore = !update && allowBackup;
+ boolean doRestore = !update;
// Set up the post-install work request bookkeeping. This will be used
// and cleaned up by the post-install event handling regardless of whether
diff --git a/services/core/java/com/android/server/pm/TEST_MAPPING b/services/core/java/com/android/server/pm/TEST_MAPPING
index dbe96e6..4858682 100644
--- a/services/core/java/com/android/server/pm/TEST_MAPPING
+++ b/services/core/java/com/android/server/pm/TEST_MAPPING
@@ -33,6 +33,9 @@
"name": "CtsContentTestCases",
"options": [
{
+ "include-filter": "android.content.pm.cts.ChecksumsTest"
+ },
+ {
"include-filter": "android.content.pm.cts.PackageManagerShellCommandTest"
},
{
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index d137fd0..e44c8ab 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -760,6 +760,8 @@
return null;
}
+ // TODO(b/157921703): replace by getAliveUsers() or remove (so callers
+ // explicitly call the 3-booleans version)
public @NonNull List<UserInfo> getUsers(boolean excludeDying) {
return getUsers(/*excludePartial= */ true, excludeDying, /* excludePreCreated= */
true);
diff --git a/services/core/java/com/android/server/slice/SliceFullAccessList.java b/services/core/java/com/android/server/slice/SliceFullAccessList.java
index 6f5afa2..d25ddf8 100644
--- a/services/core/java/com/android/server/slice/SliceFullAccessList.java
+++ b/services/core/java/com/android/server/slice/SliceFullAccessList.java
@@ -101,7 +101,7 @@
public void readXml(XmlPullParser parser) throws XmlPullParserException, IOException {
// upgrade xml
int xmlVersion = XmlUtils.readIntAttribute(parser, ATT_VERSION, 0);
- final List<UserInfo> activeUsers = UserManager.get(mContext).getUsers(true);
+ final List<UserInfo> activeUsers = UserManager.get(mContext).getAliveUsers();
for (UserInfo userInfo : activeUsers) {
upgradeXml(xmlVersion, userInfo.getUserHandle().getIdentifier());
}
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index 0c85387..386f390 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -379,7 +379,7 @@
}
private void updateTrustAll() {
- List<UserInfo> userInfos = mUserManager.getUsers(true /* excludeDying */);
+ List<UserInfo> userInfos = mUserManager.getAliveUsers();
for (UserInfo userInfo : userInfos) {
updateTrust(userInfo.id, 0);
}
@@ -485,7 +485,7 @@
List<UserInfo> userInfos;
if (userIdOrAll == UserHandle.USER_ALL) {
- userInfos = mUserManager.getUsers(true /* excludeDying */);
+ userInfos = mUserManager.getAliveUsers();
} else {
userInfos = new ArrayList<>();
userInfos.add(mUserManager.getUserInfo(userIdOrAll));
@@ -644,7 +644,7 @@
}
List<UserInfo> userInfos;
if (userId == UserHandle.USER_ALL) {
- userInfos = mUserManager.getUsers(true /* excludeDying */);
+ userInfos = mUserManager.getAliveUsers();
} else {
userInfos = new ArrayList<>();
userInfos.add(mUserManager.getUserInfo(userId));
@@ -1171,7 +1171,7 @@
fout.println("disabled because the third-party apps can't run yet.");
return;
}
- final List<UserInfo> userInfos = mUserManager.getUsers(true /* excludeDying */);
+ final List<UserInfo> userInfos = mUserManager.getAliveUsers();
mHandler.runWithScissors(new Runnable() {
@Override
public void run() {
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 56261c4..7d4d562 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -401,7 +401,6 @@
final ActivityTaskManagerService mAtmService;
final ActivityInfo info; // activity info provided by developer in AndroidManifest
- // Non-null only for application tokens.
// TODO: rename to mActivityToken
final ActivityRecord.Token appToken;
// Which user is this running for?
@@ -5480,10 +5479,6 @@
}
void updateReportedVisibilityLocked() {
- if (appToken == null) {
- return;
- }
-
if (DEBUG_VISIBILITY) Slog.v(TAG, "Update reported visibility: " + this);
final int count = mChildren.size();
@@ -6330,8 +6325,7 @@
}
private void setOrientation(int requestedOrientation, boolean freezeScreenIfNeeded) {
- final IBinder binder =
- (freezeScreenIfNeeded && appToken != null) ? appToken.asBinder() : null;
+ final IBinder binder = freezeScreenIfNeeded ? appToken.asBinder() : null;
setOrientation(requestedOrientation, binder, this);
// Push the new configuration to the requested app in case where it's not pushed, e.g. when
@@ -7713,9 +7707,7 @@
}
void writeNameToProto(ProtoOutputStream proto, long fieldId) {
- if (appToken != null) {
- proto.write(fieldId, appToken.getName());
- }
+ proto.write(fieldId, appToken.getName());
}
@Override
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index be7a6ae..f206259 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -1710,8 +1710,9 @@
mRootWindowContainer.startPowerModeLaunchIfNeeded(
false /* forceSend */, mStartActivity);
- mTargetStack.startActivityLocked(mStartActivity, topStack.getTopNonFinishingActivity(),
- newTask, mKeepCurTransition, mOptions);
+ mTargetStack.startActivityLocked(mStartActivity,
+ topStack != null ? topStack.getTopNonFinishingActivity() : null, newTask,
+ mKeepCurTransition, mOptions);
if (mDoResume) {
final ActivityRecord topTaskActivity =
mStartActivity.getTask().topRunningActivityLocked();
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 6a8cbfb..c58b5b5 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -125,6 +125,7 @@
import static com.android.server.wm.Task.REPARENT_KEEP_STACK_AT_FRONT;
import static com.android.server.wm.Task.REPARENT_LEAVE_STACK_IN_PLACE;
import static com.android.server.wm.WindowContainer.POSITION_TOP;
+import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
import android.Manifest;
import android.annotation.IntDef;
@@ -5465,8 +5466,11 @@
updateResumedAppTrace(r);
mLastResumedActivity = r;
- r.getDisplay().setFocusedApp(r, true);
-
+ final boolean changed = r.getDisplay().setFocusedApp(r);
+ if (changed) {
+ mWindowManager.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL,
+ true /*updateInputWindows*/);
+ }
if (prevTask == null || task != prevTask) {
if (prevTask != null) {
mTaskChangeNotificationController.notifyTaskFocusChanged(prevTask.mTaskId, false);
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 2f7cc69..aa8069a 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -115,13 +115,11 @@
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_STACK_CRAWLS;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
-import static com.android.server.wm.WindowManagerService.H.REPORT_FOCUS_CHANGE;
import static com.android.server.wm.WindowManagerService.H.REPORT_HARD_KEYBOARD_STATUS_CHANGE;
import static com.android.server.wm.WindowManagerService.H.UPDATE_MULTI_WINDOW_STACKS;
import static com.android.server.wm.WindowManagerService.H.WINDOW_HIDE_TIMEOUT;
import static com.android.server.wm.WindowManagerService.LAYOUT_REPEAT_THRESHOLD;
import static com.android.server.wm.WindowManagerService.SEAMLESS_ROTATION_TIMEOUT_DURATION;
-import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_PLACING_SURFACES;
import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_REMOVING_FOCUS;
import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_ASSIGN_LAYERS;
@@ -649,8 +647,9 @@
private final ToBooleanFunction<WindowState> mFindFocusedWindow = w -> {
final ActivityRecord focusedApp = mFocusedApp;
- ProtoLog.v(WM_DEBUG_FOCUS, "Looking for focus: %s, flags=%d, canReceive=%b",
- w, w.mAttrs.flags, w.canReceiveKeys());
+ ProtoLog.v(WM_DEBUG_FOCUS, "Looking for focus: %s, flags=%d, canReceive=%b, reason=%s",
+ w, w.mAttrs.flags, w.canReceiveKeys(),
+ w.canReceiveKeysReason(false /* fromUserTouch */));
if (!w.canReceiveKeys()) {
return false;
@@ -3072,7 +3071,7 @@
*/
WindowState findFocusedWindowIfNeeded(int topFocusedDisplayId) {
return (mWmService.mPerDisplayFocusEnabled || topFocusedDisplayId == INVALID_DISPLAY)
- ? findFocusedWindow() : null;
+ ? findFocusedWindow() : null;
}
WindowState findFocusedWindow() {
@@ -3081,7 +3080,8 @@
forAllWindows(mFindFocusedWindow, true /* traverseTopToBottom */);
if (mTmpWindow == null) {
- ProtoLog.v(WM_DEBUG_FOCUS_LIGHT, "findFocusedWindow: No focusable windows.");
+ ProtoLog.v(WM_DEBUG_FOCUS_LIGHT, "findFocusedWindow: No focusable windows, display=%d",
+ getDisplayId());
return null;
}
return mTmpWindow;
@@ -3116,18 +3116,15 @@
&& mode != UPDATE_FOCUS_WILL_PLACE_SURFACES) {
assignWindowLayers(false /* setLayoutNeeded */);
}
+
+ if (imWindowChanged) {
+ mWmService.mWindowsChanged = true;
+ setLayoutNeeded();
+ newFocus = findFocusedWindowIfNeeded(topFocusedDisplayId);
+ }
}
- if (imWindowChanged) {
- mWmService.mWindowsChanged = true;
- setLayoutNeeded();
- newFocus = findFocusedWindowIfNeeded(topFocusedDisplayId);
- }
- if (mCurrentFocus != newFocus) {
- mWmService.mH.obtainMessage(REPORT_FOCUS_CHANGE, this).sendToTarget();
- }
-
- ProtoLog.v(WM_DEBUG_FOCUS_LIGHT, "Changing focus from %s to %s displayId=%d Callers=%s",
+ ProtoLog.d(WM_DEBUG_FOCUS_LIGHT, "Changing focus from %s to %s displayId=%d Callers=%s",
mCurrentFocus, newFocus, getDisplayId(), Debug.getCallers(4));
final WindowState oldFocus = mCurrentFocus;
mCurrentFocus = newFocus;
@@ -3185,9 +3182,25 @@
if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM;
}
+
+ // Notify the accessibility manager for the change so it has the windows before the newly
+ // focused one starts firing events.
+ // TODO(b/151179149) investigate what info accessibility service needs before input can
+ // dispatch focus to clients.
+ if (mWmService.mAccessibilityController != null) {
+ mWmService.mH.sendMessage(PooledLambda.obtainMessage(
+ this::updateAccessibilityOnWindowFocusChanged,
+ mWmService.mAccessibilityController));
+ }
+
+ mLastFocus = mCurrentFocus;
return true;
}
+ void updateAccessibilityOnWindowFocusChanged(AccessibilityController accessibilityController) {
+ accessibilityController.onWindowFocusChangedNotLocked(getDisplayId());
+ }
+
private static void onWindowFocusChanged(WindowState oldFocus, WindowState newFocus) {
final Task focusedTask = newFocus != null ? newFocus.getTask() : null;
final Task unfocusedTask = oldFocus != null ? oldFocus.getTask() : null;
@@ -3219,6 +3232,8 @@
if (mFocusedApp == newFocus) {
return false;
}
+ ProtoLog.i(WM_DEBUG_FOCUS_LIGHT, "setFocusedApp %s displayId=%d Callers=%s",
+ newFocus, getDisplayId(), Debug.getCallers(4));
mFocusedApp = newFocus;
getInputMonitor().setFocusedAppLw(newFocus);
updateTouchExcludeRegion();
@@ -4708,7 +4723,7 @@
// Traverse all windows top down to assemble the gesture exclusion rects.
// For each window, we only take the rects that fall within its touchable region.
forAllWindows(w -> {
- if (w.cantReceiveTouchInput() || !w.isVisible()
+ if (!w.canReceiveTouchInput() || !w.isVisible()
|| (w.getAttrs().flags & FLAG_NOT_TOUCHABLE) != 0
|| unhandled.isEmpty()) {
return;
@@ -5225,30 +5240,6 @@
&& (mAtmService.mRunningVoice == null);
}
- void setFocusedApp(ActivityRecord r, boolean moveFocusNow) {
- final ActivityRecord newFocus;
- final IBinder token = r.appToken;
- if (token == null) {
- ProtoLog.v(WM_DEBUG_FOCUS_LIGHT, "Clearing focused app, displayId=%d",
- mDisplayId);
- newFocus = null;
- } else {
- newFocus = mWmService.mRoot.getActivityRecord(token);
- if (newFocus == null) {
- Slog.w(TAG_WM, "Attempted to set focus to non-existing app token: " + token
- + ", displayId=" + mDisplayId);
- }
- ProtoLog.v(WM_DEBUG_FOCUS_LIGHT,
- "Set focused app to: %s moveFocusNow=%b displayId=%d", newFocus,
- moveFocusNow, mDisplayId);
- }
-
- final boolean changed = setFocusedApp(newFocus);
- if (moveFocusNow && changed) {
- mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL,
- true /*updateInputWindows*/);
- }
- }
void ensureActivitiesVisible(ActivityRecord starting, int configChanges,
boolean preserveWindows, boolean notifyClients) {
diff --git a/services/core/java/com/android/server/wm/DragDropController.java b/services/core/java/com/android/server/wm/DragDropController.java
index 999aab9..ec62ed4 100644
--- a/services/core/java/com/android/server/wm/DragDropController.java
+++ b/services/core/java/com/android/server/wm/DragDropController.java
@@ -114,7 +114,7 @@
final WindowState callingWin = mService.windowForClientLocked(
null, window, false);
- if (callingWin == null || callingWin.cantReceiveTouchInput()) {
+ if (callingWin == null || !callingWin.canReceiveTouchInput()) {
Slog.w(TAG_WM, "Bad requesting window " + window);
return null; // !!! TODO: throw here?
}
diff --git a/services/core/java/com/android/server/wm/InputManagerCallback.java b/services/core/java/com/android/server/wm/InputManagerCallback.java
index e166bfc..0978636 100644
--- a/services/core/java/com/android/server/wm/InputManagerCallback.java
+++ b/services/core/java/com/android/server/wm/InputManagerCallback.java
@@ -24,6 +24,7 @@
import android.view.KeyEvent;
import android.view.WindowManager;
+import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.am.ActivityManagerService;
import com.android.server.input.InputManagerService;
import com.android.server.wm.EmbeddedWindowController.EmbeddedWindow;
@@ -252,7 +253,7 @@
// All the calls below need to happen without the WM lock held since they call into AM.
mService.mAtmInternal.saveANRState(reason);
- if (activity != null && activity.appToken != null) {
+ if (activity != null) {
// Notify the activity manager about the timeout and let it decide whether
// to abort dispatching or keep waiting.
final boolean abort = activity.keyDispatchingTimedOut(reason, windowPid);
@@ -410,6 +411,8 @@
requestRefreshConfiguration = dispatchPointerCaptureChanged(focusedWindow, false);
}
mFocusedWindow.set(newFocusedWindow);
+ mService.mH.sendMessage(PooledLambda.obtainMessage(mService::reportFocusChanged,
+ oldToken, newToken));
return requestRefreshConfiguration;
}
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index fb511e0..4efd687 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -370,7 +370,8 @@
* Layer assignment is assumed to be complete by the time this is called.
*/
public void setInputFocusLw(WindowState newWindow, boolean updateInputWindows) {
- ProtoLog.d(WM_DEBUG_FOCUS_LIGHT, "Input focus has changed to %s", newWindow);
+ ProtoLog.v(WM_DEBUG_FOCUS_LIGHT, "Input focus has changed to %s display=%d",
+ newWindow, mDisplayId);
if (newWindow != mInputFocus) {
if (newWindow != null && newWindow.canReceiveKeys()) {
@@ -493,7 +494,7 @@
final int type = w.mAttrs.type;
final boolean isVisible = w.isVisibleLw();
if (inputChannel == null || inputWindowHandle == null || w.mRemoved
- || (w.cantReceiveTouchInput() && !shouldApplyRecentsInputConsumer)) {
+ || (!w.canReceiveTouchInput() && !shouldApplyRecentsInputConsumer)) {
if (w.mWinAnimator.hasSurface()) {
// Assign an InputInfo with type to the overlay window which can't receive input
// event. This is used to omit Surfaces from occlusion detection.
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 21e30ce..6182a55 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -40,7 +40,6 @@
import static android.view.WindowManager.TRANSIT_NONE;
import static android.view.WindowManager.TRANSIT_SHOW_SINGLE_TASK_DISPLAY;
import static android.view.WindowManager.TRANSIT_TASK_TO_BACK;
-
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_KEEP_SCREEN_ON;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION;
@@ -90,7 +89,6 @@
import static com.android.server.wm.WindowSurfacePlacer.SET_ORIENTATION_CHANGE_COMPLETE;
import static com.android.server.wm.WindowSurfacePlacer.SET_UPDATE_ROTATION;
import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_ACTION_PENDING;
-
import static java.lang.Integer.MAX_VALUE;
import android.annotation.IntDef;
@@ -129,6 +127,7 @@
import android.os.storage.StorageManager;
import android.provider.Settings;
import android.service.voice.IVoiceInteractionSession;
+import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.DisplayMetrics;
import android.util.IntArray;
@@ -162,7 +161,6 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
-import java.util.HashMap;
import java.util.List;
import java.util.Objects;
import java.util.Set;
@@ -214,7 +212,7 @@
private int mTopFocusedDisplayId = INVALID_DISPLAY;
// Map from the PID to the top most app which has a focused window of the process.
- final HashMap<Integer, ActivityRecord> mTopFocusedAppByProcess = new HashMap<>();
+ final ArrayMap<Integer, ActivityRecord> mTopFocusedAppByProcess = new ArrayMap<>();
// Only a separate transaction until we separate the apply surface changes
// transaction from the global transaction.
@@ -480,8 +478,7 @@
mTopFocusedDisplayId = topFocusedDisplayId;
mWmService.mInputManager.setFocusedDisplay(topFocusedDisplayId);
mWmService.mPolicy.setTopFocusedDisplay(topFocusedDisplayId);
- ProtoLog.v(WM_DEBUG_FOCUS_LIGHT, "New topFocusedDisplayId=%d",
- topFocusedDisplayId);
+ ProtoLog.d(WM_DEBUG_FOCUS_LIGHT, "New topFocusedDisplayId=%d", topFocusedDisplayId);
}
return changed;
}
@@ -2289,10 +2286,6 @@
for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
final DisplayContent display = getChildAt(displayNdx);
- if (display.shouldSleep()) {
- continue;
- }
-
final boolean curResult = result;
boolean resumedOnDisplay = display.reduceOnAllTaskDisplayAreas(
(taskDisplayArea, resumed) -> {
diff --git a/services/core/java/com/android/server/wm/SurfaceAnimator.java b/services/core/java/com/android/server/wm/SurfaceAnimator.java
index 33935d6..7df2b40 100644
--- a/services/core/java/com/android/server/wm/SurfaceAnimator.java
+++ b/services/core/java/com/android/server/wm/SurfaceAnimator.java
@@ -26,6 +26,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.util.DebugUtils;
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
import android.view.SurfaceControl;
@@ -429,7 +430,8 @@
void dump(PrintWriter pw, String prefix) {
pw.print(prefix); pw.print("mLeash="); pw.print(mLeash);
- pw.print(" mAnimationType=" + mAnimationType);
+ pw.print(" mAnimationType=" + DebugUtils.valueToString(SurfaceAnimator.class,
+ "ANIMATION_TYPE_", mAnimationType));
pw.println(mAnimationStartDelayed ? " mAnimationStartDelayed=true" : "");
pw.print(prefix); pw.print("Animation: "); pw.println(mAnimation);
if (mAnimation != null) {
@@ -442,56 +444,56 @@
* No animation is specified.
* @hide
*/
- static final int ANIMATION_TYPE_NONE = 0;
+ public static final int ANIMATION_TYPE_NONE = 0;
/**
* Animation for an app transition.
* @hide
*/
- static final int ANIMATION_TYPE_APP_TRANSITION = 1;
+ public static final int ANIMATION_TYPE_APP_TRANSITION = 1;
/**
* Animation for screen rotation.
* @hide
*/
- static final int ANIMATION_TYPE_SCREEN_ROTATION = 1 << 1;
+ public static final int ANIMATION_TYPE_SCREEN_ROTATION = 1 << 1;
/**
* Animation for dimming.
* @hide
*/
- static final int ANIMATION_TYPE_DIMMER = 1 << 2;
+ public static final int ANIMATION_TYPE_DIMMER = 1 << 2;
/**
* Animation for recent apps.
* @hide
*/
- static final int ANIMATION_TYPE_RECENTS = 1 << 3;
+ public static final int ANIMATION_TYPE_RECENTS = 1 << 3;
/**
* Animation for a {@link WindowState} without animating the activity.
* @hide
*/
- static final int ANIMATION_TYPE_WINDOW_ANIMATION = 1 << 4;
+ public static final int ANIMATION_TYPE_WINDOW_ANIMATION = 1 << 4;
/**
* Animation to control insets. This is actually not an animation, but is used to give the
* client a leash over the system window causing insets.
* @hide
*/
- static final int ANIMATION_TYPE_INSETS_CONTROL = 1 << 5;
+ public static final int ANIMATION_TYPE_INSETS_CONTROL = 1 << 5;
/**
* Animation when a fixed rotation transform is applied to a window token.
* @hide
*/
- static final int ANIMATION_TYPE_FIXED_TRANSFORM = 1 << 6;
+ public static final int ANIMATION_TYPE_FIXED_TRANSFORM = 1 << 6;
/**
* Bitmask to include all animation types. This is NOT an {@link AnimationType}
* @hide
*/
- static final int ANIMATION_TYPE_ALL = -1;
+ public static final int ANIMATION_TYPE_ALL = -1;
/**
* The type of the animation.
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 19bf451..bfaaf46 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -6348,7 +6348,7 @@
return mRootWindowContainer.resumeHomeActivity(prev, reason, getDisplayArea());
}
- void startActivityLocked(ActivityRecord r, ActivityRecord focusedTopActivity,
+ void startActivityLocked(ActivityRecord r, @Nullable ActivityRecord focusedTopActivity,
boolean newTask, boolean keepCurTransition, ActivityOptions options) {
Task rTask = r.getTask();
final boolean allowMoveToFront = options == null || !options.getAvoidMoveToFront();
@@ -7585,7 +7585,11 @@
// Do not sleep activities in this stack if we're marked as focused and the keyguard
// is in the process of going away.
if (isFocusedStackOnDisplay()
- && mStackSupervisor.getKeyguardController().isKeyguardGoingAway()) {
+ && mStackSupervisor.getKeyguardController().isKeyguardGoingAway()
+ // Avoid resuming activities on secondary displays since we don't want bubble
+ // activities to be resumed while bubble is still collapsed.
+ // TODO(b/113840485): Having keyguard going away state for secondary displays.
+ && display.isDefaultDisplay) {
return false;
}
diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java
index 1b779c6..63a595e 100644
--- a/services/core/java/com/android/server/wm/TaskOrganizerController.java
+++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java
@@ -38,6 +38,7 @@
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Slog;
+import android.util.SparseBooleanArray;
import android.view.SurfaceControl;
import android.window.ITaskOrganizer;
import android.window.ITaskOrganizerController;
@@ -50,6 +51,7 @@
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
@@ -206,7 +208,6 @@
private final DeathRecipient mDeathRecipient;
private final ArrayList<Task> mOrganizedTasks = new ArrayList<>();
private final int mUid;
- private boolean mInterceptBackPressedOnTaskRoot;
TaskOrganizerState(ITaskOrganizer organizer, int uid) {
final Consumer<Runnable> deferTaskOrgCallbacksConsumer =
@@ -224,10 +225,6 @@
mUid = uid;
}
- void setInterceptBackPressedOnTaskRoot(boolean interceptBackPressed) {
- mInterceptBackPressedOnTaskRoot = interceptBackPressed;
- }
-
void addTask(Task t) {
if (t.mTaskAppearedSent) return;
@@ -247,6 +244,7 @@
mOrganizer.onTaskVanished(t);
}
mOrganizedTasks.remove(t);
+ mInterceptBackPressedOnRootTasks.remove(t.mTaskId);
}
void dispose() {
@@ -278,6 +276,8 @@
private final HashMap<IBinder, TaskOrganizerState> mTaskOrganizerStates = new HashMap<>();
private final WeakHashMap<Task, RunningTaskInfo> mLastSentTaskInfos = new WeakHashMap<>();
private final ArrayList<Task> mPendingTaskInfoChanges = new ArrayList<>();
+ // Set of organized tasks (by taskId) that dispatch back pressed to their organizers
+ private final HashSet<Integer> mInterceptBackPressedOnRootTasks = new HashSet();
private final ActivityTaskManagerService mService;
@@ -623,7 +623,7 @@
}
@Override
- public void setInterceptBackPressedOnTaskRoot(ITaskOrganizer organizer,
+ public void setInterceptBackPressedOnTaskRoot(WindowContainerToken token,
boolean interceptBackPressed) {
enforceStackPermission("setInterceptBackPressedOnTaskRoot()");
final long origId = Binder.clearCallingIdentity();
@@ -631,9 +631,15 @@
synchronized (mGlobalLock) {
ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Set intercept back pressed on root=%b",
interceptBackPressed);
- final TaskOrganizerState state = mTaskOrganizerStates.get(organizer.asBinder());
- if (state != null) {
- state.setInterceptBackPressedOnTaskRoot(interceptBackPressed);
+ final Task task = WindowContainer.fromBinder(token.asBinder()).asTask();
+ if (task == null) {
+ Slog.w(TAG, "Could not resolve task from token");
+ return;
+ }
+ if (interceptBackPressed) {
+ mInterceptBackPressedOnRootTasks.add(task.mTaskId);
+ } else {
+ mInterceptBackPressedOnRootTasks.remove(task.mTaskId);
}
}
} finally {
@@ -642,15 +648,12 @@
}
public boolean handleInterceptBackPressedOnTaskRoot(Task task) {
- if (task == null || !task.isOrganized()) {
+ if (task == null || !task.isOrganized()
+ || !mInterceptBackPressedOnRootTasks.contains(task.mTaskId)) {
return false;
}
final TaskOrganizerState state = mTaskOrganizerStates.get(task.mTaskOrganizer.asBinder());
- if (!state.mInterceptBackPressedOnTaskRoot) {
- return false;
- }
-
state.mOrganizer.onBackPressedOnTaskRoot(task);
return true;
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index c45ccb6..19179a8 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -376,8 +376,11 @@
private static final String BOOT_ANIMATION_SERVICE = "bootanim";
static final int UPDATE_FOCUS_NORMAL = 0;
+ /** Caller will assign layers */
static final int UPDATE_FOCUS_WILL_ASSIGN_LAYERS = 1;
+ /** Caller is performing surface placement */
static final int UPDATE_FOCUS_PLACING_SURFACES = 2;
+ /** Caller will performSurfacePlacement */
static final int UPDATE_FOCUS_WILL_PLACE_SURFACES = 3;
/** Indicates we are removing the focused window when updating the focus. */
static final int UPDATE_FOCUS_REMOVING_FOCUS = 4;
@@ -4730,12 +4733,30 @@
return false;
}
+ void reportFocusChanged(IBinder oldToken, IBinder newToken) {
+ WindowState lastFocus;
+ WindowState newFocus;
+ synchronized (mGlobalLock) {
+ lastFocus = mInputToWindowMap.get(oldToken);
+ newFocus = mInputToWindowMap.get(newToken);
+ ProtoLog.i(WM_DEBUG_FOCUS_LIGHT, "Focus changing: %s -> %s", lastFocus, newFocus);
+ }
+
+ if (newFocus != null) {
+ newFocus.reportFocusChangedSerialized(true);
+ notifyFocusChanged();
+ }
+
+ if (lastFocus != null) {
+ lastFocus.reportFocusChangedSerialized(false);
+ }
+ }
+
// -------------------------------------------------------------
// Async Handler
// -------------------------------------------------------------
final class H extends android.os.Handler {
- public static final int REPORT_FOCUS_CHANGE = 2;
public static final int WINDOW_FREEZE_TIMEOUT = 11;
public static final int PERSIST_ANIMATION_SCALE = 14;
@@ -4788,50 +4809,6 @@
Slog.v(TAG_WM, "handleMessage: entry what=" + msg.what);
}
switch (msg.what) {
- case REPORT_FOCUS_CHANGE: {
- final DisplayContent displayContent = (DisplayContent) msg.obj;
- WindowState lastFocus;
- WindowState newFocus;
-
- AccessibilityController accessibilityController = null;
-
- synchronized (mGlobalLock) {
- if (mAccessibilityController != null) {
- accessibilityController = mAccessibilityController;
- }
-
- lastFocus = displayContent.mLastFocus;
- newFocus = displayContent.mCurrentFocus;
- if (lastFocus == newFocus) {
- // Focus is not changing, so nothing to do.
- return;
- }
- displayContent.mLastFocus = newFocus;
- ProtoLog.i(WM_DEBUG_FOCUS_LIGHT, "Focus moving from %s"
- + " to %s displayId=%d", lastFocus, newFocus,
- displayContent.getDisplayId());
- }
-
- // First notify the accessibility manager for the change so it has
- // the windows before the newly focused one starts firing events.
- if (accessibilityController != null) {
- accessibilityController.onWindowFocusChangedNotLocked(
- displayContent.getDisplayId());
- }
-
- if (newFocus != null) {
- ProtoLog.i(WM_DEBUG_FOCUS_LIGHT, "Gaining focus: %s", newFocus);
- newFocus.reportFocusChangedSerialized(true);
- notifyFocusChanged();
- }
-
- if (lastFocus != null) {
- ProtoLog.i(WM_DEBUG_FOCUS_LIGHT, "Losing focus: %s", lastFocus);
- lastFocus.reportFocusChangedSerialized(false);
- }
- break;
- }
-
case WINDOW_FREEZE_TIMEOUT: {
final DisplayContent displayContent = (DisplayContent) msg.obj;
synchronized (mGlobalLock) {
@@ -7994,6 +7971,8 @@
return;
}
+ ProtoLog.i(WM_DEBUG_FOCUS_LIGHT, "onPointerDownOutsideFocusLocked called on %s",
+ touchedWindow);
final DisplayContent displayContent = touchedWindow.getDisplayContent();
if (!displayContent.isOnTop()) {
displayContent.getParent().positionChildAt(WindowContainer.POSITION_TOP, displayContent,
@@ -8022,10 +8001,7 @@
}
}
- try {
- mActivityTaskManager.setFocusedTask(task.mTaskId);
- } catch (RemoteException e) {
- }
+ mAtmService.setFocusedTask(task.mTaskId);
}
/**
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 9ff33b1..84a9c75 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -2884,12 +2884,25 @@
return canReceiveKeys(false /* fromUserTouch */);
}
+ public String canReceiveKeysReason(boolean fromUserTouch) {
+ return "fromTouch= " + fromUserTouch
+ + " isVisibleOrAdding=" + isVisibleOrAdding()
+ + " mViewVisibility=" + mViewVisibility
+ + " mRemoveOnExit=" + mRemoveOnExit
+ + " flags=" + mAttrs.flags
+ + " appWindowsAreFocusable="
+ + (mActivityRecord == null || mActivityRecord.windowsAreFocusable(fromUserTouch))
+ + " canReceiveTouchInput=" + canReceiveTouchInput()
+ + " displayIsOnTop=" + getDisplayContent().isOnTop()
+ + " displayIsTrusted=" + getDisplayContent().isTrusted();
+ }
+
public boolean canReceiveKeys(boolean fromUserTouch) {
final boolean canReceiveKeys = isVisibleOrAdding()
&& (mViewVisibility == View.VISIBLE) && !mRemoveOnExit
&& ((mAttrs.flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) == 0)
&& (mActivityRecord == null || mActivityRecord.windowsAreFocusable(fromUserTouch))
- && !cantReceiveTouchInput();
+ && canReceiveTouchInput();
if (!canReceiveKeys) {
return false;
}
@@ -2907,15 +2920,18 @@
return showBecauseOfActivity || showBecauseOfWindow;
}
- /** @return {@code false} if this window desires touch events. */
- boolean cantReceiveTouchInput() {
- if (mActivityRecord == null || mActivityRecord.getTask() == null) {
- return false;
+ /**
+ * @return {@code true} if this window can receive touches based on among other things,
+ * windowing state and recents animation state.
+ **/
+ boolean canReceiveTouchInput() {
+ if (mActivityRecord == null || mActivityRecord.getTask() == null) {
+ return true;
}
- return mActivityRecord.getTask().getRootTask().shouldIgnoreInput()
- || !mActivityRecord.mVisibleRequested
- || isRecentsAnimationConsumingAppInput();
+ return !mActivityRecord.getTask().getRootTask().shouldIgnoreInput()
+ && mActivityRecord.mVisibleRequested
+ && !isRecentsAnimationConsumingAppInput();
}
/**
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 22e309c..8045583 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -5782,9 +5782,6 @@
if (!mHasFeature) {
return;
}
- final CallerIdentity identity = getCallerIdentity();
- Preconditions.checkCallAuthorization(isSystemUid(identity) || isRootUid(identity)
- || hasCallingOrSelfPermission(permission.INTERACT_ACROSS_USERS_FULL));
final ActiveAdmin admin;
synchronized (getLockObject()) {
@@ -9438,8 +9435,7 @@
Preconditions.checkCallAuthorization(isDeviceOwner(identity));
return mInjector.binderWithCleanCallingIdentity(() -> {
- final List<UserInfo> userInfos = mInjector.getUserManager().getUsers(true
- /*excludeDying*/);
+ final List<UserInfo> userInfos = mInjector.getUserManager().getAliveUsers();
final List<UserHandle> userHandles = new ArrayList<>();
for (UserInfo userInfo : userInfos) {
UserHandle userHandle = userInfo.getUserHandle();
@@ -10362,7 +10358,7 @@
private void maybeClearLockTaskPolicyLocked() {
mInjector.binderWithCleanCallingIdentity(() -> {
- final List<UserInfo> userInfos = mUserManager.getUsers(/*excludeDying=*/ true);
+ final List<UserInfo> userInfos = mUserManager.getAliveUsers();
for (int i = userInfos.size() - 1; i >= 0; i--) {
int userId = userInfos.get(i).id;
if (canUserUseLockTaskLocked(userId)) {
@@ -10849,7 +10845,7 @@
* them.
*/
void updateUserSetupCompleteAndPaired() {
- List<UserInfo> users = mUserManager.getUsers(true);
+ List<UserInfo> users = mUserManager.getAliveUsers();
final int N = users.size();
for (int i = 0; i < N; i++) {
int userHandle = users.get(i).id;
@@ -12052,14 +12048,6 @@
}
@Override
- public boolean isSystemOnlyUser(ComponentName admin) {
- Objects.requireNonNull(admin, "ComponentName is null");
- final CallerIdentity identity = getCallerIdentity(admin);
- Preconditions.checkCallAuthorization(isDeviceOwner(identity));
- return UserManager.isSplitSystemUser() && identity.getUserId() == UserHandle.USER_SYSTEM;
- }
-
- @Override
public void reboot(ComponentName admin) {
Objects.requireNonNull(admin, "ComponentName is null");
final CallerIdentity identity = getCallerIdentity(admin);
@@ -12579,7 +12567,7 @@
private boolean areAllUsersAffiliatedWithDeviceLocked() {
return mInjector.binderWithCleanCallingIdentity(() -> {
- final List<UserInfo> userInfos = mUserManager.getUsers(/*excludeDying=*/ true);
+ final List<UserInfo> userInfos = mUserManager.getAliveUsers();
for (int i = 0; i < userInfos.size(); i++) {
int userId = userInfos.get(i).id;
if (!isUserAffiliatedWithDeviceLocked(userId)) {
@@ -13048,7 +13036,7 @@
}
} else {
// Caller is the device owner: Look for profile owners that it can bind to.
- final List<UserInfo> userInfos = mUserManager.getUsers(/*excludeDying=*/ true);
+ final List<UserInfo> userInfos = mUserManager.getAliveUsers();
for (int i = 0; i < userInfos.size(); i++) {
final int userId = userInfos.get(i).id;
if (userId != callingUserId && canUserBindToDeviceOwnerLocked(userId)) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java b/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
index 3cdd482..7649af4 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
@@ -169,7 +169,7 @@
// First, try to read from the legacy file.
final File legacy = getLegacyConfigFile();
- final List<UserInfo> users = mUserManager.getUsers(true);
+ final List<UserInfo> users = mUserManager.getAliveUsers();
if (readLegacyOwnerFileLocked(legacy)) {
if (DEBUG) {
diff --git a/services/incremental/BinderIncrementalService.cpp b/services/incremental/BinderIncrementalService.cpp
index 41945a2..87ae4d7 100644
--- a/services/incremental/BinderIncrementalService.cpp
+++ b/services/incremental/BinderIncrementalService.cpp
@@ -237,6 +237,13 @@
return ok();
}
+binder::Status BinderIncrementalService::isFileFullyLoaded(int32_t storageId,
+ const std::string& path,
+ int32_t* _aidl_return) {
+ *_aidl_return = mImpl.isFileFullyLoaded(storageId, path);
+ return ok();
+}
+
binder::Status BinderIncrementalService::getLoadingProgress(int32_t storageId,
float* _aidl_return) {
*_aidl_return = mImpl.getLoadingProgress(storageId);
diff --git a/services/incremental/BinderIncrementalService.h b/services/incremental/BinderIncrementalService.h
index 8b40350..8478142 100644
--- a/services/incremental/BinderIncrementalService.h
+++ b/services/incremental/BinderIncrementalService.h
@@ -66,6 +66,8 @@
int32_t destStorageId, const std::string& destPath,
int32_t* _aidl_return) final;
binder::Status unlink(int32_t storageId, const std::string& path, int32_t* _aidl_return) final;
+ binder::Status isFileFullyLoaded(int32_t storageId, const std::string& path,
+ int32_t* _aidl_return) final;
binder::Status getLoadingProgress(int32_t storageId, float* _aidl_return) final;
binder::Status getMetadataByPath(int32_t storageId, const std::string& path,
std::vector<uint8_t>* _aidl_return) final;
diff --git a/services/incremental/IncrementalService.cpp b/services/incremental/IncrementalService.cpp
index 9836262e..447ee55 100644
--- a/services/incremental/IncrementalService.cpp
+++ b/services/incremental/IncrementalService.cpp
@@ -1603,7 +1603,8 @@
const auto writeFd = mIncFs->openForSpecialOps(ifs->control, libFileId);
if (!writeFd.ok()) {
- LOG(ERROR) << "Failed to open write fd for: " << targetLibPath << " errno: " << writeFd;
+ LOG(ERROR) << "Failed to open write fd for: " << targetLibPath
+ << " errno: " << writeFd.get();
return;
}
@@ -1673,6 +1674,37 @@
return mRunning;
}
+int IncrementalService::isFileFullyLoaded(StorageId storage, const std::string& path) const {
+ std::unique_lock l(mLock);
+ const auto ifs = getIfsLocked(storage);
+ if (!ifs) {
+ LOG(ERROR) << "isFileFullyLoaded failed, invalid storageId: " << storage;
+ return -EINVAL;
+ }
+ const auto storageInfo = ifs->storages.find(storage);
+ if (storageInfo == ifs->storages.end()) {
+ LOG(ERROR) << "isFileFullyLoaded failed, no storage: " << storage;
+ return -EINVAL;
+ }
+ l.unlock();
+ return isFileFullyLoadedFromPath(*ifs, path);
+}
+
+int IncrementalService::isFileFullyLoadedFromPath(const IncFsMount& ifs,
+ std::string_view filePath) const {
+ const auto [filledBlocks, totalBlocks] = mIncFs->countFilledBlocks(ifs.control, filePath);
+ if (filledBlocks < 0) {
+ LOG(ERROR) << "isFileFullyLoadedFromPath failed to get filled blocks count for: "
+ << filePath << " errno: " << filledBlocks;
+ return filledBlocks;
+ }
+ if (totalBlocks < filledBlocks) {
+ LOG(ERROR) << "isFileFullyLoadedFromPath failed to get total num of blocks";
+ return -EINVAL;
+ }
+ return totalBlocks - filledBlocks;
+}
+
float IncrementalService::getLoadingProgress(StorageId storage) const {
std::unique_lock l(mLock);
const auto ifs = getIfsLocked(storage);
diff --git a/services/incremental/IncrementalService.h b/services/incremental/IncrementalService.h
index cd6bfed..267458d 100644
--- a/services/incremental/IncrementalService.h
+++ b/services/incremental/IncrementalService.h
@@ -132,6 +132,7 @@
std::string_view newPath);
int unlink(StorageId storage, std::string_view path);
+ int isFileFullyLoaded(StorageId storage, const std::string& path) const;
float getLoadingProgress(StorageId storage) const;
RawMetadata getMetadata(StorageId storage, std::string_view path) const;
@@ -339,6 +340,7 @@
int makeDirs(const IncFsMount& ifs, StorageId storageId, std::string_view path, int mode);
binder::Status applyStorageParams(IncFsMount& ifs, bool enableReadLogs);
+ int isFileFullyLoadedFromPath(const IncFsMount& ifs, std::string_view filePath) const;
float getLoadingProgressFromPath(const IncFsMount& ifs, std::string_view path) const;
void registerAppOpsCallback(const std::string& packageName);
diff --git a/services/incremental/ServiceWrappers.cpp b/services/incremental/ServiceWrappers.cpp
index 1ed46c4..f6d89c5 100644
--- a/services/incremental/ServiceWrappers.cpp
+++ b/services/incremental/ServiceWrappers.cpp
@@ -195,8 +195,8 @@
ErrorCode unlink(const Control& control, std::string_view path) const final {
return incfs::unlink(control, path);
}
- base::unique_fd openForSpecialOps(const Control& control, FileId id) const final {
- return base::unique_fd{incfs::openForSpecialOps(control, id).release()};
+ incfs::UniqueFd openForSpecialOps(const Control& control, FileId id) const final {
+ return incfs::openForSpecialOps(control, id);
}
ErrorCode writeBlocks(std::span<const incfs::DataBlock> blocks) const final {
return incfs::writeBlocks({blocks.data(), size_t(blocks.size())});
diff --git a/services/incremental/ServiceWrappers.h b/services/incremental/ServiceWrappers.h
index 82a1704..6376d86 100644
--- a/services/incremental/ServiceWrappers.h
+++ b/services/incremental/ServiceWrappers.h
@@ -74,6 +74,7 @@
using Control = incfs::Control;
using FileId = incfs::FileId;
using ErrorCode = incfs::ErrorCode;
+ using UniqueFd = incfs::UniqueFd;
using WaitResult = incfs::WaitResult;
using ExistingMountCallback =
@@ -96,7 +97,7 @@
virtual ErrorCode link(const Control& control, std::string_view from,
std::string_view to) const = 0;
virtual ErrorCode unlink(const Control& control, std::string_view path) const = 0;
- virtual base::unique_fd openForSpecialOps(const Control& control, FileId id) const = 0;
+ virtual UniqueFd openForSpecialOps(const Control& control, FileId id) const = 0;
virtual ErrorCode writeBlocks(std::span<const incfs::DataBlock> blocks) const = 0;
virtual WaitResult waitForPendingReads(
const Control& control, std::chrono::milliseconds timeout,
diff --git a/services/incremental/test/IncrementalServiceTest.cpp b/services/incremental/test/IncrementalServiceTest.cpp
index d1000e56..a290a17 100644
--- a/services/incremental/test/IncrementalServiceTest.cpp
+++ b/services/incremental/test/IncrementalServiceTest.cpp
@@ -289,7 +289,7 @@
ErrorCode(const Control& control, std::string_view from,
std::string_view to));
MOCK_CONST_METHOD2(unlink, ErrorCode(const Control& control, std::string_view path));
- MOCK_CONST_METHOD2(openForSpecialOps, base::unique_fd(const Control& control, FileId id));
+ MOCK_CONST_METHOD2(openForSpecialOps, UniqueFd(const Control& control, FileId id));
MOCK_CONST_METHOD1(writeBlocks, ErrorCode(std::span<const DataBlock> blocks));
MOCK_CONST_METHOD3(waitForPendingReads,
WaitResult(const Control& control, std::chrono::milliseconds timeout,
@@ -304,6 +304,10 @@
ON_CALL(*this, countFilledBlocks(_, _)).WillByDefault(Return(std::make_pair(1, 2)));
}
+ void countFilledBlocksFullyLoaded() {
+ ON_CALL(*this, countFilledBlocks(_, _)).WillByDefault(Return(std::make_pair(10000, 10000)));
+ }
+
void countFilledBlocksFails() {
ON_CALL(*this, countFilledBlocks(_, _)).WillByDefault(Return(std::make_pair(-1, -1)));
}
@@ -1069,6 +1073,53 @@
ASSERT_EQ(res, 0);
}
+TEST_F(IncrementalServiceTest, testIsFileFullyLoadedFailsWithNoFile) {
+ mIncFs->countFilledBlocksFails();
+ mFs->hasNoFile();
+
+ TemporaryDir tempDir;
+ int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
+ IncrementalService::CreateOptions::CreateNew,
+ {}, {}, {});
+ ASSERT_EQ(-1, mIncrementalService->isFileFullyLoaded(storageId, "base.apk"));
+}
+
+TEST_F(IncrementalServiceTest, testIsFileFullyLoadedFailsWithFailedRanges) {
+ mIncFs->countFilledBlocksFails();
+ mFs->hasFiles();
+
+ TemporaryDir tempDir;
+ int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
+ IncrementalService::CreateOptions::CreateNew,
+ {}, {}, {});
+ EXPECT_CALL(*mIncFs, countFilledBlocks(_, _)).Times(1);
+ ASSERT_EQ(-1, mIncrementalService->isFileFullyLoaded(storageId, "base.apk"));
+}
+
+TEST_F(IncrementalServiceTest, testIsFileFullyLoadedSuccessWithEmptyRanges) {
+ mIncFs->countFilledBlocksEmpty();
+ mFs->hasFiles();
+
+ TemporaryDir tempDir;
+ int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
+ IncrementalService::CreateOptions::CreateNew,
+ {}, {}, {});
+ EXPECT_CALL(*mIncFs, countFilledBlocks(_, _)).Times(1);
+ ASSERT_EQ(0, mIncrementalService->isFileFullyLoaded(storageId, "base.apk"));
+}
+
+TEST_F(IncrementalServiceTest, testIsFileFullyLoadedSuccess) {
+ mIncFs->countFilledBlocksFullyLoaded();
+ mFs->hasFiles();
+
+ TemporaryDir tempDir;
+ int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
+ IncrementalService::CreateOptions::CreateNew,
+ {}, {}, {});
+ EXPECT_CALL(*mIncFs, countFilledBlocks(_, _)).Times(1);
+ ASSERT_EQ(0, mIncrementalService->isFileFullyLoaded(storageId, "base.apk"));
+}
+
TEST_F(IncrementalServiceTest, testGetLoadingProgressSuccessWithNoFile) {
mIncFs->countFilledBlocksSuccess();
mFs->hasNoFile();
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java b/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java
index b306ff0..431cc27 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java
@@ -16,7 +16,6 @@
package com.android.server.devicepolicy;
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
@@ -236,7 +235,7 @@
}
mUserInfos.add(uh);
when(userManager.getUsers()).thenReturn(mUserInfos);
- when(userManager.getUsers(anyBoolean())).thenReturn(mUserInfos);
+ when(userManager.getAliveUsers()).thenReturn(mUserInfos);
when(userManager.isUserRunning(eq(new UserHandle(userId)))).thenReturn(true);
when(userManager.getProfileParent(anyInt())).thenAnswer(
invocation -> {
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
index 99433a6..d7e431f 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
@@ -978,6 +978,7 @@
assertFalse(services.isSameUser(service, 0));
assertTrue(services.isSameUser(service, 10));
+ assertTrue(services.isSameUser(service, UserHandle.USER_ALL));
}
@Test
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationAssistantsTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationAssistantsTest.java
index ab4dc47..5796e84 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationAssistantsTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationAssistantsTest.java
@@ -103,7 +103,7 @@
when(mUm.getUserInfo(eq(user.id))).thenReturn(user);
}
when(mUm.getUsers()).thenReturn(users);
- when(mUm.getUsers(anyBoolean())).thenReturn(users);
+ when(mUm.getAliveUsers()).thenReturn(users);
IntArray profileIds = new IntArray();
profileIds.add(0);
profileIds.add(11);
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 9319bea..8644719 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -5058,7 +5058,7 @@
10, 10, r.getKey(), actionIndex, action, notificationVisibility,
generatedByAssistant);
verify(mAssistants).notifyAssistantActionClicked(
- eq(r.getSbn()), eq(actionIndex), eq(action), eq(generatedByAssistant));
+ eq(r.getSbn()), eq(action), eq(generatedByAssistant));
assertEquals(1, mNotificationRecordLogger.numCalls());
assertEquals(
@@ -5082,7 +5082,7 @@
10, 10, r.getKey(), actionIndex, action, notificationVisibility,
generatedByAssistant);
verify(mAssistants).notifyAssistantActionClicked(
- eq(r.getSbn()), eq(actionIndex), eq(action), eq(generatedByAssistant));
+ eq(r.getSbn()), eq(action), eq(generatedByAssistant));
assertEquals(1, mNotificationRecordLogger.numCalls());
assertEquals(
@@ -6948,4 +6948,63 @@
assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS + 1,
mService.getNotificationRecordCount());
}
+
+ @Test
+ public void testIsVisibleToListener_notEnabled() {
+ StatusBarNotification sbn = mock(StatusBarNotification.class);
+ when(sbn.getUserId()).thenReturn(10);
+ ManagedServices.ManagedServiceInfo info = mock(ManagedServices.ManagedServiceInfo.class);
+ ManagedServices.ManagedServiceInfo assistant = mock(ManagedServices.ManagedServiceInfo.class);
+ info.userid = 10;
+ when(info.isSameUser(anyInt())).thenReturn(true);
+ when(assistant.isSameUser(anyInt())).thenReturn(true);
+ when(info.enabledAndUserMatches(info.userid)).thenReturn(false);
+ when(mAssistants.checkServiceTokenLocked(any())).thenReturn(assistant);
+
+ assertFalse(mService.isVisibleToListener(sbn, info));
+ }
+
+ @Test
+ public void testIsVisibleToListener_noAssistant() {
+ StatusBarNotification sbn = mock(StatusBarNotification.class);
+ when(sbn.getUserId()).thenReturn(10);
+ ManagedServices.ManagedServiceInfo info = mock(ManagedServices.ManagedServiceInfo.class);
+ info.userid = 10;
+ when(info.isSameUser(anyInt())).thenReturn(true);
+ when(info.enabledAndUserMatches(info.userid)).thenReturn(true);
+ when(mAssistants.checkServiceTokenLocked(any())).thenReturn(null);
+
+ assertTrue(mService.isVisibleToListener(sbn, info));
+ }
+
+ @Test
+ public void testIsVisibleToListener_assistant_differentUser() {
+ StatusBarNotification sbn = mock(StatusBarNotification.class);
+ when(sbn.getUserId()).thenReturn(10);
+ ManagedServices.ManagedServiceInfo info = mock(ManagedServices.ManagedServiceInfo.class);
+ ManagedServices.ManagedServiceInfo assistant = mock(ManagedServices.ManagedServiceInfo.class);
+ info.userid = 0;
+ when(info.isSameUser(anyInt())).thenReturn(true);
+ when(assistant.isSameUser(anyInt())).thenReturn(true);
+ when(info.enabledAndUserMatches(info.userid)).thenReturn(true);
+ when(mAssistants.checkServiceTokenLocked(any())).thenReturn(assistant);
+
+ assertFalse(mService.isVisibleToListener(sbn, info));
+ }
+
+ @Test
+ public void testIsVisibleToListener_assistant_sameUser() {
+ StatusBarNotification sbn = mock(StatusBarNotification.class);
+ when(sbn.getUserId()).thenReturn(10);
+ ManagedServices.ManagedServiceInfo info = mock(ManagedServices.ManagedServiceInfo.class);
+ ManagedServices.ManagedServiceInfo assistant = mock(ManagedServices.ManagedServiceInfo.class);
+ info.userid = 10;
+ when(info.isSameUser(anyInt())).thenReturn(true);
+ when(assistant.isSameUser(anyInt())).thenReturn(true);
+ when(info.enabledAndUserMatches(info.userid)).thenReturn(true);
+ when(mAssistants.checkServiceTokenLocked(any())).thenReturn(assistant);
+
+ assertTrue(mService.isVisibleToListener(sbn, info));
+ }
+
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
index e2948a7..4cad397 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
@@ -1202,19 +1202,22 @@
@Test
public void testShouldSleepActivities() {
// When focused activity and keyguard is going away, we should not sleep regardless
- // of the display state
+ // of the display state, but keyguard-going-away should only take effects on default
+ // display since there is no keyguard on secondary displays (yet).
verifyShouldSleepActivities(true /* focusedStack */, true /*keyguardGoingAway*/,
- true /* displaySleeping */, false /* expected*/);
+ true /* displaySleeping */, true /* isDefaultDisplay */, false /* expected */);
+ verifyShouldSleepActivities(true /* focusedStack */, true /*keyguardGoingAway*/,
+ true /* displaySleeping */, false /* isDefaultDisplay */, true /* expected */);
// When not the focused stack, defer to display sleeping state.
verifyShouldSleepActivities(false /* focusedStack */, true /*keyguardGoingAway*/,
- true /* displaySleeping */, true /* expected*/);
+ true /* displaySleeping */, true /* isDefaultDisplay */, true /* expected */);
// If keyguard is going away, defer to the display sleeping state.
verifyShouldSleepActivities(true /* focusedStack */, false /*keyguardGoingAway*/,
- true /* displaySleeping */, true /* expected*/);
+ true /* displaySleeping */, true /* isDefaultDisplay */, true /* expected */);
verifyShouldSleepActivities(true /* focusedStack */, false /*keyguardGoingAway*/,
- false /* displaySleeping */, false /* expected*/);
+ false /* displaySleeping */, true /* isDefaultDisplay */, false /* expected */);
}
@Test
@@ -1423,9 +1426,11 @@
}
private void verifyShouldSleepActivities(boolean focusedStack,
- boolean keyguardGoingAway, boolean displaySleeping, boolean expected) {
+ boolean keyguardGoingAway, boolean displaySleeping, boolean isDefaultDisplay,
+ boolean expected) {
final DisplayContent display = mock(DisplayContent.class);
final KeyguardController keyguardController = mSupervisor.getKeyguardController();
+ display.isDefaultDisplay = isDefaultDisplay;
doReturn(display).when(mStack).getDisplay();
doReturn(keyguardGoingAway).when(keyguardController).isKeyguardGoingAway();
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
index b89d168..26b0bfb 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
@@ -915,24 +915,6 @@
assertEquals(taskDisplayArea.getTopStack(), taskDisplayArea.getRootHomeTask());
}
- @Test
- public void testResumeFocusedStackOnSleepingDisplay() {
- // Create an activity on secondary display.
- final TestDisplayContent secondDisplay = addNewDisplayContentAt(
- DisplayContent.POSITION_TOP);
- final Task stack = secondDisplay.getDefaultTaskDisplayArea()
- .createStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
- final ActivityRecord activity = new ActivityBuilder(mAtm).setStack(stack).build();
- spyOn(activity);
- spyOn(stack);
-
- // Cannot resumed activities on secondary display if the display should sleep.
- doReturn(true).when(secondDisplay).shouldSleep();
- mRootWindowContainer.resumeFocusedStacksTopActivities();
- verify(stack, never()).resumeTopActivityUncheckedLocked(any(), any());
- verify(activity, never()).makeActiveIfNeeded(any());
- }
-
/**
* Mock {@link RootWindowContainer#resolveHomeActivity} for returning consistent activity
* info for test cases.
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
index 289d54e..46a6a82 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
@@ -930,23 +930,36 @@
final Task stack = createStack();
final Task task = createTask(stack);
final ActivityRecord activity = createActivityRecordInTask(stack.mDisplayContent, task);
+ final Task stack2 = createStack();
+ final Task task2 = createTask(stack2);
+ final ActivityRecord activity2 = createActivityRecordInTask(stack.mDisplayContent, task2);
final ITaskOrganizer organizer = registerMockOrganizer();
// Setup the task to be controlled by the MW mode organizer
stack.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
+ stack2.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
assertTrue(stack.isOrganized());
+ assertTrue(stack2.isOrganized());
// Verify a back pressed does not call the organizer
mWm.mAtmService.onBackPressedOnTaskRoot(activity.token);
verify(organizer, never()).onBackPressedOnTaskRoot(any());
// Enable intercepting back
- mWm.mAtmService.mTaskOrganizerController.setInterceptBackPressedOnTaskRoot(organizer,
- true);
+ mWm.mAtmService.mTaskOrganizerController.setInterceptBackPressedOnTaskRoot(
+ stack.mRemoteToken.toWindowContainerToken(), true);
// Verify now that the back press does call the organizer
mWm.mAtmService.onBackPressedOnTaskRoot(activity.token);
verify(organizer, times(1)).onBackPressedOnTaskRoot(any());
+
+ // Disable intercepting back
+ mWm.mAtmService.mTaskOrganizerController.setInterceptBackPressedOnTaskRoot(
+ stack.mRemoteToken.toWindowContainerToken(), false);
+
+ // Verify now that the back press no longer calls the organizer
+ mWm.mAtmService.onBackPressedOnTaskRoot(activity.token);
+ verify(organizer, times(1)).onBackPressedOnTaskRoot(any());
}
@Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index 9603d28..3106ca2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -661,14 +661,14 @@
RecentsAnimationController recentsController = mock(RecentsAnimationController.class);
when(recentsController.shouldApplyInputConsumer(win0.mActivityRecord)).thenReturn(true);
mWm.setRecentsAnimationController(recentsController);
- assertTrue(win0.cantReceiveTouchInput());
+ assertFalse(win0.canReceiveTouchInput());
}
@Test
public void testCantReceiveTouchWhenAppTokenHiddenRequested() {
final WindowState win0 = createWindow(null, TYPE_APPLICATION, "win0");
win0.mActivityRecord.mVisibleRequested = false;
- assertTrue(win0.cantReceiveTouchInput());
+ assertFalse(win0.canReceiveTouchInput());
}
@Test
@@ -676,7 +676,7 @@
final WindowState win0 = createWindow(null, TYPE_APPLICATION, "win0");
win0.mActivityRecord.getStack().setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
win0.mActivityRecord.getStack().setFocusable(false);
- assertTrue(win0.cantReceiveTouchInput());
+ assertFalse(win0.canReceiveTouchInput());
}
@UseTestDisplay(addWindows = W_ACTIVITY)
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 81aad97..f151d9c 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -183,6 +183,7 @@
private static class ActivityData {
private final String mTaskRootPackage;
private final String mTaskRootClass;
+ public int lastEvent = Event.NONE;
private ActivityData(String taskRootPackage, String taskRootClass) {
mTaskRootPackage = taskRootPackage;
mTaskRootClass = taskRootClass;
@@ -785,6 +786,7 @@
switch (event.mEventType) {
case Event.ACTIVITY_RESUMED:
case Event.ACTIVITY_PAUSED:
+ case Event.ACTIVITY_STOPPED:
uid = mPackageManagerInternal.getPackageUid(event.mPackage, 0, userId);
break;
default:
@@ -817,8 +819,10 @@
.APP_USAGE_EVENT_OCCURRED__EVENT_TYPE__MOVE_TO_FOREGROUND);
// check if this activity has already been resumed
if (mVisibleActivities.get(event.mInstanceId) != null) break;
- mVisibleActivities.put(event.mInstanceId,
- new ActivityData(event.mTaskRootPackage, event.mTaskRootClass));
+ final ActivityData resumedData = new ActivityData(event.mTaskRootPackage,
+ event.mTaskRootClass);
+ resumedData.lastEvent = Event.ACTIVITY_RESUMED;
+ mVisibleActivities.put(event.mInstanceId, resumedData);
try {
switch(mUsageSource) {
case USAGE_SOURCE_CURRENT_ACTIVITY:
@@ -834,16 +838,17 @@
}
break;
case Event.ACTIVITY_PAUSED:
- if (event.mTaskRootPackage == null) {
- // Task Root info is missing. Repair the event based on previous data
- final ActivityData prevData = mVisibleActivities.get(event.mInstanceId);
- if (prevData == null) {
- Slog.w(TAG, "Unexpected activity event reported! (" + event.mPackage
- + "/" + event.mClass + " event : " + event.mEventType
- + " instanceId : " + event.mInstanceId + ")");
- } else {
- event.mTaskRootPackage = prevData.mTaskRootPackage;
- event.mTaskRootClass = prevData.mTaskRootClass;
+ final ActivityData pausedData = mVisibleActivities.get(event.mInstanceId);
+ if (pausedData == null) {
+ Slog.w(TAG, "Unexpected activity event reported! (" + event.mPackage
+ + "/" + event.mClass + " event : " + event.mEventType
+ + " instanceId : " + event.mInstanceId + ")");
+ } else {
+ pausedData.lastEvent = Event.ACTIVITY_PAUSED;
+ if (event.mTaskRootPackage == null) {
+ // Task Root info is missing. Repair the event based on previous data
+ event.mTaskRootPackage = pausedData.mTaskRootPackage;
+ event.mTaskRootClass = pausedData.mTaskRootClass;
}
}
FrameworkStatsLog.write(
@@ -866,6 +871,16 @@
return;
}
+ if (prevData.lastEvent != Event.ACTIVITY_PAUSED) {
+ FrameworkStatsLog.write(
+ FrameworkStatsLog.APP_USAGE_EVENT_OCCURRED,
+ uid,
+ event.mPackage,
+ event.mClass,
+ FrameworkStatsLog
+ .APP_USAGE_EVENT_OCCURRED__EVENT_TYPE__MOVE_TO_BACKGROUND);
+ }
+
ArraySet<String> tokens;
synchronized (mUsageReporters) {
tokens = mUsageReporters.removeReturnOld(event.mInstanceId);
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index a229efb..470d4be 100755
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -1678,6 +1678,15 @@
"hide_lte_plus_data_icon_bool";
/**
+ * The combined channel bandwidth threshold (non-inclusive) in KHz required to display the
+ * LTE+ data icon. It is 20000 by default, meaning the LTE+ icon will be shown if the device is
+ * using carrier aggregation and the combined channel bandwidth is strictly greater than 20 MHz.
+ * @hide
+ */
+ public static final String KEY_LTE_PLUS_THRESHOLD_BANDWIDTH_KHZ_INT =
+ "lte_plus_threshold_bandwidth_khz_int";
+
+ /**
* The string is used to filter redundant string from PLMN Network Name that's supplied by
* specific carrier.
*
@@ -4259,6 +4268,7 @@
sDefaults.putString(KEY_OPERATOR_NAME_FILTER_PATTERN_STRING, "");
sDefaults.putString(KEY_SHOW_CARRIER_DATA_ICON_PATTERN_STRING, "");
sDefaults.putBoolean(KEY_HIDE_LTE_PLUS_DATA_ICON_BOOL, true);
+ sDefaults.putInt(KEY_LTE_PLUS_THRESHOLD_BANDWIDTH_KHZ_INT, 20000);
sDefaults.putBoolean(KEY_NR_ENABLED_BOOL, true);
sDefaults.putBoolean(KEY_LTE_ENABLED_BOOL, true);
sDefaults.putBoolean(KEY_SUPPORT_TDSCDMA_BOOL, false);
diff --git a/tests/RollbackTest/Android.bp b/tests/RollbackTest/Android.bp
index 4f5a305..7dd003e 100644
--- a/tests/RollbackTest/Android.bp
+++ b/tests/RollbackTest/Android.bp
@@ -15,6 +15,7 @@
android_test {
name: "RollbackTest",
manifest: "RollbackTest/AndroidManifest.xml",
+ platform_apis: true,
srcs: ["RollbackTest/src/**/*.java"],
static_libs: ["androidx.test.rules", "cts-rollback-lib", "cts-install-lib"],
test_suites: ["general-tests"],
diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
index de51c5c..0db2b2a 100644
--- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
@@ -175,7 +175,7 @@
assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
UserManager um = (UserManager) context.getSystemService(context.USER_SERVICE);
- List<Integer> userIds = um.getUsers(true)
+ List<Integer> userIds = um.getAliveUsers()
.stream().map(user -> user.id).collect(Collectors.toList());
assertThat(InstallUtils.isOnlyInstalledForUser(TestApp.A,
context.getUserId(), userIds)).isTrue();
diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java
index aa3a139..9302f78 100644
--- a/wifi/java/android/net/wifi/ScanResult.java
+++ b/wifi/java/android/net/wifi/ScanResult.java
@@ -81,6 +81,12 @@
public String capabilities;
/**
+ * The interface name on which the scan result was received.
+ * @hide
+ */
+ public String ifaceName;
+
+ /**
* @hide
* No security protocol.
*/
@@ -939,6 +945,7 @@
flags = source.flags;
radioChainInfos = source.radioChainInfos;
this.mWifiStandard = source.mWifiStandard;
+ this.ifaceName = source.ifaceName;
}
}
@@ -977,6 +984,7 @@
sb.append(", 80211mcResponder: ");
sb.append(((flags & FLAG_80211mc_RESPONDER) != 0) ? "is supported" : "is not supported");
sb.append(", Radio Chain Infos: ").append(Arrays.toString(radioChainInfos));
+ sb.append(", interface name: ").append(ifaceName);
return sb.toString();
}
@@ -1056,6 +1064,7 @@
} else {
dest.writeInt(0);
}
+ dest.writeString((ifaceName != null) ? ifaceName.toString() : "");
}
/** Implement the Parcelable interface */
@@ -1134,6 +1143,7 @@
sr.radioChainInfos[i].level = in.readInt();
}
}
+ sr.ifaceName = in.readString();
return sr;
}
diff --git a/wifi/tests/src/android/net/wifi/ScanResultTest.java b/wifi/tests/src/android/net/wifi/ScanResultTest.java
index 5516f43..4a35868 100644
--- a/wifi/tests/src/android/net/wifi/ScanResultTest.java
+++ b/wifi/tests/src/android/net/wifi/ScanResultTest.java
@@ -44,6 +44,7 @@
public static final long TEST_TSF = 04660l;
public static final @WifiAnnotations.WifiStandard int TEST_WIFI_STANDARD =
ScanResult.WIFI_STANDARD_11AC;
+ public static final String TEST_IFACE_NAME = "test_ifname";
/**
* Frequency to channel map. This include some frequencies used outside the US.
@@ -219,7 +220,7 @@
+ "passpoint: no, ChannelBandwidth: 0, centerFreq0: 0, centerFreq1: 0, "
+ "standard: 11ac, "
+ "80211mcResponder: is not supported, "
- + "Radio Chain Infos: null", scanResult.toString());
+ + "Radio Chain Infos: null, interface name: test_ifname", scanResult.toString());
}
/**
@@ -242,7 +243,8 @@
+ "standard: 11ac, "
+ "80211mcResponder: is not supported, "
+ "Radio Chain Infos: [RadioChainInfo: id=0, level=-45, "
- + "RadioChainInfo: id=1, level=-54]", scanResult.toString());
+ + "RadioChainInfo: id=1, level=-54], interface name: test_ifname",
+ scanResult.toString());
}
/**
@@ -283,6 +285,8 @@
result.frequency = TEST_FREQUENCY;
result.timestamp = TEST_TSF;
result.setWifiStandard(TEST_WIFI_STANDARD);
+ result.ifaceName = TEST_IFACE_NAME;
+
return result;
}