summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/app/PropertyInvalidatedCache.java2
-rw-r--r--core/java/android/content/pm/PackageParser.java4
-rw-r--r--core/java/android/hardware/input/input_framework.aconfig9
-rw-r--r--core/java/android/os/IHintManager.aidl34
-rw-r--r--core/java/android/os/UserManager.java22
-rw-r--r--core/java/android/window/flags/lse_desktop_experience.aconfig7
-rw-r--r--core/java/com/android/internal/pm/pkg/parsing/ParsingPackageUtils.java4
-rw-r--r--core/java/com/android/server/pm/pkg/AndroidPackage.java2
-rw-r--r--core/jni/android_view_SurfaceControlActivePictureListener.cpp5
-rw-r--r--core/res/res/values/attrs_manifest.xml11
-rw-r--r--core/res/res/values/config_telephony.xml6
-rw-r--r--core/tests/coretests/src/android/app/PropertyInvalidatedCacheTests.java2
-rw-r--r--core/tests/coretests/src/android/os/IpcDataCacheTest.java2
-rw-r--r--data/etc/privapp-permissions-platform.xml4
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java4
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java4
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragPositioningCallback.java11
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java7
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometry.java5
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/FixedAspectRatioTaskPositionerDecorator.kt53
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositioner.java6
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.kt2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositioner.java6
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt6
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/FixedAspectRatioTaskPositionerDecoratorTests.kt59
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositionerTest.kt63
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositionerTest.kt24
-rw-r--r--media/java/android/media/MediaFormat.java18
-rw-r--r--native/android/performance_hint.cpp114
-rw-r--r--native/android/tests/performance_hint/PerformanceHintNativeTest.cpp35
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractorTest.kt3
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/ui/viewmodel/MediaControlViewModelTest.kt29
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ongoingcall/domain/interactor/OngoingCallInteractorTest.kt157
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaControlPanel.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaControlViewModel.kt11
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt14
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarModule.kt14
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/domain/interactor/OngoingCallInteractor.kt74
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaControlPanelTest.kt101
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileViewImplTest.kt24
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/gesture/SwipeStatusBarAwayGestureHandlerKosmos.kt25
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/ongoingcall/domain/interactor/OngoingCallInteractorKosmos.kt2
-rw-r--r--services/core/java/com/android/server/am/BroadcastController.java3
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java17
-rw-r--r--services/core/java/com/android/server/pm/RestrictionsSet.java8
-rw-r--r--services/core/java/com/android/server/pm/UserManagerService.java1
-rw-r--r--services/core/java/com/android/server/power/hint/HintManagerService.java62
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskSupervisor.java3
-rw-r--r--services/core/jni/Android.bp1
-rw-r--r--services/core/jni/com_android_server_UsbAlsaDevice.cpp70
-rw-r--r--services/core/jni/onload.cpp2
-rw-r--r--services/tests/performancehinttests/src/com/android/server/power/hint/HintManagerServiceTest.java99
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/UserManagerCacheTest.java172
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java51
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java184
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java119
-rw-r--r--services/usb/java/com/android/server/usb/UsbAlsaDevice.java6
-rw-r--r--services/usb/java/com/android/server/usb/flags/usb_flags.aconfig7
59 files changed, 1367 insertions, 443 deletions
diff --git a/core/java/android/app/PropertyInvalidatedCache.java b/core/java/android/app/PropertyInvalidatedCache.java
index c72c4c8feb71..5567c085d205 100644
--- a/core/java/android/app/PropertyInvalidatedCache.java
+++ b/core/java/android/app/PropertyInvalidatedCache.java
@@ -1356,7 +1356,7 @@ public class PropertyInvalidatedCache<Query, Result> {
@Nullable QueryHandler<Query, Result> computer) {
mPropertyName = createPropertyName(args.mModule, args.mApi);
mCacheName = cacheName;
- mCacheNullResults = args.mCacheNulls && Flags.picCacheNulls();
+ mCacheNullResults = args.mCacheNulls;
mNonce = getNonceHandler(mPropertyName);
mMaxEntries = args.mMaxEntries;
mCache = new CacheMap<>(args.mIsolateUids, args.mTestMode);
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 4b579e7db9f8..219b20428d7a 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -2322,10 +2322,10 @@ public class PackageParser {
} else if (tagName.equals(TAG_ADOPT_PERMISSIONS)) {
sa = res.obtainAttributes(parser,
- com.android.internal.R.styleable.AndroidManifestOriginalPackage);
+ com.android.internal.R.styleable.AndroidManifestAdoptPermissions);
String name = sa.getNonConfigurationString(
- com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0);
+ com.android.internal.R.styleable.AndroidManifestAdoptPermissions_name, 0);
sa.recycle();
diff --git a/core/java/android/hardware/input/input_framework.aconfig b/core/java/android/hardware/input/input_framework.aconfig
index aaa78aa0916a..313bad50e88e 100644
--- a/core/java/android/hardware/input/input_framework.aconfig
+++ b/core/java/android/hardware/input/input_framework.aconfig
@@ -196,4 +196,11 @@ flag {
namespace: "input"
description: "Allows the user to disable pointer acceleration for mouse and touchpads."
bug: "349006858"
-} \ No newline at end of file
+}
+
+flag {
+ name: "mouse_scrolling_acceleration"
+ namespace: "input"
+ description: "Allows the user to disable input scrolling acceleration for mouse."
+ bug: "383555305"
+}
diff --git a/core/java/android/os/IHintManager.aidl b/core/java/android/os/IHintManager.aidl
index 4a14a8d0faf8..56a089aff78a 100644
--- a/core/java/android/os/IHintManager.aidl
+++ b/core/java/android/os/IHintManager.aidl
@@ -21,11 +21,13 @@ import android.os.CpuHeadroomParamsInternal;
import android.os.GpuHeadroomParamsInternal;
import android.os.IHintSession;
import android.os.SessionCreationConfig;
-import android.hardware.power.CpuHeadroomResult;
+
import android.hardware.power.ChannelConfig;
+import android.hardware.power.CpuHeadroomResult;
import android.hardware.power.GpuHeadroomResult;
import android.hardware.power.SessionConfig;
import android.hardware.power.SessionTag;
+import android.hardware.power.SupportInfo;
/** {@hide} */
interface IHintManager {
@@ -40,11 +42,6 @@ interface IHintManager {
IHintSession createHintSessionWithConfig(in IBinder token, in SessionTag tag,
in SessionCreationConfig creationConfig, out SessionConfig config);
- /**
- * Get preferred rate limit in nanoseconds.
- */
- long getHintSessionPreferredRate();
-
void setHintSessionThreads(in IHintSession hintSession, in int[] tids);
int[] getHintSessionThreadIds(in IHintSession hintSession);
@@ -61,13 +58,28 @@ interface IHintManager {
long getGpuHeadroomMinIntervalMillis();
/**
- * Get Maximum number of graphics pipeline threads allowed per-app.
- */
- int getMaxGraphicsPipelineThreadsCount();
-
- /**
* Used by the JNI to pass an interface to the SessionManager;
* for internal use only.
*/
oneway void passSessionManagerBinder(in IBinder sessionManager);
+
+ parcelable HintManagerClientData {
+ int powerHalVersion;
+ int maxGraphicsPipelineThreads;
+ long preferredRateNanos;
+ SupportInfo supportInfo;
+ }
+
+ interface IHintManagerClient {
+ /**
+ * Returns FMQ channel information for the caller, which it associates to the callback binder lifespan.
+ */
+ oneway void receiveChannelConfig(in ChannelConfig config);
+ }
+
+ /**
+ * Set up an ADPF client, receiving a remote client binder interface and
+ * passing back a bundle of support and configuration information.
+ */
+ HintManagerClientData registerClient(in IHintManagerClient client);
}
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index b9f2cfcd8ca8..132805da7c94 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -4197,12 +4197,21 @@ public class UserManager {
android.Manifest.permission.MANAGE_USERS,
android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional = true)
private boolean hasUserRestrictionForUser(@NonNull @UserRestrictionKey String restrictionKey,
- @UserIdInt int userId) {
- try {
- return mService.hasUserRestriction(restrictionKey, userId);
- } catch (RemoteException re) {
- throw re.rethrowFromSystemServer();
- }
+ @NonNull @UserIdInt int userId) {
+ return getUserRestrictionFromQuery(new Pair(restrictionKey, userId));
+ }
+
+ /** @hide */
+ @CachedProperty()
+ private boolean getUserRestrictionFromQuery(@NonNull Pair<String, Integer> restrictionPerUser) {
+ return UserManagerCache.getUserRestrictionFromQuery(
+ (Pair<String, Integer> q) -> mService.hasUserRestriction(q.first, q.second),
+ restrictionPerUser);
+ }
+
+ /** @hide */
+ public static final void invalidateUserRestriction() {
+ UserManagerCache.invalidateUserRestrictionFromQuery();
}
/**
@@ -6477,6 +6486,7 @@ public class UserManager {
UserManagerCache.invalidateProfileParent();
}
invalidateEnabledProfileIds();
+ invalidateUserRestriction();
}
/**
diff --git a/core/java/android/window/flags/lse_desktop_experience.aconfig b/core/java/android/window/flags/lse_desktop_experience.aconfig
index 6caa20e29c17..1707e61b28e4 100644
--- a/core/java/android/window/flags/lse_desktop_experience.aconfig
+++ b/core/java/android/window/flags/lse_desktop_experience.aconfig
@@ -175,13 +175,6 @@ flag {
}
flag {
- name: "enable_a11y_metrics"
- namespace: "lse_desktop_experience"
- description: "Whether to enable log collection for a11y actions in desktop windowing mode"
- bug: "341319597"
-}
-
-flag {
name: "enable_caption_compat_inset_force_consumption"
namespace: "lse_desktop_experience"
description: "Enables force-consumption of caption bar insets for immersive apps in freeform"
diff --git a/core/java/com/android/internal/pm/pkg/parsing/ParsingPackageUtils.java b/core/java/com/android/internal/pm/pkg/parsing/ParsingPackageUtils.java
index c160b42f8b6b..5c08dc6be1a0 100644
--- a/core/java/com/android/internal/pm/pkg/parsing/ParsingPackageUtils.java
+++ b/core/java/com/android/internal/pm/pkg/parsing/ParsingPackageUtils.java
@@ -3133,9 +3133,9 @@ public class ParsingPackageUtils {
private static ParseResult<ParsingPackage> parseAdoptPermissions(ParseInput input,
ParsingPackage pkg, Resources res, XmlResourceParser parser) {
- TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestOriginalPackage);
+ TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestAdoptPermissions);
try {
- String name = nonConfigString(0, R.styleable.AndroidManifestOriginalPackage_name, sa);
+ String name = nonConfigString(0, R.styleable.AndroidManifestAdoptPermissions_name, sa);
if (name != null) {
pkg.addAdoptPermission(name);
}
diff --git a/core/java/com/android/server/pm/pkg/AndroidPackage.java b/core/java/com/android/server/pm/pkg/AndroidPackage.java
index 70dd10f2c371..5fa8125ced10 100644
--- a/core/java/com/android/server/pm/pkg/AndroidPackage.java
+++ b/core/java/com/android/server/pm/pkg/AndroidPackage.java
@@ -722,7 +722,7 @@ public interface AndroidPackage {
* The names of packages to adopt ownership of permissions from, parsed under {@link
* ParsingPackageUtils#TAG_ADOPT_PERMISSIONS}.
*
- * @see R.styleable#AndroidManifestOriginalPackage_name
+ * @see R.styleable#AndroidManifestAdoptPermissions_name
* @hide
*/
@NonNull
diff --git a/core/jni/android_view_SurfaceControlActivePictureListener.cpp b/core/jni/android_view_SurfaceControlActivePictureListener.cpp
index 91849c1514cc..15132db2a569 100644
--- a/core/jni/android_view_SurfaceControlActivePictureListener.cpp
+++ b/core/jni/android_view_SurfaceControlActivePictureListener.cpp
@@ -106,12 +106,11 @@ struct SurfaceControlActivePictureListener : public gui::BnActivePictureListener
}
status_t startListening() {
- // TODO(b/337330263): Make SF multiple-listener capable
- return SurfaceComposerClient::setActivePictureListener(this);
+ return SurfaceComposerClient::addActivePictureListener(this);
}
status_t stopListening() {
- return SurfaceComposerClient::setActivePictureListener(nullptr);
+ return SurfaceComposerClient::removeActivePictureListener(this);
}
protected:
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index a06d184fd147..8c6fd1dfc47e 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -2892,6 +2892,17 @@
<attr name="name" />
</declare-styleable>
+ <!-- Private tag to declare the package name that the permissions of this package
+ is based on. Only used for packages installed in the system image. If
+ given, the permissions from the other package will be propagated into the
+ new package.
+
+ <p>This appears as a child tag of the root
+ {@link #AndroidManifest manifest} tag. -->
+ <declare-styleable name="AndroidManifestAdoptPermissions" parent="AndroidManifest">
+ <attr name="name" />
+ </declare-styleable>
+
<!-- The <code>processes</code> tag specifies the processes the application will run code in
and optionally characteristics of those processes. This tag is optional; if not
specified, components will simply run in the processes they specify. If supplied,
diff --git a/core/res/res/values/config_telephony.xml b/core/res/res/values/config_telephony.xml
index 20ae29659783..666f1cf39fe3 100644
--- a/core/res/res/values/config_telephony.xml
+++ b/core/res/res/values/config_telephony.xml
@@ -506,4 +506,10 @@
<!-- Whether to allow TN scanning during satellite session. -->
<bool name="config_satellite_allow_tn_scanning_during_satellite_session">true</bool>
<java-symbol type="bool" name="config_satellite_allow_tn_scanning_during_satellite_session" />
+
+ <!-- List of integer tag Ids representing VZW satellite coverage. -->
+ <integer-array name="config_verizon_satellite_enabled_tagids">
+ </integer-array>
+ <java-symbol type="array" name="config_verizon_satellite_enabled_tagids" />
+
</resources>
diff --git a/core/tests/coretests/src/android/app/PropertyInvalidatedCacheTests.java b/core/tests/coretests/src/android/app/PropertyInvalidatedCacheTests.java
index bd273377984d..e9dfdd826572 100644
--- a/core/tests/coretests/src/android/app/PropertyInvalidatedCacheTests.java
+++ b/core/tests/coretests/src/android/app/PropertyInvalidatedCacheTests.java
@@ -16,7 +16,6 @@
package android.app;
-import static android.app.Flags.FLAG_PIC_CACHE_NULLS;
import static android.app.Flags.FLAG_PIC_ISOLATE_CACHE_BY_UID;
import static android.app.PropertyInvalidatedCache.NONCE_UNSET;
import static android.app.PropertyInvalidatedCache.MODULE_BLUETOOTH;
@@ -711,7 +710,6 @@ public class PropertyInvalidatedCacheTests {
}
}
- @RequiresFlagsEnabled(FLAG_PIC_CACHE_NULLS)
@Test
public void testCachingNulls() {
TestCache cache = new TestCache(new Args(MODULE_TEST)
diff --git a/core/tests/coretests/src/android/os/IpcDataCacheTest.java b/core/tests/coretests/src/android/os/IpcDataCacheTest.java
index bb8356f7aebe..fc04e6438ac6 100644
--- a/core/tests/coretests/src/android/os/IpcDataCacheTest.java
+++ b/core/tests/coretests/src/android/os/IpcDataCacheTest.java
@@ -16,7 +16,6 @@
package android.os;
-import static android.app.Flags.FLAG_PIC_CACHE_NULLS;
import static android.app.Flags.FLAG_PIC_ISOLATE_CACHE_BY_UID;
import static org.junit.Assert.assertEquals;
@@ -511,7 +510,6 @@ public class IpcDataCacheTest {
IpcDataCache.setTestMode(true);
}
- @RequiresFlagsEnabled(FLAG_PIC_CACHE_NULLS)
@Test
public void testCachingNulls() {
IpcDataCache.Config c =
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 2c542ec31a20..2398e7134b34 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -679,4 +679,8 @@ applications that come with the platform
<permission name="android.permission.BATTERY_STATS"/>
<permission name="android.permission.ENTER_TRADE_IN_MODE"/>
</privapp-permissions>
+
+ <privapp-permissions package="com.android.wm.shell">
+ <permission name="android.permission.SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE" />
+ </privapp-permissions>
</permissions>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
index 0b919668f7fe..792f5cad3418 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
@@ -468,7 +468,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel, FocusT
case MotionEvent.ACTION_DOWN: {
mDragPointerId = e.getPointerId(0);
mDragPositioningCallback.onDragPositioningStart(
- 0 /* ctrlType */, e.getRawX(0), e.getRawY(0));
+ 0 /* ctrlType */, e.getDisplayId(), e.getRawX(0), e.getRawY(0));
mIsDragging = false;
return false;
}
@@ -481,6 +481,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel, FocusT
if (decoration.isHandlingDragResize()) break;
final int dragPointerIdx = e.findPointerIndex(mDragPointerId);
mDragPositioningCallback.onDragPositioningMove(
+ e.getDisplayId(),
e.getRawX(dragPointerIdx), e.getRawY(dragPointerIdx));
mIsDragging = true;
return true;
@@ -492,6 +493,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel, FocusT
}
final int dragPointerIdx = e.findPointerIndex(mDragPointerId);
final Rect newTaskBounds = mDragPositioningCallback.onDragPositioningEnd(
+ e.getDisplayId(),
e.getRawX(dragPointerIdx), e.getRawY(dragPointerIdx));
DragPositioningCallbackUtility.snapTaskBoundsIfNecessary(newTaskBounds,
mWindowDecorByTaskId.get(mTaskId).calculateValidDragArea());
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
index 5a05861c3a88..7928e5ed4188 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
@@ -1140,7 +1140,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
if (dragAllowed) {
mDragPointerId = e.getPointerId(0);
final Rect initialBounds = mDragPositioningCallback.onDragPositioningStart(
- 0 /* ctrlType */, e.getRawX(0),
+ 0 /* ctrlType */, e.getDisplayId(), e.getRawX(0),
e.getRawY(0));
updateDragStatus(e.getActionMasked());
mOnDragStartInitialBounds.set(initialBounds);
@@ -1161,6 +1161,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
}
final int dragPointerIdx = e.findPointerIndex(mDragPointerId);
final Rect newTaskBounds = mDragPositioningCallback.onDragPositioningMove(
+ e.getDisplayId(),
e.getRawX(dragPointerIdx), e.getRawY(dragPointerIdx));
mDesktopTasksController.onDragPositioningMove(taskInfo,
decoration.mTaskSurface,
@@ -1191,6 +1192,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
(int) (e.getRawX(dragPointerIdx) - e.getX(dragPointerIdx)),
(int) (e.getRawY(dragPointerIdx) - e.getY(dragPointerIdx)));
final Rect newTaskBounds = mDragPositioningCallback.onDragPositioningEnd(
+ e.getDisplayId(),
e.getRawX(dragPointerIdx), e.getRawY(dragPointerIdx));
// Tasks bounds haven't actually been updated (only its leash), so pass to
// DesktopTasksController to allow secondary transformations (i.e. snap resizing
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragPositioningCallback.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragPositioningCallback.java
index 421ffd929fb2..3eebdb048f0d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragPositioningCallback.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragPositioningCallback.java
@@ -41,25 +41,30 @@ public interface DragPositioningCallback {
*
* @param ctrlType {@link CtrlType} indicating the direction of resizing, use
* {@code 0} to indicate it's a move
+ * @param displayId the ID of the display where the drag starts
* @param x x coordinate in window decoration coordinate system where the drag starts
* @param y y coordinate in window decoration coordinate system where the drag starts
* @return the starting task bounds
*/
- Rect onDragPositioningStart(@CtrlType int ctrlType, float x, float y);
+ Rect onDragPositioningStart(@CtrlType int ctrlType, int displayId, float x, float y);
/**
* Called when the pointer moves during a drag-resize or drag-move.
+ *
+ * @param displayId the ID of the display where the pointer is currently located
* @param x x coordinate in window decoration coordinate system of the new pointer location
* @param y y coordinate in window decoration coordinate system of the new pointer location
* @return the updated task bounds
*/
- Rect onDragPositioningMove(float x, float y);
+ Rect onDragPositioningMove(int displayId, float x, float y);
/**
* Called when a drag-resize or drag-move stops.
+ *
+ * @param displayId the ID of the display where the pointer is located when drag stops
* @param x x coordinate in window decoration coordinate system where the drag resize stops
* @param y y coordinate in window decoration coordinate system where the drag resize stops
* @return the final bounds for the dragged task
*/
- Rect onDragPositioningEnd(float x, float y);
+ Rect onDragPositioningEnd(int displayId, float x, float y);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java
index a6d503d0d991..7d1471f44674 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java
@@ -454,7 +454,7 @@ class DragResizeInputListener implements AutoCloseable {
ProtoLog.d(WM_SHELL_DESKTOP_MODE,
"%s: Handling action down, update ctrlType to %d", TAG, ctrlType);
mDragStartTaskBounds = mCallback.onDragPositioningStart(ctrlType,
- rawX, rawY);
+ e.getDisplayId(), rawX, rawY);
mLastMotionEventOnDown = e;
mResizeTrigger = (ctrlType == CTRL_TYPE_BOTTOM || ctrlType == CTRL_TYPE_TOP
|| ctrlType == CTRL_TYPE_RIGHT || ctrlType == CTRL_TYPE_LEFT)
@@ -489,7 +489,8 @@ class DragResizeInputListener implements AutoCloseable {
}
final float rawX = e.getRawX(dragPointerIndex);
final float rawY = e.getRawY(dragPointerIndex);
- final Rect taskBounds = mCallback.onDragPositioningMove(rawX, rawY);
+ final Rect taskBounds = mCallback.onDragPositioningMove(e.getDisplayId(),
+ rawX, rawY);
updateInputSinkRegionForDrag(taskBounds);
result = true;
break;
@@ -505,7 +506,7 @@ class DragResizeInputListener implements AutoCloseable {
TAG, e.getActionMasked());
break;
}
- final Rect taskBounds = mCallback.onDragPositioningEnd(
+ final Rect taskBounds = mCallback.onDragPositioningEnd(e.getDisplayId(),
e.getRawX(dragPointerIndex), e.getRawY(dragPointerIndex));
// If taskBounds has changed, setGeometry will be called and update the
// sink region. Otherwise, we should revert it here.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometry.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometry.java
index c8aff78cbb36..5b027f3c039e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometry.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometry.java
@@ -168,7 +168,10 @@ public final class DragResizeWindowGeometry {
return (e.getSource() & SOURCE_TOUCHSCREEN) == SOURCE_TOUCHSCREEN;
}
- static boolean isEdgeResizePermitted(@NonNull MotionEvent e) {
+ /**
+ * Whether resizing a window from the edge is permitted based on the motion event.
+ */
+ public static boolean isEdgeResizePermitted(@NonNull MotionEvent e) {
if (ENABLE_WINDOWING_EDGE_DRAG_RESIZE.isTrue()) {
return e.getToolType(0) == MotionEvent.TOOL_TYPE_STYLUS
|| e.getToolType(0) == MotionEvent.TOOL_TYPE_MOUSE
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/FixedAspectRatioTaskPositionerDecorator.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/FixedAspectRatioTaskPositionerDecorator.kt
index 3885761d0742..ab30d617af54 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/FixedAspectRatioTaskPositionerDecorator.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/FixedAspectRatioTaskPositionerDecorator.kt
@@ -47,10 +47,11 @@ class FixedAspectRatioTaskPositionerDecorator (
private var startingAspectRatio = 0f
private var isTaskPortrait = false
- override fun onDragPositioningStart(@CtrlType ctrlType: Int, x: Float, y: Float): Rect {
+ override fun onDragPositioningStart(
+ @CtrlType ctrlType: Int, displayId: Int, x: Float, y: Float): Rect {
originalCtrlType = ctrlType
if (!requiresFixedAspectRatio()) {
- return super.onDragPositioningStart(originalCtrlType, x, y)
+ return super.onDragPositioningStart(originalCtrlType, displayId, x, y)
}
lastRepositionedBounds.set(getBounds(windowDecoration.mTaskInfo))
@@ -72,27 +73,27 @@ class FixedAspectRatioTaskPositionerDecorator (
val verticalMidPoint = lastRepositionedBounds.top + (startingBoundHeight / 2)
edgeResizeCtrlType = originalCtrlType +
if (y < verticalMidPoint) CTRL_TYPE_TOP else CTRL_TYPE_BOTTOM
- super.onDragPositioningStart(edgeResizeCtrlType, x, y)
+ super.onDragPositioningStart(edgeResizeCtrlType, displayId, x, y)
}
CTRL_TYPE_TOP, CTRL_TYPE_BOTTOM -> {
val horizontalMidPoint = lastRepositionedBounds.left + (startingBoundWidth / 2)
edgeResizeCtrlType = originalCtrlType +
if (x < horizontalMidPoint) CTRL_TYPE_LEFT else CTRL_TYPE_RIGHT
- super.onDragPositioningStart(edgeResizeCtrlType, x, y)
+ super.onDragPositioningStart(edgeResizeCtrlType, displayId, x, y)
}
// If resize is corner resize, no alteration to the ctrlType needs to be made.
else -> {
edgeResizeCtrlType = CTRL_TYPE_UNDEFINED
- super.onDragPositioningStart(originalCtrlType, x, y)
+ super.onDragPositioningStart(originalCtrlType, displayId, x, y)
}
}
)
return lastRepositionedBounds
}
- override fun onDragPositioningMove(x: Float, y: Float): Rect {
+ override fun onDragPositioningMove(displayId: Int, x: Float, y: Float): Rect {
if (!requiresFixedAspectRatio()) {
- return super.onDragPositioningMove(x, y)
+ return super.onDragPositioningMove(displayId, x, y)
}
val diffX = x - lastValidPoint.x
@@ -103,7 +104,7 @@ class FixedAspectRatioTaskPositionerDecorator (
// Drag coordinate falls within valid region (90 - 180 degrees or 270- 360
// degrees from the corner the previous valid point). Allow resize with adjusted
// coordinates to maintain aspect ratio.
- lastRepositionedBounds.set(dragAdjustedMove(x, y))
+ lastRepositionedBounds.set(dragAdjustedMove(displayId, x, y))
}
}
CTRL_TYPE_BOTTOM + CTRL_TYPE_LEFT, CTRL_TYPE_TOP + CTRL_TYPE_RIGHT -> {
@@ -111,28 +112,28 @@ class FixedAspectRatioTaskPositionerDecorator (
// Drag coordinate falls within valid region (180 - 270 degrees or 0 - 90
// degrees from the corner the previous valid point). Allow resize with adjusted
// coordinates to maintain aspect ratio.
- lastRepositionedBounds.set(dragAdjustedMove(x, y))
+ lastRepositionedBounds.set(dragAdjustedMove(displayId, x, y))
}
}
CTRL_TYPE_LEFT, CTRL_TYPE_RIGHT -> {
// If resize is on left or right edge, always adjust the y coordinate.
val adjustedY = getScaledChangeForY(x)
lastValidPoint.set(x, adjustedY)
- lastRepositionedBounds.set(super.onDragPositioningMove(x, adjustedY))
+ lastRepositionedBounds.set(super.onDragPositioningMove(displayId, x, adjustedY))
}
CTRL_TYPE_TOP, CTRL_TYPE_BOTTOM -> {
// If resize is on top or bottom edge, always adjust the x coordinate.
val adjustedX = getScaledChangeForX(y)
lastValidPoint.set(adjustedX, y)
- lastRepositionedBounds.set(super.onDragPositioningMove(adjustedX, y))
+ lastRepositionedBounds.set(super.onDragPositioningMove(displayId, adjustedX, y))
}
}
return lastRepositionedBounds
}
- override fun onDragPositioningEnd(x: Float, y: Float): Rect {
+ override fun onDragPositioningEnd(displayId: Int, x: Float, y: Float): Rect {
if (!requiresFixedAspectRatio()) {
- return super.onDragPositioningEnd(x, y)
+ return super.onDragPositioningEnd(displayId, x, y)
}
val diffX = x - lastValidPoint.x
@@ -144,55 +145,55 @@ class FixedAspectRatioTaskPositionerDecorator (
// Drag coordinate falls within valid region (90 - 180 degrees or 270- 360
// degrees from the corner the previous valid point). End resize with adjusted
// coordinates to maintain aspect ratio.
- return dragAdjustedEnd(x, y)
+ return dragAdjustedEnd(displayId, x, y)
}
// If end of resize is not within valid region, end resize from last valid
// coordinates.
- return super.onDragPositioningEnd(lastValidPoint.x, lastValidPoint.y)
+ return super.onDragPositioningEnd(displayId, lastValidPoint.x, lastValidPoint.y)
}
CTRL_TYPE_BOTTOM + CTRL_TYPE_LEFT, CTRL_TYPE_TOP + CTRL_TYPE_RIGHT -> {
if ((diffX > 0 && diffY < 0) || (diffX < 0 && diffY > 0)) {
// Drag coordinate falls within valid region (180 - 260 degrees or 0 - 90
// degrees from the corner the previous valid point). End resize with adjusted
// coordinates to maintain aspect ratio.
- return dragAdjustedEnd(x, y)
+ return dragAdjustedEnd(displayId, x, y)
}
// If end of resize is not within valid region, end resize from last valid
// coordinates.
- return super.onDragPositioningEnd(lastValidPoint.x, lastValidPoint.y)
+ return super.onDragPositioningEnd(displayId, lastValidPoint.x, lastValidPoint.y)
}
CTRL_TYPE_LEFT, CTRL_TYPE_RIGHT -> {
// If resize is on left or right edge, always adjust the y coordinate.
- return super.onDragPositioningEnd(x, getScaledChangeForY(x))
+ return super.onDragPositioningEnd(displayId, x, getScaledChangeForY(x))
}
CTRL_TYPE_TOP, CTRL_TYPE_BOTTOM -> {
// If resize is on top or bottom edge, always adjust the x coordinate.
- return super.onDragPositioningEnd(getScaledChangeForX(y), y)
+ return super.onDragPositioningEnd(displayId, getScaledChangeForX(y), y)
}
else -> {
- return super.onDragPositioningEnd(x, y)
+ return super.onDragPositioningEnd(displayId, x, y)
}
}
}
- private fun dragAdjustedMove(x: Float, y: Float): Rect {
+ private fun dragAdjustedMove(displayId: Int, x: Float, y: Float): Rect {
val absDiffX = abs(x - lastValidPoint.x)
val absDiffY = abs(y - lastValidPoint.y)
if (absDiffY < absDiffX) {
lastValidPoint.set(getScaledChangeForX(y), y)
- return super.onDragPositioningMove(getScaledChangeForX(y), y)
+ return super.onDragPositioningMove(displayId, getScaledChangeForX(y), y)
}
lastValidPoint.set(x, getScaledChangeForY(x))
- return super.onDragPositioningMove(x, getScaledChangeForY(x))
+ return super.onDragPositioningMove(displayId, x, getScaledChangeForY(x))
}
- private fun dragAdjustedEnd(x: Float, y: Float): Rect {
+ private fun dragAdjustedEnd(displayId: Int, x: Float, y: Float): Rect {
val absDiffX = abs(x - lastValidPoint.x)
val absDiffY = abs(y - lastValidPoint.y)
if (absDiffY < absDiffX) {
- return super.onDragPositioningEnd(getScaledChangeForX(y), y)
+ return super.onDragPositioningEnd(displayId, getScaledChangeForX(y), y)
}
- return super.onDragPositioningEnd(x, getScaledChangeForY(x))
+ return super.onDragPositioningEnd(displayId, x, getScaledChangeForY(x))
}
/**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositioner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositioner.java
index 3efae9d6375a..2d6f7459e0ae 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositioner.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositioner.java
@@ -91,7 +91,7 @@ class FluidResizeTaskPositioner implements TaskPositioner, Transitions.Transitio
}
@Override
- public Rect onDragPositioningStart(int ctrlType, float x, float y) {
+ public Rect onDragPositioningStart(int ctrlType, int displayId, float x, float y) {
mCtrlType = ctrlType;
mTaskBoundsAtDragStart.set(
mWindowDecoration.mTaskInfo.configuration.windowConfiguration.getBounds());
@@ -117,7 +117,7 @@ class FluidResizeTaskPositioner implements TaskPositioner, Transitions.Transitio
}
@Override
- public Rect onDragPositioningMove(float x, float y) {
+ public Rect onDragPositioningMove(int displayId, float x, float y) {
final WindowContainerTransaction wct = new WindowContainerTransaction();
PointF delta = DragPositioningCallbackUtility.calculateDelta(x, y, mRepositionStartPoint);
if (isResizing() && DragPositioningCallbackUtility.changeBounds(mCtrlType,
@@ -147,7 +147,7 @@ class FluidResizeTaskPositioner implements TaskPositioner, Transitions.Transitio
}
@Override
- public Rect onDragPositioningEnd(float x, float y) {
+ public Rect onDragPositioningEnd(int displayId, float x, float y) {
// If task has been resized or task was dragged into area outside of
// mDisallowedAreaForEndBounds, apply WCT to finish it.
if (isResizing() && mHasDragResized) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.kt
index 159759ede368..bb19a2cc2ad4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.kt
@@ -694,7 +694,7 @@ class HandleMenu(
setTextColor(style.textColor)
compoundDrawableTintList = ColorStateList.valueOf(style.textColor)
}
-
+ openByDefaultBtn.isGone = isBrowserApp
openByDefaultBtn.imageTintList = ColorStateList.valueOf(style.textColor)
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositioner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositioner.java
index 1f03d7568130..e011cc08903b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositioner.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositioner.java
@@ -104,7 +104,7 @@ public class VeiledResizeTaskPositioner implements TaskPositioner, Transitions.T
}
@Override
- public Rect onDragPositioningStart(int ctrlType, float x, float y) {
+ public Rect onDragPositioningStart(int ctrlType, int displayId, float x, float y) {
mCtrlType = ctrlType;
mTaskBoundsAtDragStart.set(
mDesktopWindowDecoration.mTaskInfo.configuration.windowConfiguration.getBounds());
@@ -136,7 +136,7 @@ public class VeiledResizeTaskPositioner implements TaskPositioner, Transitions.T
}
@Override
- public Rect onDragPositioningMove(float x, float y) {
+ public Rect onDragPositioningMove(int displayId, float x, float y) {
if (Looper.myLooper() != mHandler.getLooper()) {
// This method must run on the shell main thread to use the correct Choreographer
// instance below.
@@ -170,7 +170,7 @@ public class VeiledResizeTaskPositioner implements TaskPositioner, Transitions.T
}
@Override
- public Rect onDragPositioningEnd(float x, float y) {
+ public Rect onDragPositioningEnd(int displayId, float x, float y) {
PointF delta = DragPositioningCallbackUtility.calculateDelta(x, y,
mRepositionStartPoint);
if (isResizing()) {
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt
index 0214da4660ad..aead0a7afb53 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt
@@ -1015,11 +1015,11 @@ class DesktopModeWindowDecorViewModelTests : DesktopModeWindowDecorViewModelTest
onCaptionButtonTouchListener = onTouchListenerCaptor
)
- whenever(mockTaskPositioner.onDragPositioningStart(any(), any(), any()))
+ whenever(mockTaskPositioner.onDragPositioningStart(any(), any(), any(), any()))
.thenReturn(INITIAL_BOUNDS)
- whenever(mockTaskPositioner.onDragPositioningMove(any(), any()))
+ whenever(mockTaskPositioner.onDragPositioningMove(any(), any(), any()))
.thenReturn(INITIAL_BOUNDS)
- whenever(mockTaskPositioner.onDragPositioningEnd(any(), any()))
+ whenever(mockTaskPositioner.onDragPositioningEnd(any(), any(), any()))
.thenReturn(INITIAL_BOUNDS)
val view = mock(View::class.java)
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/FixedAspectRatioTaskPositionerDecoratorTests.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/FixedAspectRatioTaskPositionerDecoratorTests.kt
index ce17c1df50bc..3c3d6b6bb258 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/FixedAspectRatioTaskPositionerDecoratorTests.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/FixedAspectRatioTaskPositionerDecoratorTests.kt
@@ -68,9 +68,9 @@ class FixedAspectRatioTaskPositionerDecoratorTests : ShellTestCase(){
configuration.windowConfiguration.setBounds(PORTRAIT_BOUNDS)
}
doReturn(PORTRAIT_BOUNDS).`when`(mockTaskPositioner).onDragPositioningStart(
- any(), any(), any())
- doReturn(Rect()).`when`(mockTaskPositioner).onDragPositioningMove(any(), any())
- doReturn(Rect()).`when`(mockTaskPositioner).onDragPositioningEnd(any(), any())
+ any(), any(), any(), any())
+ doReturn(Rect()).`when`(mockTaskPositioner).onDragPositioningMove(any(), any(), any())
+ doReturn(Rect()).`when`(mockTaskPositioner).onDragPositioningEnd(any(), any(), any())
decoratedTaskPositioner = spy(
FixedAspectRatioTaskPositionerDecorator(
mockDesktopWindowDecoration, mockTaskPositioner)
@@ -87,7 +87,8 @@ class FixedAspectRatioTaskPositionerDecoratorTests : ShellTestCase(){
isResizeable = testCase.isResizeable
}
- decoratedTaskPositioner.onDragPositioningStart(testCase.ctrlType, originalX, originalY)
+ decoratedTaskPositioner.onDragPositioningStart(
+ testCase.ctrlType, DISPLAY_ID, originalX, originalY)
val capturedValues = getLatestOnStartArguments()
assertThat(capturedValues.ctrlType).isEqualTo(testCase.ctrlType)
@@ -102,7 +103,8 @@ class FixedAspectRatioTaskPositionerDecoratorTests : ShellTestCase(){
val originalX = 0f
val originalY = 0f
- decoratedTaskPositioner.onDragPositioningStart(testCase.ctrlType, originalX, originalY)
+ decoratedTaskPositioner.onDragPositioningStart(
+ testCase.ctrlType, DISPLAY_ID, originalX, originalY)
val capturedValues = getLatestOnStartArguments()
assertThat(capturedValues.ctrlType).isEqualTo(testCase.ctrlType)
@@ -119,7 +121,7 @@ class FixedAspectRatioTaskPositionerDecoratorTests : ShellTestCase(){
testCase.ctrlType, testCase.additionalEdgeCtrlType, startingBounds)
decoratedTaskPositioner.onDragPositioningStart(
- testCase.ctrlType, startingPoint.x, startingPoint.y)
+ testCase.ctrlType, DISPLAY_ID, startingPoint.x, startingPoint.y)
val adjustedCtrlType = testCase.ctrlType + testCase.additionalEdgeCtrlType
val capturedValues = getLatestOnStartArguments()
@@ -134,13 +136,14 @@ class FixedAspectRatioTaskPositionerDecoratorTests : ShellTestCase(){
) {
val originalX = 0f
val originalY = 0f
- decoratedTaskPositioner.onDragPositioningStart(testCase.ctrlType, originalX, originalX)
+ decoratedTaskPositioner.onDragPositioningStart(
+ testCase.ctrlType, DISPLAY_ID, originalX, originalX)
mockDesktopWindowDecoration.mTaskInfo = ActivityManager.RunningTaskInfo().apply {
isResizeable = testCase.isResizeable
}
decoratedTaskPositioner.onDragPositioningMove(
- originalX + SMALL_DELTA, originalY + SMALL_DELTA)
+ DISPLAY_ID, originalX + SMALL_DELTA, originalY + SMALL_DELTA)
val capturedValues = getLatestOnMoveArguments()
assertThat(capturedValues.x).isEqualTo(originalX + SMALL_DELTA)
@@ -156,13 +159,14 @@ class FixedAspectRatioTaskPositionerDecoratorTests : ShellTestCase(){
val startingPoint = getCornerStartingPoint(testCase.ctrlType, startingBounds)
decoratedTaskPositioner.onDragPositioningStart(
- testCase.ctrlType, startingPoint.x, startingPoint.y)
+ testCase.ctrlType, DISPLAY_ID, startingPoint.x, startingPoint.y)
val updatedBounds = decoratedTaskPositioner.onDragPositioningMove(
+ DISPLAY_ID,
startingPoint.x + testCase.dragDelta.x,
startingPoint.y + testCase.dragDelta.y)
- verify(mockTaskPositioner, never()).onDragPositioningMove(any(), any())
+ verify(mockTaskPositioner, never()).onDragPositioningMove(any(), any(), any())
assertThat(updatedBounds).isEqualTo(startingBounds)
}
@@ -176,10 +180,12 @@ class FixedAspectRatioTaskPositionerDecoratorTests : ShellTestCase(){
val startingPoint = getCornerStartingPoint(testCase.ctrlType, startingBounds)
decoratedTaskPositioner.onDragPositioningStart(
- testCase.ctrlType, startingPoint.x, startingPoint.y)
+ testCase.ctrlType, DISPLAY_ID, startingPoint.x, startingPoint.y)
decoratedTaskPositioner.onDragPositioningMove(
- startingPoint.x + testCase.dragDelta.x, startingPoint.y + testCase.dragDelta.y)
+ DISPLAY_ID,
+ startingPoint.x + testCase.dragDelta.x,
+ startingPoint.y + testCase.dragDelta.y)
val adjustedDragDelta = calculateAdjustedDelta(
testCase.ctrlType, testCase.dragDelta, orientation)
@@ -202,9 +208,10 @@ class FixedAspectRatioTaskPositionerDecoratorTests : ShellTestCase(){
testCase.ctrlType, testCase.additionalEdgeCtrlType, startingBounds)
decoratedTaskPositioner.onDragPositioningStart(
- testCase.ctrlType, startingPoint.x, startingPoint.y)
+ testCase.ctrlType, DISPLAY_ID, startingPoint.x, startingPoint.y)
decoratedTaskPositioner.onDragPositioningMove(
+ DISPLAY_ID,
startingPoint.x + testCase.dragDelta.x,
startingPoint.y + testCase.dragDelta.y)
@@ -227,13 +234,14 @@ class FixedAspectRatioTaskPositionerDecoratorTests : ShellTestCase(){
) {
val originalX = 0f
val originalY = 0f
- decoratedTaskPositioner.onDragPositioningStart(testCase.ctrlType, originalX, originalX)
+ decoratedTaskPositioner.onDragPositioningStart(testCase.ctrlType, DISPLAY_ID,
+ originalX, originalX)
mockDesktopWindowDecoration.mTaskInfo = ActivityManager.RunningTaskInfo().apply {
isResizeable = testCase.isResizeable
}
decoratedTaskPositioner.onDragPositioningEnd(
- originalX + SMALL_DELTA, originalY + SMALL_DELTA)
+ DISPLAY_ID, originalX + SMALL_DELTA, originalY + SMALL_DELTA)
val capturedValues = getLatestOnEndArguments()
assertThat(capturedValues.x).isEqualTo(originalX + SMALL_DELTA)
@@ -249,9 +257,10 @@ class FixedAspectRatioTaskPositionerDecoratorTests : ShellTestCase(){
val startingPoint = getCornerStartingPoint(testCase.ctrlType, startingBounds)
decoratedTaskPositioner.onDragPositioningStart(
- testCase.ctrlType, startingPoint.x, startingPoint.y)
+ testCase.ctrlType, DISPLAY_ID, startingPoint.x, startingPoint.y)
decoratedTaskPositioner.onDragPositioningEnd(
+ DISPLAY_ID,
startingPoint.x + testCase.dragDelta.x,
startingPoint.y + testCase.dragDelta.y)
@@ -269,10 +278,12 @@ class FixedAspectRatioTaskPositionerDecoratorTests : ShellTestCase(){
val startingPoint = getCornerStartingPoint(testCase.ctrlType, startingBounds)
decoratedTaskPositioner.onDragPositioningStart(
- testCase.ctrlType, startingPoint.x, startingPoint.y)
+ testCase.ctrlType, DISPLAY_ID, startingPoint.x, startingPoint.y)
decoratedTaskPositioner.onDragPositioningEnd(
- startingPoint.x + testCase.dragDelta.x, startingPoint.y + testCase.dragDelta.y)
+ DISPLAY_ID,
+ startingPoint.x + testCase.dragDelta.x,
+ startingPoint.y + testCase.dragDelta.y)
val adjustedDragDelta = calculateAdjustedDelta(
testCase.ctrlType, testCase.dragDelta, orientation)
@@ -295,9 +306,10 @@ class FixedAspectRatioTaskPositionerDecoratorTests : ShellTestCase(){
testCase.ctrlType, testCase.additionalEdgeCtrlType, startingBounds)
decoratedTaskPositioner.onDragPositioningStart(
- testCase.ctrlType, startingPoint.x, startingPoint.y)
+ testCase.ctrlType, DISPLAY_ID, startingPoint.x, startingPoint.y)
decoratedTaskPositioner.onDragPositioningEnd(
+ DISPLAY_ID,
startingPoint.x + testCase.dragDelta.x,
startingPoint.y + testCase.dragDelta.y)
@@ -322,7 +334,7 @@ class FixedAspectRatioTaskPositionerDecoratorTests : ShellTestCase(){
val captorCtrlType = argumentCaptor<Int>()
val captorCoordinates = argumentCaptor<Float>()
verify(mockTaskPositioner).onDragPositioningStart(
- captorCtrlType.capture(), captorCoordinates.capture(), captorCoordinates.capture())
+ captorCtrlType.capture(), any(), captorCoordinates.capture(), captorCoordinates.capture())
return CtrlCoordinateCapture(captorCtrlType.firstValue, captorCoordinates.firstValue,
captorCoordinates.secondValue)
@@ -335,7 +347,7 @@ class FixedAspectRatioTaskPositionerDecoratorTests : ShellTestCase(){
private fun getLatestOnMoveArguments(): PointF {
val captorCoordinates = argumentCaptor<Float>()
verify(mockTaskPositioner).onDragPositioningMove(
- captorCoordinates.capture(), captorCoordinates.capture())
+ any(), captorCoordinates.capture(), captorCoordinates.capture())
return PointF(captorCoordinates.firstValue, captorCoordinates.secondValue)
}
@@ -347,7 +359,7 @@ class FixedAspectRatioTaskPositionerDecoratorTests : ShellTestCase(){
private fun getLatestOnEndArguments(): PointF {
val captorCoordinates = argumentCaptor<Float>()
verify(mockTaskPositioner).onDragPositioningEnd(
- captorCoordinates.capture(), captorCoordinates.capture())
+ any(), captorCoordinates.capture(), captorCoordinates.capture())
return PointF(captorCoordinates.firstValue, captorCoordinates.secondValue)
}
@@ -358,7 +370,7 @@ class FixedAspectRatioTaskPositionerDecoratorTests : ShellTestCase(){
private fun getAndMockBounds(orientation: Orientation): Rect {
val mockBounds = if (orientation.isPortrait) PORTRAIT_BOUNDS else LANDSCAPE_BOUNDS
doReturn(mockBounds).`when`(mockTaskPositioner).onDragPositioningStart(
- any(), any(), any())
+ any(), any(), any(), any())
doReturn(mockBounds).`when`(decoratedTaskPositioner).getBounds(any())
return mockBounds
}
@@ -458,6 +470,7 @@ class FixedAspectRatioTaskPositionerDecoratorTests : ShellTestCase(){
private val STARTING_ASPECT_RATIO = PORTRAIT_BOUNDS.height() / PORTRAIT_BOUNDS.width()
private const val LARGE_DELTA = 50f
private const val SMALL_DELTA = 30f
+ private const val DISPLAY_ID = 1
enum class Orientation(
val isPortrait: Boolean
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositionerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositionerTest.kt
index 3b80cb4936b9..cec52518edd2 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositionerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositionerTest.kt
@@ -150,11 +150,13 @@ class FluidResizeTaskPositionerTest : ShellTestCase() {
fun testDragResize_notMove_skipsTransitionOnEnd() {
taskPositioner.onDragPositioningStart(
CTRL_TYPE_TOP or CTRL_TYPE_RIGHT,
+ DISPLAY_ID,
STARTING_BOUNDS.left.toFloat(),
STARTING_BOUNDS.top.toFloat()
)
taskPositioner.onDragPositioningEnd(
+ DISPLAY_ID,
STARTING_BOUNDS.left.toFloat() + 10,
STARTING_BOUNDS.top.toFloat() + 10
)
@@ -171,11 +173,13 @@ class FluidResizeTaskPositionerTest : ShellTestCase() {
fun testDragResize_noEffectiveMove_skipsTransitionOnMoveAndEnd() {
taskPositioner.onDragPositioningStart(
CTRL_TYPE_TOP or CTRL_TYPE_RIGHT,
+ DISPLAY_ID,
STARTING_BOUNDS.left.toFloat(),
STARTING_BOUNDS.top.toFloat()
)
taskPositioner.onDragPositioningMove(
+ DISPLAY_ID,
STARTING_BOUNDS.left.toFloat(),
STARTING_BOUNDS.top.toFloat()
)
@@ -188,6 +192,7 @@ class FluidResizeTaskPositionerTest : ShellTestCase() {
})
taskPositioner.onDragPositioningEnd(
+ DISPLAY_ID,
STARTING_BOUNDS.left.toFloat() + 10,
STARTING_BOUNDS.top.toFloat() + 10
)
@@ -204,11 +209,13 @@ class FluidResizeTaskPositionerTest : ShellTestCase() {
fun testDragResize_hasEffectiveMove_issuesTransitionOnMoveAndEnd() {
taskPositioner.onDragPositioningStart(
CTRL_TYPE_TOP or CTRL_TYPE_RIGHT,
+ DISPLAY_ID,
STARTING_BOUNDS.left.toFloat(),
STARTING_BOUNDS.top.toFloat()
)
taskPositioner.onDragPositioningMove(
+ DISPLAY_ID,
STARTING_BOUNDS.left.toFloat() + 10,
STARTING_BOUNDS.top.toFloat()
)
@@ -224,6 +231,7 @@ class FluidResizeTaskPositionerTest : ShellTestCase() {
verify(mockDragEventListener, times(1)).onDragMove(eq(TASK_ID))
taskPositioner.onDragPositioningEnd(
+ DISPLAY_ID,
STARTING_BOUNDS.left.toFloat() + 10,
STARTING_BOUNDS.top.toFloat() + 10
)
@@ -242,6 +250,7 @@ class FluidResizeTaskPositionerTest : ShellTestCase() {
fun testDragResize_move_skipsDragResizingFlag() {
taskPositioner.onDragPositioningStart(
CTRL_TYPE_UNDEFINED, // Move
+ DISPLAY_ID,
STARTING_BOUNDS.left.toFloat(),
STARTING_BOUNDS.top.toFloat()
)
@@ -250,11 +259,12 @@ class FluidResizeTaskPositionerTest : ShellTestCase() {
val newX = STARTING_BOUNDS.left.toFloat() + 10
val newY = STARTING_BOUNDS.top.toFloat()
taskPositioner.onDragPositioningMove(
+ DISPLAY_ID,
newX,
newY
)
- taskPositioner.onDragPositioningEnd(newX, newY)
+ taskPositioner.onDragPositioningEnd(DISPLAY_ID, newX, newY)
verify(mockShellTaskOrganizer, never()).applyTransaction(argThat { wct ->
return@argThat wct.changes.any { (token, change) ->
@@ -276,6 +286,7 @@ class FluidResizeTaskPositionerTest : ShellTestCase() {
fun testDragResize_resize_setsDragResizingFlag() {
taskPositioner.onDragPositioningStart(
CTRL_TYPE_RIGHT, // Resize right
+ DISPLAY_ID,
STARTING_BOUNDS.left.toFloat(),
STARTING_BOUNDS.top.toFloat()
)
@@ -284,11 +295,12 @@ class FluidResizeTaskPositionerTest : ShellTestCase() {
val newX = STARTING_BOUNDS.right.toFloat() + 10
val newY = STARTING_BOUNDS.top.toFloat()
taskPositioner.onDragPositioningMove(
+ DISPLAY_ID,
newX,
newY
)
- taskPositioner.onDragPositioningEnd(newX, newY)
+ taskPositioner.onDragPositioningEnd(DISPLAY_ID, newX, newY)
verify(mockShellTaskOrganizer).applyTransaction(argThat { wct ->
return@argThat wct.changes.any { (token, change) ->
@@ -310,6 +322,7 @@ class FluidResizeTaskPositionerTest : ShellTestCase() {
fun testDragResize_resize_setBoundsDoesNotChangeHeightWhenLessThanMin() {
taskPositioner.onDragPositioningStart(
CTRL_TYPE_RIGHT or CTRL_TYPE_TOP, // Resize right and top
+ DISPLAY_ID,
STARTING_BOUNDS.right.toFloat(),
STARTING_BOUNDS.top.toFloat()
)
@@ -318,11 +331,12 @@ class FluidResizeTaskPositionerTest : ShellTestCase() {
val newX = STARTING_BOUNDS.right.toFloat() - 5
val newY = STARTING_BOUNDS.top.toFloat() + 95
taskPositioner.onDragPositioningMove(
+ DISPLAY_ID,
newX,
newY
)
- taskPositioner.onDragPositioningEnd(newX, newY)
+ taskPositioner.onDragPositioningEnd(DISPLAY_ID, newX, newY)
verify(mockShellTaskOrganizer).applyTransaction(argThat { wct ->
return@argThat wct.changes.any { (token, change) ->
@@ -340,6 +354,7 @@ class FluidResizeTaskPositionerTest : ShellTestCase() {
fun testDragResize_resize_setBoundsDoesNotChangeWidthWhenLessThanMin() {
taskPositioner.onDragPositioningStart(
CTRL_TYPE_RIGHT or CTRL_TYPE_TOP, // Resize right and top
+ DISPLAY_ID,
STARTING_BOUNDS.right.toFloat(),
STARTING_BOUNDS.top.toFloat()
)
@@ -348,11 +363,12 @@ class FluidResizeTaskPositionerTest : ShellTestCase() {
val newX = STARTING_BOUNDS.right.toFloat() - 95
val newY = STARTING_BOUNDS.top.toFloat() + 5
taskPositioner.onDragPositioningMove(
+ DISPLAY_ID,
newX,
newY
)
- taskPositioner.onDragPositioningEnd(newX, newY)
+ taskPositioner.onDragPositioningEnd(DISPLAY_ID, newX, newY)
verify(mockShellTaskOrganizer).applyTransaction(argThat { wct ->
return@argThat wct.changes.any { (token, change) ->
@@ -370,6 +386,7 @@ class FluidResizeTaskPositionerTest : ShellTestCase() {
fun testDragResize_resize_setBoundsDoesNotChangeHeightWhenNegative() {
taskPositioner.onDragPositioningStart(
CTRL_TYPE_RIGHT or CTRL_TYPE_TOP, // Resize right and top
+ DISPLAY_ID,
STARTING_BOUNDS.right.toFloat(),
STARTING_BOUNDS.top.toFloat()
)
@@ -378,11 +395,12 @@ class FluidResizeTaskPositionerTest : ShellTestCase() {
val newX = STARTING_BOUNDS.right.toFloat() - 5
val newY = STARTING_BOUNDS.top.toFloat() + 105
taskPositioner.onDragPositioningMove(
+ DISPLAY_ID,
newX,
newY
)
- taskPositioner.onDragPositioningEnd(newX, newY)
+ taskPositioner.onDragPositioningEnd(DISPLAY_ID, newX, newY)
verify(mockShellTaskOrganizer).applyTransaction(argThat { wct ->
return@argThat wct.changes.any { (token, change) ->
@@ -400,6 +418,7 @@ class FluidResizeTaskPositionerTest : ShellTestCase() {
fun testDragResize_resize_setBoundsDoesNotChangeWidthWhenNegative() {
taskPositioner.onDragPositioningStart(
CTRL_TYPE_RIGHT or CTRL_TYPE_TOP, // Resize right and top
+ DISPLAY_ID,
STARTING_BOUNDS.right.toFloat(),
STARTING_BOUNDS.top.toFloat()
)
@@ -408,11 +427,12 @@ class FluidResizeTaskPositionerTest : ShellTestCase() {
val newX = STARTING_BOUNDS.right.toFloat() - 105
val newY = STARTING_BOUNDS.top.toFloat() + 5
taskPositioner.onDragPositioningMove(
+ DISPLAY_ID,
newX,
newY
)
- taskPositioner.onDragPositioningEnd(newX, newY)
+ taskPositioner.onDragPositioningEnd(DISPLAY_ID, newX, newY)
verify(mockShellTaskOrganizer).applyTransaction(argThat { wct ->
return@argThat wct.changes.any { (token, change) ->
@@ -430,6 +450,7 @@ class FluidResizeTaskPositionerTest : ShellTestCase() {
fun testDragResize_resize_setBoundsRunsWhenResizeBoundsValid() {
taskPositioner.onDragPositioningStart(
CTRL_TYPE_RIGHT or CTRL_TYPE_TOP, // Resize right and top
+ DISPLAY_ID,
STARTING_BOUNDS.right.toFloat(),
STARTING_BOUNDS.top.toFloat()
)
@@ -438,11 +459,12 @@ class FluidResizeTaskPositionerTest : ShellTestCase() {
val newX = STARTING_BOUNDS.right.toFloat() - 80
val newY = STARTING_BOUNDS.top.toFloat() + 80
taskPositioner.onDragPositioningMove(
+ DISPLAY_ID,
newX,
newY
)
- taskPositioner.onDragPositioningEnd(newX, newY)
+ taskPositioner.onDragPositioningEnd(DISPLAY_ID, newX, newY)
verify(mockShellTaskOrganizer).applyTransaction(argThat { wct ->
return@argThat wct.changes.any { (token, change) ->
@@ -456,6 +478,7 @@ class FluidResizeTaskPositionerTest : ShellTestCase() {
fun testDragResize_resize_setBoundsDoesNotRunWithNegativeHeightAndWidth() {
taskPositioner.onDragPositioningStart(
CTRL_TYPE_RIGHT or CTRL_TYPE_TOP, // Resize right and top
+ DISPLAY_ID,
STARTING_BOUNDS.right.toFloat(),
STARTING_BOUNDS.top.toFloat()
)
@@ -464,11 +487,12 @@ class FluidResizeTaskPositionerTest : ShellTestCase() {
val newX = STARTING_BOUNDS.right.toFloat() - 95
val newY = STARTING_BOUNDS.top.toFloat() + 95
taskPositioner.onDragPositioningMove(
+ DISPLAY_ID,
newX,
newY
)
- taskPositioner.onDragPositioningEnd(newX, newY)
+ taskPositioner.onDragPositioningEnd(DISPLAY_ID, newX, newY)
verify(mockShellTaskOrganizer, never()).applyTransaction(argThat { wct ->
return@argThat wct.changes.any { (token, change) ->
@@ -484,6 +508,7 @@ class FluidResizeTaskPositionerTest : ShellTestCase() {
taskPositioner.onDragPositioningStart(
CTRL_TYPE_RIGHT or CTRL_TYPE_TOP, // Resize right and top
+ DISPLAY_ID,
STARTING_BOUNDS.right.toFloat(),
STARTING_BOUNDS.top.toFloat()
)
@@ -492,11 +517,12 @@ class FluidResizeTaskPositionerTest : ShellTestCase() {
val newX = STARTING_BOUNDS.right.toFloat() - 97
val newY = STARTING_BOUNDS.top.toFloat() + 97
taskPositioner.onDragPositioningMove(
+ DISPLAY_ID,
newX,
newY
)
- taskPositioner.onDragPositioningEnd(newX, newY)
+ taskPositioner.onDragPositioningEnd(DISPLAY_ID, newX, newY)
verify(mockShellTaskOrganizer, never()).applyTransaction(argThat { wct ->
return@argThat wct.changes.any { (token, change) ->
@@ -510,6 +536,7 @@ class FluidResizeTaskPositionerTest : ShellTestCase() {
fun testDragResize_resize_useMinWidthWhenValid() {
taskPositioner.onDragPositioningStart(
CTRL_TYPE_RIGHT or CTRL_TYPE_TOP, // Resize right and top
+ DISPLAY_ID,
STARTING_BOUNDS.right.toFloat(),
STARTING_BOUNDS.top.toFloat()
)
@@ -518,11 +545,12 @@ class FluidResizeTaskPositionerTest : ShellTestCase() {
val newX = STARTING_BOUNDS.right.toFloat() - 93
val newY = STARTING_BOUNDS.top.toFloat() + 93
taskPositioner.onDragPositioningMove(
+ DISPLAY_ID,
newX,
newY
)
- taskPositioner.onDragPositioningEnd(newX, newY)
+ taskPositioner.onDragPositioningEnd(DISPLAY_ID, newX, newY)
verify(mockShellTaskOrganizer, never()).applyTransaction(argThat { wct ->
return@argThat wct.changes.any { (token, change) ->
@@ -535,6 +563,7 @@ class FluidResizeTaskPositionerTest : ShellTestCase() {
fun testDragResize_toDisallowedBounds_freezesAtLimit() {
taskPositioner.onDragPositioningStart(
CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM, // Resize right-bottom corner
+ DISPLAY_ID,
STARTING_BOUNDS.right.toFloat(),
STARTING_BOUNDS.bottom.toFloat()
)
@@ -546,6 +575,7 @@ class FluidResizeTaskPositionerTest : ShellTestCase() {
STARTING_BOUNDS.right + 10,
STARTING_BOUNDS.bottom + 10)
taskPositioner.onDragPositioningMove(
+ DISPLAY_ID,
newBounds.right.toFloat(),
newBounds.bottom.toFloat()
)
@@ -559,11 +589,13 @@ class FluidResizeTaskPositionerTest : ShellTestCase() {
DISALLOWED_RESIZE_AREA.top
)
taskPositioner.onDragPositioningMove(
+ DISPLAY_ID,
newBounds2.right.toFloat(),
newBounds2.bottom.toFloat()
)
- taskPositioner.onDragPositioningEnd(newBounds2.right.toFloat(), newBounds2.bottom.toFloat())
+ taskPositioner.onDragPositioningEnd(DISPLAY_ID, newBounds2.right.toFloat(),
+ newBounds2.bottom.toFloat())
// The first resize falls in the allowed area, verify there's a change for it.
verify(mockShellTaskOrganizer).applyTransaction(argThat { wct ->
@@ -629,6 +661,7 @@ class FluidResizeTaskPositionerTest : ShellTestCase() {
mockWindowDecoration.mHasGlobalFocus = false
taskPositioner.onDragPositioningStart(
CTRL_TYPE_RIGHT, // Resize right
+ DISPLAY_ID,
STARTING_BOUNDS.left.toFloat(),
STARTING_BOUNDS.top.toFloat()
)
@@ -645,6 +678,7 @@ class FluidResizeTaskPositionerTest : ShellTestCase() {
mockWindowDecoration.mHasGlobalFocus = true
taskPositioner.onDragPositioningStart(
CTRL_TYPE_RIGHT, // Resize right
+ DISPLAY_ID,
STARTING_BOUNDS.left.toFloat(),
STARTING_BOUNDS.top.toFloat()
)
@@ -661,6 +695,7 @@ class FluidResizeTaskPositionerTest : ShellTestCase() {
mockWindowDecoration.mHasGlobalFocus = false
taskPositioner.onDragPositioningStart(
CTRL_TYPE_UNDEFINED, // drag
+ DISPLAY_ID,
STARTING_BOUNDS.left.toFloat(),
STARTING_BOUNDS.top.toFloat()
)
@@ -729,11 +764,13 @@ class FluidResizeTaskPositionerTest : ShellTestCase() {
taskPositioner.onDragPositioningStart(
CTRL_TYPE_TOP or CTRL_TYPE_RIGHT,
+ DISPLAY_ID,
STARTING_BOUNDS.left.toFloat(),
STARTING_BOUNDS.top.toFloat()
)
taskPositioner.onDragPositioningMove(
+ DISPLAY_ID,
STARTING_BOUNDS.left.toFloat() - 20,
STARTING_BOUNDS.top.toFloat() - 20
)
@@ -742,6 +779,7 @@ class FluidResizeTaskPositionerTest : ShellTestCase() {
assertTrue(taskPositioner.isResizingOrAnimating)
taskPositioner.onDragPositioningEnd(
+ DISPLAY_ID,
STARTING_BOUNDS.left.toFloat(),
STARTING_BOUNDS.top.toFloat()
)
@@ -785,15 +823,18 @@ class FluidResizeTaskPositionerTest : ShellTestCase() {
) {
taskPositioner.onDragPositioningStart(
ctrlType,
+ DISPLAY_ID,
startX,
startY
)
taskPositioner.onDragPositioningMove(
+ DISPLAY_ID,
endX,
endY
)
taskPositioner.onDragPositioningEnd(
+ DISPLAY_ID,
endX,
endY
)
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositionerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositionerTest.kt
index e7df8643ba66..eb8c0dd365a3 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositionerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositionerTest.kt
@@ -168,12 +168,14 @@ class VeiledResizeTaskPositionerTest : ShellTestCase() {
fun testDragResize_noMove_doesNotShowResizeVeil() = runOnUiThread {
taskPositioner.onDragPositioningStart(
CTRL_TYPE_TOP or CTRL_TYPE_RIGHT,
+ DISPLAY_ID,
STARTING_BOUNDS.left.toFloat(),
STARTING_BOUNDS.top.toFloat()
)
verify(mockDesktopWindowDecoration, never()).showResizeVeil(STARTING_BOUNDS)
taskPositioner.onDragPositioningEnd(
+ DISPLAY_ID,
STARTING_BOUNDS.left.toFloat(),
STARTING_BOUNDS.top.toFloat()
)
@@ -191,11 +193,13 @@ class VeiledResizeTaskPositionerTest : ShellTestCase() {
fun testDragResize_movesTask_doesNotShowResizeVeil() = runOnUiThread {
taskPositioner.onDragPositioningStart(
CTRL_TYPE_UNDEFINED,
+ DISPLAY_ID,
STARTING_BOUNDS.left.toFloat(),
STARTING_BOUNDS.top.toFloat()
)
taskPositioner.onDragPositioningMove(
+ DISPLAY_ID,
STARTING_BOUNDS.left.toFloat() + 60,
STARTING_BOUNDS.top.toFloat() + 100
)
@@ -208,6 +212,7 @@ class VeiledResizeTaskPositionerTest : ShellTestCase() {
eq(rectAfterMove.top.toFloat()))
val endBounds = taskPositioner.onDragPositioningEnd(
+ DISPLAY_ID,
STARTING_BOUNDS.left.toFloat() + 70,
STARTING_BOUNDS.top.toFloat() + 20
)
@@ -226,11 +231,13 @@ class VeiledResizeTaskPositionerTest : ShellTestCase() {
fun testDragResize_resize_boundsUpdateOnEnd() = runOnUiThread {
taskPositioner.onDragPositioningStart(
CTRL_TYPE_RIGHT or CTRL_TYPE_TOP,
+ DISPLAY_ID,
STARTING_BOUNDS.right.toFloat(),
STARTING_BOUNDS.top.toFloat()
)
taskPositioner.onDragPositioningMove(
+ DISPLAY_ID,
STARTING_BOUNDS.right.toFloat() + 10,
STARTING_BOUNDS.top.toFloat() + 10
)
@@ -248,6 +255,7 @@ class VeiledResizeTaskPositionerTest : ShellTestCase() {
})
taskPositioner.onDragPositioningEnd(
+ DISPLAY_ID,
STARTING_BOUNDS.right.toFloat() + 20,
STARTING_BOUNDS.top.toFloat() + 20
)
@@ -266,17 +274,20 @@ class VeiledResizeTaskPositionerTest : ShellTestCase() {
@Test
fun testDragResize_noEffectiveMove_skipsTransactionOnEnd() = runOnUiThread {
taskPositioner.onDragPositioningStart(
+ DISPLAY_ID,
CTRL_TYPE_TOP or CTRL_TYPE_RIGHT,
STARTING_BOUNDS.left.toFloat(),
STARTING_BOUNDS.top.toFloat()
)
taskPositioner.onDragPositioningMove(
+ DISPLAY_ID,
STARTING_BOUNDS.left.toFloat(),
STARTING_BOUNDS.top.toFloat()
)
taskPositioner.onDragPositioningEnd(
+ DISPLAY_ID,
STARTING_BOUNDS.left.toFloat() + 10,
STARTING_BOUNDS.top.toFloat() + 10
)
@@ -300,6 +311,7 @@ class VeiledResizeTaskPositionerTest : ShellTestCase() {
fun testDragResize_drag_setBoundsNotRunIfDragEndsInDisallowedEndArea() = runOnUiThread {
taskPositioner.onDragPositioningStart(
CTRL_TYPE_UNDEFINED, // drag
+ DISPLAY_ID,
STARTING_BOUNDS.left.toFloat(),
STARTING_BOUNDS.top.toFloat()
)
@@ -307,11 +319,12 @@ class VeiledResizeTaskPositionerTest : ShellTestCase() {
val newX = STARTING_BOUNDS.left.toFloat() + 5
val newY = DISALLOWED_AREA_FOR_END_BOUNDS_HEIGHT.toFloat() - 1
taskPositioner.onDragPositioningMove(
+ DISPLAY_ID,
newX,
newY
)
- taskPositioner.onDragPositioningEnd(newX, newY)
+ taskPositioner.onDragPositioningEnd(DISPLAY_ID, newX, newY)
verify(mockShellTaskOrganizer, never()).applyTransaction(argThat { wct ->
return@argThat wct.changes.any { (token, change) ->
@@ -326,6 +339,7 @@ class VeiledResizeTaskPositionerTest : ShellTestCase() {
mockDesktopWindowDecoration.mHasGlobalFocus = false
taskPositioner.onDragPositioningStart(
CTRL_TYPE_RIGHT, // Resize right
+ DISPLAY_ID,
STARTING_BOUNDS.left.toFloat(),
STARTING_BOUNDS.top.toFloat()
)
@@ -342,6 +356,7 @@ class VeiledResizeTaskPositionerTest : ShellTestCase() {
mockDesktopWindowDecoration.mHasGlobalFocus = true
taskPositioner.onDragPositioningStart(
CTRL_TYPE_RIGHT, // Resize right
+ DISPLAY_ID,
STARTING_BOUNDS.left.toFloat(),
STARTING_BOUNDS.top.toFloat()
)
@@ -358,6 +373,7 @@ class VeiledResizeTaskPositionerTest : ShellTestCase() {
mockDesktopWindowDecoration.mHasGlobalFocus = false
taskPositioner.onDragPositioningStart(
CTRL_TYPE_UNDEFINED, // drag
+ DISPLAY_ID,
STARTING_BOUNDS.left.toFloat(),
STARTING_BOUNDS.top.toFloat()
)
@@ -422,11 +438,13 @@ class VeiledResizeTaskPositionerTest : ShellTestCase() {
taskPositioner.onDragPositioningStart(
CTRL_TYPE_TOP or CTRL_TYPE_RIGHT,
+ DISPLAY_ID,
STARTING_BOUNDS.left.toFloat(),
STARTING_BOUNDS.top.toFloat()
)
taskPositioner.onDragPositioningMove(
+ DISPLAY_ID,
STARTING_BOUNDS.left.toFloat() - 20,
STARTING_BOUNDS.top.toFloat() - 20
)
@@ -436,6 +454,7 @@ class VeiledResizeTaskPositionerTest : ShellTestCase() {
verify(mockDragEventListener, times(1)).onDragMove(eq(TASK_ID))
taskPositioner.onDragPositioningEnd(
+ DISPLAY_ID,
STARTING_BOUNDS.left.toFloat(),
STARTING_BOUNDS.top.toFloat()
)
@@ -501,15 +520,18 @@ class VeiledResizeTaskPositionerTest : ShellTestCase() {
) {
taskPositioner.onDragPositioningStart(
ctrlType,
+ DISPLAY_ID,
startX,
startY
)
taskPositioner.onDragPositioningMove(
+ DISPLAY_ID,
endX,
endY
)
taskPositioner.onDragPositioningEnd(
+ DISPLAY_ID,
endX,
endY
)
diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java
index 50387548b4ab..bcb70019b3ac 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -53,7 +53,7 @@ import java.util.stream.Collectors;
* The format of the media data is specified as key/value pairs. Keys are strings. Values can
* be integer, long, float, String or ByteBuffer.
* <p>
- * The feature metadata is specificed as string/boolean pairs.
+ * The feature metadata is specified as string/boolean pairs.
* <p>
* Keys common to all audio/video formats, <b>all keys not marked optional are mandatory</b>:
*
@@ -1244,12 +1244,12 @@ public final class MediaFormat {
/**
* An optional key describing the desired encoder latency in frames. This is an optional
- * parameter that applies only to video encoders. If encoder supports it, it should ouput
+ * parameter that applies only to video encoders. If encoder supports it, it should output
* at least one output frame after being queued the specified number of frames. This key
* is ignored if the video encoder does not support the latency feature. Use the output
* format to verify that this feature was enabled and the actual value used by the encoder.
* <p>
- * If the key is not specified, the default latency will be implenmentation specific.
+ * If the key is not specified, the default latency will be implementation specific.
* The associated value is an integer.
*/
public static final String KEY_LATENCY = "latency";
@@ -1507,16 +1507,16 @@ public final class MediaFormat {
*/
public static final String KEY_COLOR_STANDARD = "color-standard";
- /** BT.709 color chromacity coordinates with KR = 0.2126, KB = 0.0722. */
+ /** BT.709 color chromaticity coordinates with KR = 0.2126, KB = 0.0722. */
public static final int COLOR_STANDARD_BT709 = 1;
- /** BT.601 625 color chromacity coordinates with KR = 0.299, KB = 0.114. */
+ /** BT.601 625 color chromaticity coordinates with KR = 0.299, KB = 0.114. */
public static final int COLOR_STANDARD_BT601_PAL = 2;
- /** BT.601 525 color chromacity coordinates with KR = 0.299, KB = 0.114. */
+ /** BT.601 525 color chromaticity coordinates with KR = 0.299, KB = 0.114. */
public static final int COLOR_STANDARD_BT601_NTSC = 4;
- /** BT.2020 color chromacity coordinates with KR = 0.2627, KB = 0.0593. */
+ /** BT.2020 color chromaticity coordinates with KR = 0.2627, KB = 0.0593. */
public static final int COLOR_STANDARD_BT2020 = 6;
/** @hide */
@@ -2150,7 +2150,7 @@ public final class MediaFormat {
* Sets the value of a string key.
* <p>
* If value is {@code null}, it sets a null value that behaves similarly to a missing key.
- * This could be used prior to API level {@link android os.Build.VERSION_CODES#Q} to effectively
+ * This could be used prior to API level {@link android.os.Build.VERSION_CODES#Q} to effectively
* remove a key.
*/
public final void setString(@NonNull String name, @Nullable String value) {
@@ -2161,7 +2161,7 @@ public final class MediaFormat {
* Sets the value of a ByteBuffer key.
* <p>
* If value is {@code null}, it sets a null value that behaves similarly to a missing key.
- * This could be used prior to API level {@link android os.Build.VERSION_CODES#Q} to effectively
+ * This could be used prior to API level {@link android.os.Build.VERSION_CODES#Q} to effectively
* remove a key.
*/
public final void setByteBuffer(@NonNull String name, @Nullable ByteBuffer bytes) {
diff --git a/native/android/performance_hint.cpp b/native/android/performance_hint.cpp
index 0db99ffd208a..9257901bcd1f 100644
--- a/native/android/performance_hint.cpp
+++ b/native/android/performance_hint.cpp
@@ -22,6 +22,7 @@
#include <aidl/android/hardware/power/SessionHint.h>
#include <aidl/android/hardware/power/SessionMode.h>
#include <aidl/android/hardware/power/SessionTag.h>
+#include <aidl/android/hardware/power/SupportInfo.h>
#include <aidl/android/hardware/power/WorkDuration.h>
#include <aidl/android/hardware/power/WorkDurationFixedV1.h>
#include <aidl/android/os/IHintManager.h>
@@ -148,10 +149,36 @@ private:
std::future<bool> mChannelCreationFinished;
};
+class SupportInfoWrapper {
+public:
+ SupportInfoWrapper(hal::SupportInfo& info);
+ bool isSessionModeSupported(hal::SessionMode mode);
+ bool isSessionHintSupported(hal::SessionHint hint);
+
+private:
+ template <class T>
+ bool getEnumSupportFromBitfield(T& enumValue, int64_t& supportBitfield) {
+ // extract the bit corresponding to the enum by shifting the bitfield
+ // over that much and cutting off any extra values
+ return (supportBitfield >> static_cast<int>(enumValue)) % 2;
+ }
+ hal::SupportInfo mSupportInfo;
+};
+
+class HintManagerClient : public IHintManager::BnHintManagerClient {
+public:
+ // Currently a no-op that exists for FMQ init to call in the future
+ ndk::ScopedAStatus receiveChannelConfig(const hal::ChannelConfig&) {
+ return ndk::ScopedAStatus::ok();
+ }
+};
+
struct APerformanceHintManager {
public:
static APerformanceHintManager* getInstance();
- APerformanceHintManager(std::shared_ptr<IHintManager>& service, int64_t preferredRateNanos);
+ APerformanceHintManager(std::shared_ptr<IHintManager>& service,
+ IHintManager::HintManagerClientData&& clientData,
+ std::shared_ptr<HintManagerClient> callbackClient);
APerformanceHintManager() = delete;
~APerformanceHintManager();
@@ -169,29 +196,21 @@ public:
FMQWrapper& getFMQWrapper();
bool canSendLoadHints(std::vector<hal::SessionHint>& hints, int64_t now) REQUIRES(sHintMutex);
void initJava(JNIEnv* _Nonnull env);
- ndk::ScopedAIBinder_Weak x;
template <class T>
static void layersFromNativeSurfaces(ANativeWindow** windows, int numWindows,
ASurfaceControl** controls, int numSurfaceControls,
std::vector<T>& out);
+ ndk::SpAIBinder& getToken();
+ SupportInfoWrapper& getSupportInfo();
private:
- // Necessary to create an empty binder object
- static void* tokenStubOnCreate(void*) {
- return nullptr;
- }
- static void tokenStubOnDestroy(void*) {}
- static binder_status_t tokenStubOnTransact(AIBinder*, transaction_code_t, const AParcel*,
- AParcel*) {
- return STATUS_OK;
- }
-
static APerformanceHintManager* create(std::shared_ptr<IHintManager> iHintManager);
std::shared_ptr<IHintManager> mHintManager;
+ std::shared_ptr<HintManagerClient> mCallbackClient;
+ IHintManager::HintManagerClientData mClientData;
+ SupportInfoWrapper mSupportInfoWrapper;
ndk::SpAIBinder mToken;
- const int64_t mPreferredRateNanos;
- std::optional<int32_t> mMaxGraphicsPipelineThreadsCount;
FMQWrapper mFMQWrapper;
double mHintBudget = kMaxLoadHintsPerInterval;
int64_t mLastBudgetReplenish = 0;
@@ -273,14 +292,27 @@ static FMQWrapper& getFMQ() {
return APerformanceHintManager::getInstance()->getFMQWrapper();
}
+// ===================================== SupportInfoWrapper implementation
+
+SupportInfoWrapper::SupportInfoWrapper(hal::SupportInfo& info) : mSupportInfo(info) {}
+
+bool SupportInfoWrapper::isSessionHintSupported(hal::SessionHint hint) {
+ return getEnumSupportFromBitfield(hint, mSupportInfo.sessionHints);
+}
+
+bool SupportInfoWrapper::isSessionModeSupported(hal::SessionMode mode) {
+ return getEnumSupportFromBitfield(mode, mSupportInfo.sessionModes);
+}
+
// ===================================== APerformanceHintManager implementation
APerformanceHintManager::APerformanceHintManager(std::shared_ptr<IHintManager>& manager,
- int64_t preferredRateNanos)
- : mHintManager(std::move(manager)), mPreferredRateNanos(preferredRateNanos) {
- static AIBinder_Class* tokenBinderClass =
- AIBinder_Class_define("phm_token", tokenStubOnCreate, tokenStubOnDestroy,
- tokenStubOnTransact);
- mToken = ndk::SpAIBinder(AIBinder_new(tokenBinderClass, nullptr));
+ IHintManager::HintManagerClientData&& clientData,
+ std::shared_ptr<HintManagerClient> callbackClient)
+ : mHintManager(std::move(manager)),
+ mCallbackClient(callbackClient),
+ mClientData(clientData),
+ mSupportInfoWrapper(clientData.supportInfo),
+ mToken(callbackClient->asBinder()) {
if (mFMQWrapper.isSupported()) {
mFMQWrapper.setToken(mToken);
mFMQWrapper.startChannel(mHintManager.get());
@@ -315,16 +347,17 @@ APerformanceHintManager* APerformanceHintManager::create(std::shared_ptr<IHintMa
ALOGE("%s: PerformanceHint service is not ready ", __FUNCTION__);
return nullptr;
}
- int64_t preferredRateNanos = -1L;
- ndk::ScopedAStatus ret = manager->getHintSessionPreferredRate(&preferredRateNanos);
+ std::shared_ptr<HintManagerClient> client = ndk::SharedRefBase::make<HintManagerClient>();
+ IHintManager::HintManagerClientData clientData;
+ ndk::ScopedAStatus ret = manager->registerClient(client, &clientData);
if (!ret.isOk()) {
- ALOGE("%s: PerformanceHint cannot get preferred rate. %s", __FUNCTION__, ret.getMessage());
+ ALOGE("%s: PerformanceHint is not supported. %s", __FUNCTION__, ret.getMessage());
return nullptr;
}
- if (preferredRateNanos <= 0) {
- preferredRateNanos = -1L;
+ if (clientData.preferredRateNanos <= 0) {
+ clientData.preferredRateNanos = -1L;
}
- return new APerformanceHintManager(manager, preferredRateNanos);
+ return new APerformanceHintManager(manager, std::move(clientData), client);
}
bool APerformanceHintManager::canSendLoadHints(std::vector<hal::SessionHint>& hints, int64_t now) {
@@ -389,7 +422,9 @@ APerformanceHintSession* APerformanceHintManager::createSessionUsingConfig(
ALOGE("%s: PerformanceHint cannot create session. %s", __FUNCTION__, ret.getMessage());
return nullptr;
}
- auto out = new APerformanceHintSession(mHintManager, std::move(session), mPreferredRateNanos,
+
+ auto out = new APerformanceHintSession(mHintManager, std::move(session),
+ mClientData.preferredRateNanos,
sessionCreationConfig->targetWorkDurationNanos, isJava,
sessionConfig.id == -1
? std::nullopt
@@ -416,24 +451,11 @@ APerformanceHintSession* APerformanceHintManager::getSessionFromJava(JNIEnv* env
}
int64_t APerformanceHintManager::getPreferredRateNanos() const {
- return mPreferredRateNanos;
+ return mClientData.preferredRateNanos;
}
int32_t APerformanceHintManager::getMaxGraphicsPipelineThreadsCount() {
- if (!mMaxGraphicsPipelineThreadsCount.has_value()) {
- int32_t threadsCount = -1;
- ndk::ScopedAStatus ret = mHintManager->getMaxGraphicsPipelineThreadsCount(&threadsCount);
- if (!ret.isOk()) {
- ALOGE("%s: PerformanceHint cannot get max graphics pipeline threads count. %s",
- __FUNCTION__, ret.getMessage());
- return -1;
- }
- if (threadsCount <= 0) {
- threadsCount = -1;
- }
- mMaxGraphicsPipelineThreadsCount.emplace(threadsCount);
- }
- return mMaxGraphicsPipelineThreadsCount.value();
+ return mClientData.maxGraphicsPipelineThreads;
}
FMQWrapper& APerformanceHintManager::getFMQWrapper() {
@@ -450,6 +472,14 @@ void APerformanceHintManager::initJava(JNIEnv* _Nonnull env) {
mJavaInitialized = true;
}
+ndk::SpAIBinder& APerformanceHintManager::getToken() {
+ return mToken;
+}
+
+SupportInfoWrapper& APerformanceHintManager::getSupportInfo() {
+ return mSupportInfoWrapper;
+}
+
// ===================================== APerformanceHintSession implementation
constexpr int kNumEnums = enum_size<hal::SessionHint>();
diff --git a/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp b/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp
index c166e738ffb2..e3c10f63abb4 100644
--- a/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp
+++ b/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp
@@ -56,9 +56,6 @@ public:
const SessionCreationConfig& creationConfig, hal::SessionConfig* config,
std::shared_ptr<IHintSession>* _aidl_return),
(override));
- MOCK_METHOD(ScopedAStatus, getHintSessionPreferredRate, (int64_t * _aidl_return), (override));
- MOCK_METHOD(ScopedAStatus, getMaxGraphicsPipelineThreadsCount, (int32_t* _aidl_return),
- (override));
MOCK_METHOD(ScopedAStatus, setHintSessionThreads,
(const std::shared_ptr<IHintSession>& hintSession,
const ::std::vector<int32_t>& tids),
@@ -84,6 +81,11 @@ public:
MOCK_METHOD(ScopedAStatus, getGpuHeadroomMinIntervalMillis, (int64_t* _aidl_return),
(override));
MOCK_METHOD(ScopedAStatus, passSessionManagerBinder, (const SpAIBinder& sessionManager));
+ MOCK_METHOD(ScopedAStatus, registerClient,
+ (const std::shared_ptr<::aidl::android::os::IHintManager::IHintManagerClient>&
+ clientDataIn,
+ ::aidl::android::os::IHintManager::HintManagerClientData* _aidl_return),
+ (override));
MOCK_METHOD(SpAIBinder, asBinder, (), (override));
MOCK_METHOD(bool, isRemote, (), (override));
};
@@ -125,10 +127,9 @@ public:
APerformanceHintManager* createManager() {
APerformanceHint_setUseFMQForTesting(mUsingFMQ);
- ON_CALL(*mMockIHintManager, getHintSessionPreferredRate(_))
- .WillByDefault(DoAll(SetArgPointee<0>(123L), [] { return ScopedAStatus::ok(); }));
- ON_CALL(*mMockIHintManager, getMaxGraphicsPipelineThreadsCount(_))
- .WillByDefault(DoAll(SetArgPointee<0>(5), [] { return ScopedAStatus::ok(); }));
+ ON_CALL(*mMockIHintManager, registerClient(_, _))
+ .WillByDefault(
+ DoAll(SetArgPointee<1>(mClientData), [] { return ScopedAStatus::ok(); }));
return APerformanceHint_getManager();
}
@@ -238,6 +239,20 @@ public:
int kMockQueueSize = 20;
bool mUsingFMQ = false;
+ IHintManager::HintManagerClientData mClientData{
+ .powerHalVersion = 6,
+ .maxGraphicsPipelineThreads = 5,
+ .preferredRateNanos = 123L,
+ .supportInfo{
+ .usesSessions = true,
+ .boosts = 0,
+ .modes = 0,
+ .sessionHints = -1,
+ .sessionModes = -1,
+ .sessionTags = -1,
+ },
+ };
+
int32_t mMaxLoadHintsPerInterval;
int64_t mLoadHintInterval;
@@ -256,12 +271,6 @@ bool equalsWithoutTimestamp(hal::WorkDuration lhs, hal::WorkDuration rhs) {
lhs.gpuDurationNanos == rhs.gpuDurationNanos && lhs.durationNanos == rhs.durationNanos;
}
-TEST_F(PerformanceHintTest, TestGetPreferredUpdateRateNanos) {
- APerformanceHintManager* manager = createManager();
- int64_t preferredUpdateRateNanos = APerformanceHint_getPreferredUpdateRateNanos(manager);
- EXPECT_EQ(123L, preferredUpdateRateNanos);
-}
-
TEST_F(PerformanceHintTest, TestSession) {
APerformanceHintManager* manager = createManager();
APerformanceHintSession* session = createSession(manager);
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractorTest.kt
index 21019875f51e..9d5bf4dbdc3f 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractorTest.kt
@@ -55,7 +55,6 @@ import kotlinx.coroutines.flow.map
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Before
-import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith
@@ -887,7 +886,6 @@ class WindowManagerLockscreenVisibilityInteractorTest : SysuiTestCase() {
@Test
@EnableSceneContainer
- @Ignore("b/378766637")
fun lockscreenVisibilityWithScenes() =
testScope.runTest {
val isDeviceUnlocked by
@@ -896,6 +894,7 @@ class WindowManagerLockscreenVisibilityInteractorTest : SysuiTestCase() {
)
assertThat(isDeviceUnlocked).isFalse()
+ kosmos.setSceneTransition(Idle(Scenes.Lockscreen))
val currentScene by collectLastValue(kosmos.sceneInteractor.currentScene)
assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/ui/viewmodel/MediaControlViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/ui/viewmodel/MediaControlViewModelTest.kt
index 9edd62a8a784..6a2aae175d80 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/ui/viewmodel/MediaControlViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/ui/viewmodel/MediaControlViewModelTest.kt
@@ -16,21 +16,23 @@
package com.android.systemui.media.controls.ui.viewmodel
-import android.R
import android.content.packageManager
import android.content.pm.ApplicationInfo
import android.media.MediaMetadata
import android.media.session.MediaSession
import android.media.session.PlaybackState
+import androidx.constraintlayout.widget.ConstraintSet
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.kosmos.testScope
import com.android.systemui.media.controls.domain.pipeline.mediaDataFilter
+import com.android.systemui.media.controls.shared.model.MediaButton
import com.android.systemui.media.controls.shared.model.MediaData
import com.android.systemui.media.controls.shared.model.MediaDeviceData
import com.android.systemui.media.controls.util.mediaInstanceId
+import com.android.systemui.res.R
import com.android.systemui.statusbar.notificationLockscreenUserManager
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
@@ -132,6 +134,31 @@ class MediaControlViewModelTest : SysuiTestCase() {
assertThat(underTest.setPlayer(playerModel!!)).isTrue()
}
+ @Test
+ fun reservedButtons_showScrubbingTimes() =
+ testScope.runTest {
+ val playerModel by collectLastValue(underTest.player)
+ val mediaData =
+ initMediaData(ARTIST, TITLE)
+ .copy(semanticActions = MediaButton(reserveNext = true, reservePrev = true))
+
+ mediaDataFilter.onMediaDataLoaded(KEY, KEY, mediaData)
+
+ assertThat(playerModel?.actionButtons).isNotNull()
+ assertThat(playerModel!!.useSemanticActions).isTrue()
+ assertThat(playerModel!!.canShowTime).isTrue()
+
+ val buttons = playerModel!!.actionButtons
+
+ val prevButton = buttons.find { it.buttonId == R.id.actionPrev }!!
+ assertThat(prevButton.notVisibleValue).isEqualTo(ConstraintSet.GONE)
+ assertThat(prevButton.isVisibleWhenScrubbing).isEqualTo(false)
+
+ val nextButton = buttons.find { it.buttonId == R.id.actionNext }!!
+ assertThat(nextButton.notVisibleValue).isEqualTo(ConstraintSet.GONE)
+ assertThat(nextButton.isVisibleWhenScrubbing).isEqualTo(false)
+ }
+
private fun initMediaData(artist: String, title: String): MediaData {
val device = MediaDeviceData(true, null, DEVICE_NAME, null, showBroadcastButton = true)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ongoingcall/domain/interactor/OngoingCallInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ongoingcall/domain/interactor/OngoingCallInteractorTest.kt
index b19645fadbdf..8fb95e843ec1 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ongoingcall/domain/interactor/OngoingCallInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ongoingcall/domain/interactor/OngoingCallInteractorTest.kt
@@ -31,6 +31,7 @@ import com.android.systemui.kosmos.runTest
import com.android.systemui.kosmos.useUnconfinedTestDispatcher
import com.android.systemui.statusbar.StatusBarIconView
import com.android.systemui.statusbar.data.repository.fakeStatusBarModeRepository
+import com.android.systemui.statusbar.gesture.swipeStatusBarAwayGestureHandler
import com.android.systemui.statusbar.notification.data.model.activeNotificationModel
import com.android.systemui.statusbar.notification.data.repository.ActiveNotificationsStore
import com.android.systemui.statusbar.notification.data.repository.activeNotificationListRepository
@@ -40,9 +41,14 @@ import com.android.systemui.statusbar.window.fakeStatusBarWindowControllerStore
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
+import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+import org.mockito.kotlin.any
+import org.mockito.kotlin.clearInvocations
import org.mockito.kotlin.mock
+import org.mockito.kotlin.never
+import org.mockito.kotlin.verify
@SmallTest
@RunWith(AndroidJUnit4::class)
@@ -51,6 +57,11 @@ class OngoingCallInteractorTest : SysuiTestCase() {
private val repository = kosmos.activeNotificationListRepository
private val underTest = kosmos.ongoingCallInteractor
+ @Before
+ fun setUp() {
+ underTest.start()
+ }
+
@Test
fun noNotification_emitsNoCall() = runTest {
val state by collectLastValue(underTest.ongoingCallState)
@@ -210,8 +221,7 @@ class OngoingCallInteractorTest : SysuiTestCase() {
@Test
fun ongoingCallNotification_setsRequiresStatusBarVisibleTrue() =
kosmos.runTest {
- val ongoingCallState by collectLastValue(underTest.ongoingCallState)
-
+ val isStatusBarRequired by collectLastValue(underTest.isStatusBarRequiredForOngoingCall)
val requiresStatusBarVisibleInRepository by
collectLastValue(
kosmos.fakeStatusBarModeRepository.defaultDisplay
@@ -222,21 +232,9 @@ class OngoingCallInteractorTest : SysuiTestCase() {
kosmos.fakeStatusBarWindowControllerStore.defaultDisplay
.ongoingProcessRequiresStatusBarVisible
)
- repository.activeNotifications.value =
- ActiveNotificationsStore.Builder()
- .apply {
- addIndividualNotif(
- activeNotificationModel(
- key = "notif1",
- whenTime = 1000L,
- callType = CallType.Ongoing,
- uid = UID,
- )
- )
- }
- .build()
+ postOngoingCallNotification()
- assertThat(ongoingCallState).isInstanceOf(OngoingCallModel.InCall::class.java)
+ assertThat(isStatusBarRequired).isTrue()
assertThat(requiresStatusBarVisibleInRepository).isTrue()
assertThat(requiresStatusBarVisibleInWindowController).isTrue()
}
@@ -244,8 +242,7 @@ class OngoingCallInteractorTest : SysuiTestCase() {
@Test
fun notificationRemoved_setsRequiresStatusBarVisibleFalse() =
kosmos.runTest {
- val ongoingCallState by collectLastValue(underTest.ongoingCallState)
-
+ val isStatusBarRequired by collectLastValue(underTest.isStatusBarRequiredForOngoingCall)
val requiresStatusBarVisibleInRepository by
collectLastValue(
kosmos.fakeStatusBarModeRepository.defaultDisplay
@@ -257,23 +254,11 @@ class OngoingCallInteractorTest : SysuiTestCase() {
.ongoingProcessRequiresStatusBarVisible
)
- repository.activeNotifications.value =
- ActiveNotificationsStore.Builder()
- .apply {
- addIndividualNotif(
- activeNotificationModel(
- key = "notif1",
- whenTime = 1000L,
- callType = CallType.Ongoing,
- uid = UID,
- )
- )
- }
- .build()
+ postOngoingCallNotification()
repository.activeNotifications.value = ActiveNotificationsStore()
- assertThat(ongoingCallState).isInstanceOf(OngoingCallModel.NoCall::class.java)
+ assertThat(isStatusBarRequired).isFalse()
assertThat(requiresStatusBarVisibleInRepository).isFalse()
assertThat(requiresStatusBarVisibleInWindowController).isFalse()
}
@@ -295,19 +280,8 @@ class OngoingCallInteractorTest : SysuiTestCase() {
)
kosmos.activityManagerRepository.fake.startingIsAppVisibleValue = false
- repository.activeNotifications.value =
- ActiveNotificationsStore.Builder()
- .apply {
- addIndividualNotif(
- activeNotificationModel(
- key = "notif1",
- whenTime = 1000L,
- callType = CallType.Ongoing,
- uid = UID,
- )
- )
- }
- .build()
+
+ postOngoingCallNotification()
assertThat(ongoingCallState).isInstanceOf(OngoingCallModel.InCall::class.java)
assertThat(requiresStatusBarVisibleInRepository).isTrue()
@@ -321,6 +295,99 @@ class OngoingCallInteractorTest : SysuiTestCase() {
assertThat(requiresStatusBarVisibleInWindowController).isFalse()
}
+ @Test
+ fun gestureHandler_inCall_notFullscreen_doesNotListen() =
+ kosmos.runTest {
+ val ongoingCallState by collectLastValue(underTest.ongoingCallState)
+
+ clearInvocations(kosmos.swipeStatusBarAwayGestureHandler)
+ // Set up notification but not in fullscreen
+ kosmos.fakeStatusBarModeRepository.defaultDisplay.isInFullscreenMode.value = false
+ postOngoingCallNotification()
+
+ assertThat(ongoingCallState).isInstanceOf(OngoingCallModel.InCall::class.java)
+ verify(kosmos.swipeStatusBarAwayGestureHandler, never())
+ .addOnGestureDetectedCallback(any(), any())
+ }
+
+ @Test
+ fun gestureHandler_inCall_fullscreen_addsListener() =
+ kosmos.runTest {
+ val isGestureListeningEnabled by collectLastValue(underTest.isGestureListeningEnabled)
+
+ // Set up notification and fullscreen mode
+ kosmos.fakeStatusBarModeRepository.defaultDisplay.isInFullscreenMode.value = true
+ postOngoingCallNotification()
+
+ assertThat(isGestureListeningEnabled).isTrue()
+ verify(kosmos.swipeStatusBarAwayGestureHandler)
+ .addOnGestureDetectedCallback(any(), any())
+ }
+
+ @Test
+ fun gestureHandler_inCall_fullscreen_chipSwiped_removesListener() =
+ kosmos.runTest {
+ val swipeAwayState by collectLastValue(underTest.isChipSwipedAway)
+
+ // Set up notification and fullscreen mode
+ kosmos.fakeStatusBarModeRepository.defaultDisplay.isInFullscreenMode.value = true
+ postOngoingCallNotification()
+
+ clearInvocations(kosmos.swipeStatusBarAwayGestureHandler)
+
+ underTest.onStatusBarSwiped()
+
+ assertThat(swipeAwayState).isTrue()
+ verify(kosmos.swipeStatusBarAwayGestureHandler).removeOnGestureDetectedCallback(any())
+ }
+
+ @Test
+ fun chipSwipedAway_setsRequiresStatusBarVisibleFalse() =
+ kosmos.runTest {
+ val isStatusBarRequiredForOngoingCall by
+ collectLastValue(underTest.isStatusBarRequiredForOngoingCall)
+ val requiresStatusBarVisibleInRepository by
+ collectLastValue(
+ kosmos.fakeStatusBarModeRepository.defaultDisplay
+ .ongoingProcessRequiresStatusBarVisible
+ )
+ val requiresStatusBarVisibleInWindowController by
+ collectLastValue(
+ kosmos.fakeStatusBarWindowControllerStore.defaultDisplay
+ .ongoingProcessRequiresStatusBarVisible
+ )
+
+ // Start with an ongoing call (which should set status bar required)
+ postOngoingCallNotification()
+
+ assertThat(isStatusBarRequiredForOngoingCall).isTrue()
+ assertThat(requiresStatusBarVisibleInRepository).isTrue()
+ assertThat(requiresStatusBarVisibleInWindowController).isTrue()
+
+ // Swipe away the chip
+ underTest.onStatusBarSwiped()
+
+ // Verify status bar is no longer required
+ assertThat(requiresStatusBarVisibleInRepository).isFalse()
+ assertThat(requiresStatusBarVisibleInWindowController).isFalse()
+ }
+
+ private fun postOngoingCallNotification() {
+ repository.activeNotifications.value =
+ ActiveNotificationsStore.Builder()
+ .apply {
+ addIndividualNotif(
+ activeNotificationModel(
+ key = "notif1",
+ whenTime = 1000L,
+ callType = CallType.Ongoing,
+ uid = UID,
+ )
+ )
+ }
+ .build()
+ }
+
companion object {
private const val UID = 885
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaControlPanel.java
index 70ca82492775..dccf61d4e6c7 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaControlPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaControlPanel.java
@@ -1369,8 +1369,9 @@ public class MediaControlPanel {
boolean visible = mediaAction != null && !shouldBeHiddenDueToScrubbing;
int notVisibleValue;
- if ((buttonId == R.id.actionPrev && semanticActions.getReservePrev())
- || (buttonId == R.id.actionNext && semanticActions.getReserveNext())) {
+ if (!shouldBeHiddenDueToScrubbing
+ && ((buttonId == R.id.actionPrev && semanticActions.getReservePrev())
+ || (buttonId == R.id.actionNext && semanticActions.getReserveNext()))) {
notVisibleValue = ConstraintSet.INVISIBLE;
mMediaViewHolder.getAction(buttonId).setFocusable(visible);
mMediaViewHolder.getAction(buttonId).setClickable(visible);
@@ -1408,7 +1409,9 @@ public class MediaControlPanel {
// The scrubbing time views replace the SEMANTIC_ACTIONS_HIDE_WHEN_SCRUBBING action views,
// so we should only allow scrubbing times to be shown if those action views are present.
return semanticActions != null && SEMANTIC_ACTIONS_HIDE_WHEN_SCRUBBING.stream().allMatch(
- id -> semanticActions.getActionById(id) != null
+ id -> (semanticActions.getActionById(id) != null
+ || ((id == R.id.actionPrev && semanticActions.getReservePrev())
+ || (id == R.id.actionNext && semanticActions.getReserveNext())))
);
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaControlViewModel.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaControlViewModel.kt
index 4e97f2015c12..61e4d95a88e6 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaControlViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaControlViewModel.kt
@@ -316,8 +316,11 @@ class MediaControlViewModel(
isVisibleWhenScrubbing = !shouldHideWhenScrubbing,
notVisibleValue =
if (
- (buttonId == R.id.actionPrev && model.semanticActionButtons!!.reservePrev) ||
- (buttonId == R.id.actionNext && model.semanticActionButtons!!.reserveNext)
+ !shouldHideWhenScrubbing &&
+ ((buttonId == R.id.actionPrev &&
+ model.semanticActionButtons!!.reservePrev) ||
+ (buttonId == R.id.actionNext &&
+ model.semanticActionButtons!!.reserveNext))
) {
ConstraintSet.INVISIBLE
} else {
@@ -382,7 +385,9 @@ class MediaControlViewModel(
// so we should only allow scrubbing times to be shown if those action views are present.
return semanticActions?.let {
SEMANTIC_ACTIONS_HIDE_WHEN_SCRUBBING.stream().allMatch { id: Int ->
- semanticActions.getActionById(id) != null
+ semanticActions.getActionById(id) != null ||
+ (id == R.id.actionPrev && semanticActions.reservePrev ||
+ id == R.id.actionNext && semanticActions.reserveNext)
}
} ?: false
}
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
index b1719107fae1..037a1b2a97f1 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
@@ -26,6 +26,7 @@ import static com.android.systemui.classifier.Classifier.BACK_GESTURE;
import static com.android.systemui.navigationbar.gestural.Utilities.isTrackpadScroll;
import static com.android.systemui.navigationbar.gestural.Utilities.isTrackpadThreeFingerSwipe;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_TOUCHPAD_GESTURES_DISABLED;
+import static com.android.wm.shell.windowdecor.DragResizeWindowGeometry.isEdgeResizePermitted;
import static java.util.stream.Collectors.joining;
@@ -965,11 +966,14 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack
return mDesktopModeExcludeRegion.contains(x, y);
}
- private boolean isWithinTouchRegion(int x, int y) {
+ private boolean isWithinTouchRegion(MotionEvent ev) {
// If the point is inside the PiP or Nav bar overlay excluded bounds, then ignore the back
// gesture
+ int x = (int) ev.getX();
+ int y = (int) ev.getY();
final boolean isInsidePip = mIsInPip && mPipExcludedBounds.contains(x, y);
- final boolean isInDesktopExcludeRegion = desktopExcludeRegionContains(x, y);
+ final boolean isInDesktopExcludeRegion = desktopExcludeRegionContains(x, y)
+ && isEdgeResizePermitted(ev);
if (isInsidePip || isInDesktopExcludeRegion
|| mNavBarOverlayExcludedBounds.contains(x, y)) {
return false;
@@ -1098,8 +1102,7 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack
&& isValidTrackpadBackGesture(true /* isTrackpadEvent */);
} else {
mAllowGesture = isBackAllowedCommon && !mUsingThreeButtonNav && isWithinInsets
- && isWithinTouchRegion((int) ev.getX(), (int) ev.getY())
- && !isButtonPressFromTrackpad(ev);
+ && isWithinTouchRegion(ev) && !isButtonPressFromTrackpad(ev);
}
if (mAllowGesture) {
mEdgeBackPlugin.setIsLeftPanel(mIsOnLeftEdge);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
index 879e01f0ae9a..d401b6ecbfd8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
@@ -779,11 +779,15 @@ constructor(
lastIconTint = icon.getColor(state)
// Long-press effects
- longPressEffect?.qsTile?.state?.handlesLongClick = state.handlesLongClick
- if (
- state.handlesLongClick &&
- longPressEffect?.initializeEffect(longPressEffectDuration) == true
- ) {
+ updateLongPressEffect(state.handlesLongClick)
+ }
+
+ private fun updateLongPressEffect(handlesLongClick: Boolean) {
+ // The long press effect in the tile can't be updated if it is still running
+ if (longPressEffect?.state != QSLongPressEffect.State.IDLE) return
+
+ longPressEffect.qsTile?.state?.handlesLongClick = handlesLongClick
+ if (handlesLongClick && longPressEffect.initializeEffect(longPressEffectDuration)) {
showRippleEffect = false
longPressEffect.qsTile?.state?.state = lastState // Store the tile's state
longPressEffect.resetState()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarModule.kt
index 2588c7ae2363..46c84fbc19aa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarModule.kt
@@ -37,6 +37,7 @@ import com.android.systemui.statusbar.phone.StatusBarSignalPolicy
import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController
import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallLog
import com.android.systemui.statusbar.phone.ongoingcall.StatusBarChipsModernization
+import com.android.systemui.statusbar.phone.ongoingcall.domain.interactor.OngoingCallInteractor
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.statusbar.ui.SystemBarUtilsProxyImpl
import com.android.systemui.statusbar.window.MultiDisplayStatusBarWindowControllerStore
@@ -101,6 +102,19 @@ interface StatusBarModule {
@Provides
@SysUISingleton
+ @IntoMap
+ @ClassKey(OngoingCallInteractor::class)
+ fun ongoingCallInteractor(
+ interactor: OngoingCallInteractor
+ ): CoreStartable =
+ if (StatusBarChipsModernization.isEnabled) {
+ interactor
+ } else {
+ CoreStartable.NOP
+ }
+
+ @Provides
+ @SysUISingleton
fun lightBarController(store: LightBarControllerStore): LightBarController {
return store.defaultDisplay
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/domain/interactor/OngoingCallInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/domain/interactor/OngoingCallInteractor.kt
index b7ccfa01c92c..2f7b24393ae0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/domain/interactor/OngoingCallInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/domain/interactor/OngoingCallInteractor.kt
@@ -16,12 +16,15 @@
package com.android.systemui.statusbar.phone.ongoingcall.domain.interactor
+import androidx.annotation.VisibleForTesting
+import com.android.systemui.CoreStartable
import com.android.systemui.activity.data.repository.ActivityManagerRepository
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.log.LogBuffer
import com.android.systemui.log.core.Logger
import com.android.systemui.statusbar.data.repository.StatusBarModeRepositoryStore
+import com.android.systemui.statusbar.gesture.SwipeStatusBarAwayGestureHandler
import com.android.systemui.statusbar.notification.domain.interactor.ActiveNotificationsInteractor
import com.android.systemui.statusbar.notification.shared.ActiveNotificationModel
import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallLog
@@ -31,11 +34,15 @@ import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.filterIsInstance
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.stateIn
@@ -55,12 +62,19 @@ class OngoingCallInteractor @Inject constructor(
private val activityManagerRepository: ActivityManagerRepository,
private val statusBarModeRepositoryStore: StatusBarModeRepositoryStore,
private val statusBarWindowControllerStore: StatusBarWindowControllerStore,
+ private val swipeStatusBarAwayGestureHandler: SwipeStatusBarAwayGestureHandler,
activeNotificationsInteractor: ActiveNotificationsInteractor,
@OngoingCallLog private val logBuffer: LogBuffer,
-) {
+) : CoreStartable {
private val logger = Logger(logBuffer, TAG)
/**
+ * Tracks whether the call chip has been swiped away.
+ */
+ private val _isChipSwipedAway = MutableStateFlow(false)
+ val isChipSwipedAway: StateFlow<Boolean> = _isChipSwipedAway.asStateFlow()
+
+ /**
* The current state of ongoing calls.
*/
val ongoingCallState: StateFlow<OngoingCallModel> =
@@ -70,15 +84,29 @@ class OngoingCallInteractor @Inject constructor(
notification = notification
)
}
- .onEach { state ->
- setStatusBarRequiredForOngoingCall(state)
- }
.stateIn(
scope = scope,
started = SharingStarted.WhileSubscribed(),
initialValue = OngoingCallModel.NoCall
)
+ @VisibleForTesting
+ val isStatusBarRequiredForOngoingCall = combine(
+ ongoingCallState,
+ isChipSwipedAway
+ ) { callState, chipSwipedAway ->
+ callState is OngoingCallModel.InCall && !chipSwipedAway
+ }
+
+ @VisibleForTesting
+ val isGestureListeningEnabled = combine(
+ ongoingCallState,
+ statusBarModeRepositoryStore.defaultDisplay.isInFullscreenMode,
+ isChipSwipedAway
+ ) { callState, isFullscreen, chipSwipedAway ->
+ callState is OngoingCallModel.InCall && !chipSwipedAway && isFullscreen
+ }
+
private fun createOngoingCallStateFlow(
notification: ActiveNotificationModel?
): Flow<OngoingCallModel> {
@@ -99,6 +127,31 @@ class OngoingCallInteractor @Inject constructor(
}
}
+ override fun start() {
+ ongoingCallState
+ .filterIsInstance<OngoingCallModel.NoCall>()
+ .onEach {
+ _isChipSwipedAway.value = false
+ }.launchIn(scope)
+
+ isStatusBarRequiredForOngoingCall.onEach { statusBarRequired ->
+ setStatusBarRequiredForOngoingCall(statusBarRequired)
+ }.launchIn(scope)
+
+ isGestureListeningEnabled.onEach { isEnabled ->
+ updateGestureListening(isEnabled)
+ }.launchIn(scope)
+ }
+
+ /**
+ * Callback that must run when the status bar is swiped while gesture listening is active.
+ */
+ @VisibleForTesting
+ fun onStatusBarSwiped() {
+ logger.d("Status bar chip swiped away")
+ _isChipSwipedAway.value = true
+ }
+
private fun deriveOngoingCallState(
model: ActiveNotificationModel,
isVisible: Boolean
@@ -126,8 +179,7 @@ class OngoingCallInteractor @Inject constructor(
}
}
- private fun setStatusBarRequiredForOngoingCall(state: OngoingCallModel) {
- val statusBarRequired = state is OngoingCallModel.InCall
+ private fun setStatusBarRequiredForOngoingCall(statusBarRequired: Boolean) {
// TODO(b/382808183): Create a single repository that can be utilized in
// `statusBarModeRepositoryStore` and `statusBarWindowControllerStore` so we do not need
// two separate calls to force the status bar to stay visible.
@@ -138,6 +190,16 @@ class OngoingCallInteractor @Inject constructor(
.setOngoingProcessRequiresStatusBarVisible(statusBarRequired)
}
+ private fun updateGestureListening(isEnabled: Boolean) {
+ if (isEnabled) {
+ swipeStatusBarAwayGestureHandler.addOnGestureDetectedCallback(TAG) { _ ->
+ onStatusBarSwiped()
+ }
+ } else {
+ swipeStatusBarAwayGestureHandler.removeOnGestureDetectedCallback(TAG)
+ }
+ }
+
companion object {
private val TAG = "OngoingCall"
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaControlPanelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaControlPanelTest.kt
index 68a5d9361046..9543032ef5ec 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaControlPanelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaControlPanelTest.kt
@@ -247,7 +247,7 @@ public class MediaControlPanelTest : SysuiTestCase() {
mContext,
0,
intent.setPackage(mContext.packageName),
- PendingIntent.FLAG_MUTABLE
+ PendingIntent.FLAG_MUTABLE,
)
@JvmField @Rule val mockito = MockitoJUnit.rule()
@@ -294,7 +294,7 @@ public class MediaControlPanelTest : SysuiTestCase() {
override fun loadAnimator(
animId: Int,
otionInterpolator: Interpolator,
- vararg targets: View
+ vararg targets: View,
): AnimatorSet {
return mockAnimator
}
@@ -323,7 +323,7 @@ public class MediaControlPanelTest : SysuiTestCase() {
packageName = PACKAGE,
instanceId = instanceId,
recommendations = listOf(smartspaceAction, smartspaceAction, smartspaceAction),
- cardAction = smartspaceAction
+ cardAction = smartspaceAction,
)
}
@@ -370,7 +370,7 @@ public class MediaControlPanelTest : SysuiTestCase() {
packageName = PACKAGE,
token = session.sessionToken,
device = device,
- instanceId = instanceId
+ instanceId = instanceId,
)
}
@@ -416,7 +416,7 @@ public class MediaControlPanelTest : SysuiTestCase() {
action1.id,
action2.id,
action3.id,
- action4.id
+ action4.id,
)
}
@@ -536,7 +536,7 @@ public class MediaControlPanelTest : SysuiTestCase() {
playOrPause = MediaAction(icon, Runnable {}, "play", bg),
nextOrCustom = MediaAction(icon, Runnable {}, "next", bg),
custom0 = MediaAction(icon, null, "custom 0", bg),
- custom1 = MediaAction(icon, null, "custom 1", bg)
+ custom1 = MediaAction(icon, null, "custom 1", bg),
)
val state = mediaData.copy(semanticActions = semanticActions)
player.attachPlayer(viewHolder)
@@ -590,7 +590,7 @@ public class MediaControlPanelTest : SysuiTestCase() {
custom0 = MediaAction(icon, null, "custom 0", bg),
custom1 = MediaAction(icon, null, "custom 1", bg),
false,
- true
+ true,
)
val state = mediaData.copy(semanticActions = semanticActions)
@@ -622,7 +622,7 @@ public class MediaControlPanelTest : SysuiTestCase() {
custom0 = MediaAction(icon, null, "custom 0", bg),
custom1 = MediaAction(icon, null, "custom 1", bg),
true,
- false
+ false,
)
val state = mediaData.copy(semanticActions = semanticActions)
@@ -760,7 +760,7 @@ public class MediaControlPanelTest : SysuiTestCase() {
val semanticActions =
MediaButton(
playOrPause = MediaAction(icon, Runnable {}, "play", null),
- nextOrCustom = MediaAction(icon, Runnable {}, "next", null)
+ nextOrCustom = MediaAction(icon, Runnable {}, "next", null),
)
val state = mediaData.copy(semanticActions = semanticActions)
@@ -850,7 +850,7 @@ public class MediaControlPanelTest : SysuiTestCase() {
val semanticActions =
MediaButton(
prevOrCustom = MediaAction(icon, {}, "prev", null),
- nextOrCustom = MediaAction(icon, {}, "next", null)
+ nextOrCustom = MediaAction(icon, {}, "next", null),
)
val state = mediaData.copy(semanticActions = semanticActions)
@@ -921,7 +921,7 @@ public class MediaControlPanelTest : SysuiTestCase() {
val semanticActions =
MediaButton(
prevOrCustom = MediaAction(icon, {}, "prev", null),
- nextOrCustom = MediaAction(icon, {}, "next", null)
+ nextOrCustom = MediaAction(icon, {}, "next", null),
)
val state = mediaData.copy(semanticActions = semanticActions)
player.attachPlayer(viewHolder)
@@ -944,7 +944,7 @@ public class MediaControlPanelTest : SysuiTestCase() {
val semanticActions =
MediaButton(
prevOrCustom = MediaAction(icon, {}, "prev", null),
- nextOrCustom = MediaAction(icon, {}, "next", null)
+ nextOrCustom = MediaAction(icon, {}, "next", null),
)
val state = mediaData.copy(semanticActions = semanticActions)
@@ -966,6 +966,29 @@ public class MediaControlPanelTest : SysuiTestCase() {
}
@Test
+ fun setIsScrubbing_reservedButtonSpaces_scrubbingTimesShown() {
+ val semanticActions =
+ MediaButton(
+ prevOrCustom = null,
+ nextOrCustom = null,
+ reserveNext = true,
+ reservePrev = true,
+ )
+ val state = mediaData.copy(semanticActions = semanticActions)
+ player.attachPlayer(viewHolder)
+ player.bindPlayer(state, PACKAGE)
+ reset(expandedSet)
+
+ getScrubbingChangeListener().onScrubbingChanged(true)
+ mainExecutor.runAllReady()
+
+ verify(expandedSet).setVisibility(R.id.actionPrev, View.GONE)
+ verify(expandedSet).setVisibility(R.id.actionNext, View.GONE)
+ verify(expandedSet).setVisibility(R.id.media_scrubbing_elapsed_time, View.VISIBLE)
+ verify(expandedSet).setVisibility(R.id.media_scrubbing_total_time, View.VISIBLE)
+ }
+
+ @Test
fun bind_resumeState_withProgress() {
val progress = 0.5
val state = mediaData.copy(resumption = true, resumeProgress = progress)
@@ -1009,13 +1032,13 @@ public class MediaControlPanelTest : SysuiTestCase() {
MediaNotificationAction(true, actionIntent = pendingIntent, icon, "play"),
MediaNotificationAction(true, actionIntent = null, icon, "next"),
MediaNotificationAction(true, actionIntent = null, icon, "custom 0"),
- MediaNotificationAction(true, actionIntent = pendingIntent, icon, "custom 1")
+ MediaNotificationAction(true, actionIntent = pendingIntent, icon, "custom 1"),
)
val state =
mediaData.copy(
actions = actions,
actionsToShowInCompact = listOf(1, 2),
- semanticActions = null
+ semanticActions = null,
)
player.attachPlayer(viewHolder)
@@ -1701,7 +1724,7 @@ public class MediaControlPanelTest : SysuiTestCase() {
MediaNotificationAction(true, actionIntent = pendingIntent, null, "action 1"),
MediaNotificationAction(true, actionIntent = pendingIntent, null, "action 2"),
MediaNotificationAction(true, actionIntent = pendingIntent, null, "action 3"),
- MediaNotificationAction(true, actionIntent = pendingIntent, null, "action 4")
+ MediaNotificationAction(true, actionIntent = pendingIntent, null, "action 4"),
)
val data = mediaData.copy(actions = actions)
@@ -1720,7 +1743,7 @@ public class MediaControlPanelTest : SysuiTestCase() {
MediaNotificationAction(true, actionIntent = pendingIntent, null, "action 1"),
MediaNotificationAction(true, actionIntent = pendingIntent, null, "action 2"),
MediaNotificationAction(true, actionIntent = pendingIntent, null, "action 3"),
- MediaNotificationAction(true, actionIntent = pendingIntent, null, "action 4")
+ MediaNotificationAction(true, actionIntent = pendingIntent, null, "action 4"),
)
val data = mediaData.copy(actions = actions)
@@ -1739,7 +1762,7 @@ public class MediaControlPanelTest : SysuiTestCase() {
MediaNotificationAction(true, actionIntent = pendingIntent, null, "action 1"),
MediaNotificationAction(true, actionIntent = pendingIntent, null, "action 2"),
MediaNotificationAction(true, actionIntent = pendingIntent, null, "action 3"),
- MediaNotificationAction(true, actionIntent = pendingIntent, null, "action 4")
+ MediaNotificationAction(true, actionIntent = pendingIntent, null, "action 4"),
)
val data = mediaData.copy(actions = actions)
@@ -2021,7 +2044,7 @@ public class MediaControlPanelTest : SysuiTestCase() {
.setSubtitle(subtitle3)
.setIcon(icon)
.setExtras(Bundle.EMPTY)
- .build()
+ .build(),
)
)
player.bindRecommendation(data)
@@ -2047,7 +2070,7 @@ public class MediaControlPanelTest : SysuiTestCase() {
.setIcon(
Icon.createWithResource(
context,
- com.android.settingslib.R.drawable.ic_1x_mobiledata
+ com.android.settingslib.R.drawable.ic_1x_mobiledata,
)
)
.setExtras(Bundle.EMPTY)
@@ -2084,7 +2107,7 @@ public class MediaControlPanelTest : SysuiTestCase() {
.setSubtitle("fake subtitle")
.setIcon(icon)
.setExtras(Bundle.EMPTY)
- .build()
+ .build(),
)
)
player.bindRecommendation(data)
@@ -2119,7 +2142,7 @@ public class MediaControlPanelTest : SysuiTestCase() {
.setSubtitle("")
.setIcon(icon)
.setExtras(Bundle.EMPTY)
- .build()
+ .build(),
)
)
player.bindRecommendation(data)
@@ -2142,7 +2165,7 @@ public class MediaControlPanelTest : SysuiTestCase() {
.setIcon(
Icon.createWithResource(
context,
- com.android.settingslib.R.drawable.ic_1x_mobiledata
+ com.android.settingslib.R.drawable.ic_1x_mobiledata,
)
)
.setExtras(Bundle.EMPTY)
@@ -2157,11 +2180,11 @@ public class MediaControlPanelTest : SysuiTestCase() {
.setIcon(
Icon.createWithResource(
context,
- com.android.settingslib.R.drawable.ic_3g_mobiledata
+ com.android.settingslib.R.drawable.ic_3g_mobiledata,
)
)
.setExtras(Bundle.EMPTY)
- .build()
+ .build(),
)
)
@@ -2185,7 +2208,7 @@ public class MediaControlPanelTest : SysuiTestCase() {
.setIcon(
Icon.createWithResource(
context,
- com.android.settingslib.R.drawable.ic_1x_mobiledata
+ com.android.settingslib.R.drawable.ic_1x_mobiledata,
)
)
.setExtras(Bundle.EMPTY)
@@ -2200,11 +2223,11 @@ public class MediaControlPanelTest : SysuiTestCase() {
.setIcon(
Icon.createWithResource(
context,
- com.android.settingslib.R.drawable.ic_3g_mobiledata
+ com.android.settingslib.R.drawable.ic_3g_mobiledata,
)
)
.setExtras(Bundle.EMPTY)
- .build()
+ .build(),
)
)
@@ -2245,7 +2268,7 @@ public class MediaControlPanelTest : SysuiTestCase() {
.setSubtitle("subtitle1")
.setIcon(albumArt)
.setExtras(Bundle.EMPTY)
- .build()
+ .build(),
)
)
@@ -2268,7 +2291,7 @@ public class MediaControlPanelTest : SysuiTestCase() {
Bundle().apply {
putInt(
MediaConstants.DESCRIPTION_EXTRAS_KEY_COMPLETION_STATUS,
- MediaConstants.DESCRIPTION_EXTRAS_VALUE_COMPLETION_STATUS_PARTIALLY_PLAYED
+ MediaConstants.DESCRIPTION_EXTRAS_VALUE_COMPLETION_STATUS_PARTIALLY_PLAYED,
)
putDouble(MediaConstants.DESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGE, 0.5)
}
@@ -2290,7 +2313,7 @@ public class MediaControlPanelTest : SysuiTestCase() {
.setSubtitle("subtitle1")
.setIcon(albumArt)
.setExtras(Bundle.EMPTY)
- .build()
+ .build(),
)
)
@@ -2328,7 +2351,7 @@ public class MediaControlPanelTest : SysuiTestCase() {
.setSubtitle("subtitle1")
.setIcon(albumArt)
.setExtras(Bundle.EMPTY)
- .build()
+ .build(),
)
)
@@ -2381,7 +2404,7 @@ public class MediaControlPanelTest : SysuiTestCase() {
.setSubtitle("subtitle1")
.setIcon(albumArt)
.setExtras(Bundle.EMPTY)
- .build()
+ .build(),
)
)
@@ -2444,7 +2467,7 @@ public class MediaControlPanelTest : SysuiTestCase() {
icon = null,
action = {},
contentDescription = "play",
- background = null
+ background = null,
)
)
val data = mediaData.copy(semanticActions = semanticActions)
@@ -2465,7 +2488,7 @@ public class MediaControlPanelTest : SysuiTestCase() {
icon = null,
action = {},
contentDescription = "play",
- background = null
+ background = null,
)
)
val data = mediaData.copy(semanticActions = semanticActions)
@@ -2498,7 +2521,7 @@ public class MediaControlPanelTest : SysuiTestCase() {
icon = null,
action = {},
contentDescription = "play",
- background = null
+ background = null,
)
)
val data = mediaData.copy(semanticActions = semanticActions)
@@ -2530,8 +2553,8 @@ public class MediaControlPanelTest : SysuiTestCase() {
icon = null,
action = {},
contentDescription = "custom0",
- background = null
- ),
+ background = null,
+ )
)
val data = mediaData.copy(semanticActions = semanticActions)
player.attachPlayer(viewHolder)
@@ -2553,8 +2576,8 @@ public class MediaControlPanelTest : SysuiTestCase() {
icon = null,
action = {},
contentDescription = "custom0",
- background = null
- ),
+ background = null,
+ )
)
val data = mediaData.copy(semanticActions = semanticActions)
player.attachPlayer(viewHolder)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileViewImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileViewImplTest.kt
index 90ffaf19be96..67c5986fe5d8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileViewImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileViewImplTest.kt
@@ -236,7 +236,7 @@ class QSTileViewImplTest : SysuiTestCase() {
context.orCreateTestableResources.addOverride(
R.array.tile_states_internet,
- arrayOf(unavailableString, offString, onString)
+ arrayOf(unavailableString, offString, onString),
)
// State UNAVAILABLE
@@ -341,7 +341,7 @@ class QSTileViewImplTest : SysuiTestCase() {
val testA11yLabel = "TEST_LABEL"
context.orCreateTestableResources.addOverride(
R.string.accessibility_tile_disabled_by_policy_action_description,
- testA11yLabel
+ testA11yLabel,
)
val stateDisabledByPolicy = QSTile.State()
@@ -374,7 +374,7 @@ class QSTileViewImplTest : SysuiTestCase() {
context.orCreateTestableResources.addOverride(
R.array.tile_states_internet,
- arrayOf(unavailableString, offString, onString)
+ arrayOf(unavailableString, offString, onString),
)
tileView.changeState(state)
@@ -477,6 +477,24 @@ class QSTileViewImplTest : SysuiTestCase() {
}
@Test
+ fun onStateChange_fromLongPress_toNoLongPress_whileLongPressRuns_doesNotClearResources() {
+ // GIVEN that the long-press effect has been initialized
+ val state = QSTile.State()
+ state.handlesLongClick = true
+ tileView.changeState(state)
+
+ // WHEN the long-press effect is running
+ kosmos.qsLongPressEffect.setState(QSLongPressEffect.State.RUNNING_FORWARD)
+
+ // WHEN a state changed happens so that the tile no longer handles long-press
+ state.handlesLongClick = false
+ tileView.changeState(state)
+
+ // THEN the long-press effect resources are not cleared
+ assertThat(tileView.areLongPressEffectPropertiesSet).isTrue()
+ }
+
+ @Test
fun onStateChange_withoutLongPressEffect_fromLongPress_to_noLongPress_neverSetsProperties() {
// GIVEN a tile where the long-press effect is null
tileView = FakeTileView(context, false, null)
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/gesture/SwipeStatusBarAwayGestureHandlerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/gesture/SwipeStatusBarAwayGestureHandlerKosmos.kt
new file mode 100644
index 000000000000..72165c95fc55
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/gesture/SwipeStatusBarAwayGestureHandlerKosmos.kt
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2024 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.gesture
+
+import com.android.systemui.kosmos.Kosmos
+import org.mockito.kotlin.mock
+
+val Kosmos.swipeStatusBarAwayGestureHandler: SwipeStatusBarAwayGestureHandler by
+Kosmos.Fixture {
+ mock<SwipeStatusBarAwayGestureHandler>()
+} \ No newline at end of file
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/ongoingcall/domain/interactor/OngoingCallInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/ongoingcall/domain/interactor/OngoingCallInteractorKosmos.kt
index 9090e02b22b6..40d91017eeef 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/ongoingcall/domain/interactor/OngoingCallInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/ongoingcall/domain/interactor/OngoingCallInteractorKosmos.kt
@@ -21,6 +21,7 @@ import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.applicationCoroutineScope
import com.android.systemui.log.logcatLogBuffer
import com.android.systemui.statusbar.data.repository.fakeStatusBarModeRepository
+import com.android.systemui.statusbar.gesture.swipeStatusBarAwayGestureHandler
import com.android.systemui.statusbar.notification.domain.interactor.activeNotificationsInteractor
import com.android.systemui.statusbar.window.fakeStatusBarWindowControllerStore
@@ -32,6 +33,7 @@ val Kosmos.ongoingCallInteractor: OngoingCallInteractor by
activityManagerRepository = activityManagerRepository,
statusBarModeRepositoryStore = fakeStatusBarModeRepository,
statusBarWindowControllerStore = fakeStatusBarWindowControllerStore,
+ swipeStatusBarAwayGestureHandler = swipeStatusBarAwayGestureHandler,
logBuffer = logcatLogBuffer("OngoingCallInteractorKosmos"),
)
}
diff --git a/services/core/java/com/android/server/am/BroadcastController.java b/services/core/java/com/android/server/am/BroadcastController.java
index 354f281551b2..aa06b7ecf76c 100644
--- a/services/core/java/com/android/server/am/BroadcastController.java
+++ b/services/core/java/com/android/server/am/BroadcastController.java
@@ -316,8 +316,7 @@ class BroadcastController {
return null;
}
if (callerApp.info.uid != SYSTEM_UID
- && !callerApp.getPkgList().containsKey(callerPackage)
- && !"android".equals(callerPackage)) {
+ && !callerApp.getPkgList().containsKey(callerPackage)) {
throw new SecurityException("Given caller package " + callerPackage
+ " is not running in process " + callerApp);
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index 7505c710f483..424102cbdd89 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -212,11 +212,11 @@ public class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
HdmiConfig.TIMEOUT_MS);
}
- launchRoutingControl(reason != HdmiControlService.INITIATED_BY_ENABLE_CEC &&
- reason != HdmiControlService.INITIATED_BY_BOOT_UP);
resetSelectRequestBuffer();
launchDeviceDiscovery();
startQueuedActions();
+ final boolean routingForBootup = reason != HdmiControlService.INITIATED_BY_ENABLE_CEC
+ && reason != HdmiControlService.INITIATED_BY_BOOT_UP;
List<HdmiCecMessage> bufferedActiveSource = mDelayedMessageBuffer
.getBufferedMessagesWithOpcode(Constants.MESSAGE_ACTIVE_SOURCE);
if (bufferedActiveSource.isEmpty()) {
@@ -227,14 +227,8 @@ public class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
addAndStartAction(new RequestActiveSourceAction(this, new IHdmiControlCallback.Stub() {
@Override
public void onComplete(int result) {
- if (!mService.getLocalActiveSource().isValid()
- && result != HdmiControlManager.RESULT_SUCCESS) {
- mService.sendCecCommand(HdmiCecMessageBuilder.buildActiveSource(
- getDeviceInfo().getLogicalAddress(),
- getDeviceInfo().getPhysicalAddress()));
- updateActiveSource(getDeviceInfo().getLogicalAddress(),
- getDeviceInfo().getPhysicalAddress(),
- "RequestActiveSourceAction#finishWithCallback()");
+ if (result != HdmiControlManager.RESULT_SUCCESS) {
+ launchRoutingControl(routingForBootup);
}
}
}));
@@ -1384,8 +1378,7 @@ public class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
} else {
int activePath = mService.getPhysicalAddress();
setActivePath(activePath);
- if (!routingForBootup
- && !mDelayedMessageBuffer.isBuffered(Constants.MESSAGE_ACTIVE_SOURCE)) {
+ if (!mDelayedMessageBuffer.isBuffered(Constants.MESSAGE_ACTIVE_SOURCE)) {
mService.sendCecCommand(
HdmiCecMessageBuilder.buildActiveSource(
getDeviceInfo().getLogicalAddress(), activePath));
diff --git a/services/core/java/com/android/server/pm/RestrictionsSet.java b/services/core/java/com/android/server/pm/RestrictionsSet.java
index 08047695a42a..38075c135d2a 100644
--- a/services/core/java/com/android/server/pm/RestrictionsSet.java
+++ b/services/core/java/com/android/server/pm/RestrictionsSet.java
@@ -65,6 +65,7 @@ public class RestrictionsSet {
throw new IllegalArgumentException("empty restriction bundle cannot be added.");
}
mUserRestrictions.put(userId, restrictions);
+ UserManager.invalidateUserRestriction();
}
/**
@@ -84,6 +85,7 @@ public class RestrictionsSet {
} else {
mUserRestrictions.delete(userId);
}
+ UserManager.invalidateUserRestriction();
return true;
}
@@ -102,6 +104,9 @@ public class RestrictionsSet {
removed = true;
}
}
+ if (removed) {
+ UserManager.invalidateUserRestriction();
+ }
return removed;
}
@@ -129,6 +134,7 @@ public class RestrictionsSet {
i--;
}
}
+ UserManager.invalidateUserRestriction();
}
}
@@ -192,6 +198,7 @@ public class RestrictionsSet {
public boolean remove(@UserIdInt int userId) {
boolean hasUserRestriction = mUserRestrictions.contains(userId);
mUserRestrictions.remove(userId);
+ UserManager.invalidateUserRestriction();
return hasUserRestriction;
}
@@ -200,6 +207,7 @@ public class RestrictionsSet {
*/
public void removeAllRestrictions() {
mUserRestrictions.clear();
+ UserManager.invalidateUserRestriction();
}
/**
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 066fce068d61..8249d65868cd 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -1113,6 +1113,7 @@ public class UserManagerService extends IUserManager.Stub {
UserManager.invalidateUserPropertiesCache();
}
UserManager.invalidateCacheOnUserListChange();
+ UserManager.invalidateUserRestriction();
}
}
diff --git a/services/core/java/com/android/server/power/hint/HintManagerService.java b/services/core/java/com/android/server/power/hint/HintManagerService.java
index 7c7504dccf94..aae7417970eb 100644
--- a/services/core/java/com/android/server/power/hint/HintManagerService.java
+++ b/services/core/java/com/android/server/power/hint/HintManagerService.java
@@ -297,7 +297,11 @@ public final class HintManagerService extends SystemService {
mPowerHalVersion = 0;
mUsesFmq = false;
if (mPowerHal != null) {
- mSupportInfo = getSupportInfo();
+ try {
+ mSupportInfo = getSupportInfo();
+ } catch (RemoteException e) {
+ throw new IllegalStateException("Could not contact PowerHAL!", e);
+ }
}
mDefaultCpuHeadroomCalculationWindowMillis =
new CpuHeadroomParamsInternal().calculationWindowMillis;
@@ -315,7 +319,7 @@ public final class HintManagerService extends SystemService {
}
}
- SupportInfo getSupportInfo() {
+ SupportInfo getSupportInfo() throws RemoteException {
try {
mPowerHalVersion = mPowerHal.getInterfaceVersion();
if (mPowerHalVersion >= 6) {
@@ -326,9 +330,42 @@ public final class HintManagerService extends SystemService {
}
SupportInfo supportInfo = new SupportInfo();
+ supportInfo.usesSessions = isHintSessionSupported();
+ // Global boosts & modes aren't currently relevant for HMS clients
+ supportInfo.boosts = 0;
+ supportInfo.modes = 0;
+ supportInfo.sessionHints = 0;
+ supportInfo.sessionModes = 0;
+ supportInfo.sessionTags = 0;
+
supportInfo.headroom = new SupportInfo.HeadroomSupportInfo();
supportInfo.headroom.isCpuSupported = false;
supportInfo.headroom.isGpuSupported = false;
+
+ supportInfo.compositionData = new SupportInfo.CompositionDataSupportInfo();
+ if (isHintSessionSupported()) {
+ if (mPowerHalVersion == 4) {
+ // Assume we support the V4 hints & modes unless specified
+ // otherwise; this is to avoid breaking backwards compat
+ // since we historically just assumed they were.
+ supportInfo.sessionHints = 31; // first 5 bits are ones
+ }
+ if (mPowerHalVersion == 5) {
+ // Assume we support the V5 hints & modes unless specified
+ // otherwise; this is to avoid breaking backwards compat
+ // since we historically just assumed they were.
+
+ // Hal V5 has 8 modes, all of which it assumes are supported,
+ // so we represent that by having the first 8 bits set
+ supportInfo.sessionHints = 255; // first 8 bits are ones
+ // Hal V5 has 1 mode which it assumes is supported, so we
+ // represent that by having the first bit set
+ supportInfo.sessionModes = 1;
+ // Hal V5 has 5 tags, all of which it assumes are supported,
+ // so we represent that by having the first 5 bits set
+ supportInfo.sessionTags = 31;
+ }
+ }
return supportInfo;
}
@@ -1229,7 +1266,7 @@ public final class HintManagerService extends SystemService {
@SessionTag int tag, SessionCreationConfig creationConfig,
SessionConfig config) {
if (!isHintSessionSupported()) {
- throw new UnsupportedOperationException("PowerHAL is not supported!");
+ throw new UnsupportedOperationException("PowerHintSessions are not supported!");
}
java.util.Objects.requireNonNull(token);
@@ -1425,12 +1462,6 @@ public final class HintManagerService extends SystemService {
removeChannelItem(callingTgid, callingUid);
};
- @Override
- public long getHintSessionPreferredRate() {
- return mHintSessionPreferredRate;
- }
-
- @Override
public int getMaxGraphicsPipelineThreadsCount() {
return MAX_GRAPHICS_PIPELINE_THREADS_COUNT;
}
@@ -1621,13 +1652,24 @@ public final class HintManagerService extends SystemService {
}
@Override
+ public IHintManager.HintManagerClientData
+ registerClient(@NonNull IHintManager.IHintManagerClient clientBinder) {
+ IHintManager.HintManagerClientData out = new IHintManager.HintManagerClientData();
+ out.preferredRateNanos = mHintSessionPreferredRate;
+ out.maxGraphicsPipelineThreads = getMaxGraphicsPipelineThreadsCount();
+ out.powerHalVersion = mPowerHalVersion;
+ out.supportInfo = mSupportInfo;
+ return out;
+ }
+
+ @Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (!DumpUtils.checkDumpPermission(getContext(), TAG, pw)) {
return;
}
pw.println("HintSessionPreferredRate: " + mHintSessionPreferredRate);
pw.println("MaxGraphicsPipelineThreadsCount: " + MAX_GRAPHICS_PIPELINE_THREADS_COUNT);
- pw.println("HAL Support: " + isHintSessionSupported());
+ pw.println("Hint Session Support: " + isHintSessionSupported());
pw.println("Active Sessions:");
synchronized (mLock) {
for (int i = 0; i < mActiveSessions.size(); i++) {
diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
index 27d32bedfecb..0aff1de72cb1 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
@@ -1269,7 +1269,8 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
// Checks if the caller can be shown in the given public display.
int userId = UserHandle.getUserId(callingUid);
int displayId = display.getDisplayId();
- boolean allowed = mWindowManager.mUmInternal.isUserVisible(userId, displayId);
+ boolean allowed = userId == UserHandle.USER_SYSTEM
+ || mWindowManager.mUmInternal.isUserVisible(userId, displayId);
ProtoLog.d(WM_DEBUG_TASKS,
"Launch on display check: %s launch for userId=%d on displayId=%d",
(allowed ? "allow" : "disallow"), userId, displayId);
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index 82699ea3badb..01639cc3b516 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -61,6 +61,7 @@ cc_library_static {
"com_android_server_SystemServer.cpp",
"com_android_server_tv_TvUinputBridge.cpp",
"com_android_server_tv_TvInputHal.cpp",
+ "com_android_server_UsbAlsaDevice.cpp",
"com_android_server_UsbAlsaJackDetector.cpp",
"com_android_server_UsbAlsaMidiDevice.cpp",
"com_android_server_UsbDeviceManager.cpp",
diff --git a/services/core/jni/com_android_server_UsbAlsaDevice.cpp b/services/core/jni/com_android_server_UsbAlsaDevice.cpp
new file mode 100644
index 000000000000..166932f167ed
--- /dev/null
+++ b/services/core/jni/com_android_server_UsbAlsaDevice.cpp
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+#define LOG_TAG "UsbAlsaDeviceJNI"
+
+#include <nativehelper/JNIPlatformHelp.h>
+#include <tinyalsa/asoundlib.h>
+
+#include <string>
+#include <vector>
+
+#include "jni.h"
+#include "utils/Log.h"
+
+static const std::vector<std::string> POSSIBLE_HARDWARE_VOLUME_MIXER_NAMES =
+ {"Headphone Playback Volume", "Headset Playback Volume", "PCM Playback Volume"};
+
+namespace android {
+
+static void android_server_UsbAlsaDevice_setVolume(JNIEnv* /*env*/, jobject /*thiz*/, jint card,
+ float volume) {
+ ALOGD("%s(%d, %f)", __func__, card, volume);
+ struct mixer* alsaMixer = mixer_open(card);
+ if (alsaMixer == nullptr) {
+ ALOGW("%s(%d, %f) returned as no mixer is opened", __func__, card, volume);
+ return;
+ }
+ struct mixer_ctl* ctl = nullptr;
+ for (const auto& mixerName : POSSIBLE_HARDWARE_VOLUME_MIXER_NAMES) {
+ ctl = mixer_get_ctl_by_name(alsaMixer, mixerName.c_str());
+ if (ctl != nullptr) {
+ break;
+ }
+ }
+ if (ctl == nullptr) {
+ ALOGW("%s(%d, %f) returned as no volume mixer is found", __func__, card, volume);
+ return;
+ }
+ const unsigned int n = mixer_ctl_get_num_values(ctl);
+ for (unsigned int id = 0; id < n; id++) {
+ if (int error = mixer_ctl_set_percent(ctl, id, 100 * volume); error != 0) {
+ ALOGE("%s(%d, %f) failed, error=%d", __func__, card, volume, error);
+ return;
+ }
+ }
+ ALOGD("%s(%d, %f) succeed", __func__, card, volume);
+}
+
+static JNINativeMethod method_table[] = {
+ {"nativeSetVolume", "(IF)V", (void*)android_server_UsbAlsaDevice_setVolume},
+};
+
+int register_android_server_UsbAlsaDevice(JNIEnv* env) {
+ return jniRegisterNativeMethods(env, "com/android/server/usb/UsbAlsaDevice", method_table,
+ NELEM(method_table));
+}
+} // namespace android
diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp
index 09fd8d4ac02e..e3bd69c30de7 100644
--- a/services/core/jni/onload.cpp
+++ b/services/core/jni/onload.cpp
@@ -33,6 +33,7 @@ int register_android_server_power_stats_CpuPowerStatsCollector(JNIEnv* env);
int register_android_server_HintManagerService(JNIEnv* env);
int register_android_server_storage_AppFuse(JNIEnv* env);
int register_android_server_SystemServer(JNIEnv* env);
+int register_android_server_UsbAlsaDevice(JNIEnv* env);
int register_android_server_UsbAlsaJackDetector(JNIEnv* env);
int register_android_server_UsbAlsaMidiDevice(JNIEnv* env);
int register_android_server_UsbDeviceManager(JavaVM* vm, JNIEnv* env);
@@ -98,6 +99,7 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
register_android_server_InputManager(env);
register_android_server_LightsService(env);
register_android_server_UsbDeviceManager(vm, env);
+ register_android_server_UsbAlsaDevice(env);
register_android_server_UsbAlsaJackDetector(env);
register_android_server_UsbAlsaMidiDevice(env);
register_android_server_UsbHostManager(env);
diff --git a/services/tests/performancehinttests/src/com/android/server/power/hint/HintManagerServiceTest.java b/services/tests/performancehinttests/src/com/android/server/power/hint/HintManagerServiceTest.java
index 5c73fd33f46f..4b2e850d08e7 100644
--- a/services/tests/performancehinttests/src/com/android/server/power/hint/HintManagerServiceTest.java
+++ b/services/tests/performancehinttests/src/com/android/server/power/hint/HintManagerServiceTest.java
@@ -64,6 +64,7 @@ import android.os.Binder;
import android.os.CpuHeadroomParamsInternal;
import android.os.GpuHeadroomParamsInternal;
import android.os.IBinder;
+import android.os.IHintManager;
import android.os.IHintSession;
import android.os.PerformanceHintManager;
import android.os.Process;
@@ -154,6 +155,8 @@ public class HintManagerServiceTest {
private ActivityManagerInternal mAmInternalMock;
@Mock
private PackageManager mMockPackageManager;
+ @Mock
+ private IHintManager.IHintManagerClient mClientCallback;
@Rule
public final CheckFlagsRule mCheckFlagsRule =
DeviceFlagsValueProvider.createCheckFlagsRule();
@@ -171,6 +174,24 @@ public class HintManagerServiceTest {
};
}
+ private SupportInfo makeDefaultSupportInfo() {
+ mSupportInfo = new SupportInfo();
+ mSupportInfo.usesSessions = true;
+ // By default, mark everything as fully supported
+ mSupportInfo.sessionHints = -1;
+ mSupportInfo.sessionModes = -1;
+ mSupportInfo.modes = -1;
+ mSupportInfo.boosts = -1;
+ mSupportInfo.sessionTags = -1;
+ mSupportInfo.headroom = new SupportInfo.HeadroomSupportInfo();
+ mSupportInfo.headroom.isCpuSupported = true;
+ mSupportInfo.headroom.cpuMinIntervalMillis = 2000;
+ mSupportInfo.headroom.isGpuSupported = true;
+ mSupportInfo.headroom.gpuMinIntervalMillis = 2000;
+ mSupportInfo.compositionData = new SupportInfo.CompositionDataSupportInfo();
+ return mSupportInfo;
+ }
+
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
@@ -181,12 +202,7 @@ public class HintManagerServiceTest {
mConfig.eventFlagDescriptor = new MQDescriptor<Byte, Byte>();
ApplicationInfo applicationInfo = new ApplicationInfo();
applicationInfo.category = ApplicationInfo.CATEGORY_GAME;
- mSupportInfo = new SupportInfo();
- mSupportInfo.headroom = new SupportInfo.HeadroomSupportInfo();
- mSupportInfo.headroom.isCpuSupported = true;
- mSupportInfo.headroom.cpuMinIntervalMillis = 2000;
- mSupportInfo.headroom.isGpuSupported = true;
- mSupportInfo.headroom.gpuMinIntervalMillis = 2000;
+ mSupportInfo = makeDefaultSupportInfo();
when(mContext.getPackageManager()).thenReturn(mMockPackageManager);
when(mMockPackageManager.getNameForUid(anyInt())).thenReturn(TEST_APP_NAME);
when(mMockPackageManager.getApplicationInfo(eq(TEST_APP_NAME), anyInt()))
@@ -215,6 +231,7 @@ public class HintManagerServiceTest {
when(mIPowerMock.getInterfaceVersion()).thenReturn(6);
when(mIPowerMock.getSupportInfo()).thenReturn(mSupportInfo);
when(mIPowerMock.getSessionChannel(anyInt(), anyInt())).thenReturn(mConfig);
+ when(mIPowerMock.getSupportInfo()).thenReturn(mSupportInfo);
LocalServices.removeServiceForTest(ActivityManagerInternal.class);
LocalServices.addService(ActivityManagerInternal.class, mAmInternalMock);
}
@@ -409,8 +426,11 @@ public class HintManagerServiceTest {
HintManagerService service = createService();
IBinder token = new Binder();
- final int threadCount =
- service.getBinderServiceInstance().getMaxGraphicsPipelineThreadsCount();
+ IHintManager.HintManagerClientData data = service.getBinderServiceInstance()
+ .registerClient(mClientCallback);
+
+ final int threadCount = data.maxGraphicsPipelineThreads;
+
long sessionPtr1 = 1111L;
long sessionId1 = 11111L;
CountDownLatch stopLatch1 = new CountDownLatch(1);
@@ -1447,4 +1467,67 @@ public class HintManagerServiceTest {
verify(mIPowerMock, times(1)).getGpuHeadroom(eq(halParams1));
verify(mIPowerMock, times(1)).getGpuHeadroom(eq(halParams2));
}
+
+ @Test
+ public void testRegisteringClient() throws Exception {
+ HintManagerService service = createService();
+ IHintManager.HintManagerClientData data = service.getBinderServiceInstance()
+ .registerClient(mClientCallback);
+ assertNotNull(data);
+ assertEquals(data.supportInfo, mSupportInfo);
+ }
+
+ @Test
+ public void testRegisteringClientOnV4() throws Exception {
+ when(mIPowerMock.getInterfaceVersion()).thenReturn(4);
+ HintManagerService service = createService();
+ IHintManager.HintManagerClientData data = service.getBinderServiceInstance()
+ .registerClient(mClientCallback);
+ assertNotNull(data);
+ assertEquals(data.supportInfo.usesSessions, true);
+ assertEquals(data.supportInfo.boosts, 0);
+ assertEquals(data.supportInfo.modes, 0);
+ assertEquals(data.supportInfo.sessionHints, 31);
+ assertEquals(data.supportInfo.sessionModes, 0);
+ assertEquals(data.supportInfo.sessionTags, 0);
+ assertEquals(data.powerHalVersion, 4);
+ assertEquals(data.preferredRateNanos, DEFAULT_HINT_PREFERRED_RATE);
+ }
+
+ @Test
+ public void testRegisteringClientOnV5() throws Exception {
+ when(mIPowerMock.getInterfaceVersion()).thenReturn(5);
+ HintManagerService service = createService();
+ IHintManager.HintManagerClientData data = service.getBinderServiceInstance()
+ .registerClient(mClientCallback);
+ assertNotNull(data);
+ assertEquals(data.supportInfo.usesSessions, true);
+ assertEquals(data.supportInfo.boosts, 0);
+ assertEquals(data.supportInfo.modes, 0);
+ assertEquals(data.supportInfo.sessionHints, 255);
+ assertEquals(data.supportInfo.sessionModes, 1);
+ assertEquals(data.supportInfo.sessionTags, 31);
+ assertEquals(data.powerHalVersion, 5);
+ assertEquals(data.preferredRateNanos, DEFAULT_HINT_PREFERRED_RATE);
+ }
+
+ @Test
+ public void testSettingUpOldClientWhenUnsupported() throws Exception {
+ when(mIPowerMock.getInterfaceVersion()).thenReturn(5);
+ // Mock unsupported to modify the default support behavior
+ when(mNativeWrapperMock.halGetHintSessionPreferredRate())
+ .thenReturn(-1L);
+ HintManagerService service = createService();
+ IHintManager.HintManagerClientData data = service.getBinderServiceInstance()
+ .registerClient(mClientCallback);
+ assertNotNull(data);
+ assertEquals(data.supportInfo.usesSessions, false);
+ assertEquals(data.supportInfo.boosts, 0);
+ assertEquals(data.supportInfo.modes, 0);
+ assertEquals(data.supportInfo.sessionHints, 0);
+ assertEquals(data.supportInfo.sessionModes, 0);
+ assertEquals(data.supportInfo.sessionTags, 0);
+ assertEquals(data.powerHalVersion, 5);
+ assertEquals(data.preferredRateNanos, -1);
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerCacheTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerCacheTest.java
index d69e47684f8b..9b878b349618 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerCacheTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerCacheTest.java
@@ -19,6 +19,7 @@ package com.android.server.pm;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assume.assumeTrue;
+import static org.junit.Assert.fail;
import android.app.ActivityManager;
import android.app.LocaleManager;
@@ -26,6 +27,7 @@ import android.content.Context;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.multiuser.Flags;
+import android.os.Bundle;
import android.os.LocaleList;
import android.os.SystemClock;
import android.os.UserHandle;
@@ -261,6 +263,162 @@ public final class UserManagerCacheTest {
assertThat(um.getUserName()).isEqualTo(newName);
}
+
+ @MediumTest
+ @Test
+ public void testDefaultRestrictionsApplied() throws Exception {
+ final UserInfo userInfo = mUserManager.createUser("Useroid",
+ UserManager.USER_TYPE_FULL_SECONDARY, 0);
+ mUsersToRemove.add(userInfo.id);
+ final UserTypeDetails userTypeDetails =
+ UserTypeFactory.getUserTypes().get(UserManager.USER_TYPE_FULL_SECONDARY);
+ final Bundle expectedRestrictions = userTypeDetails.getDefaultRestrictions();
+ // Note this can fail if DO unset those restrictions.
+ for (String restriction : expectedRestrictions.keySet()) {
+ if (expectedRestrictions.getBoolean(restriction)) {
+ assertThat(mUserManager.hasUserRestriction(restriction, UserHandle.of(userInfo.id)))
+ .isTrue();
+ // Test cached value
+ assertThat(mUserManager.hasUserRestriction(restriction, UserHandle.of(userInfo.id)))
+ .isTrue();
+ }
+ }
+ }
+
+ @MediumTest
+ @Test
+ public void testSetDefaultGuestRestrictions() {
+ final Bundle origRestrictions = mUserManager.getDefaultGuestRestrictions();
+ try {
+ final boolean isFunDisallowed = origRestrictions.getBoolean(UserManager.DISALLOW_FUN,
+ false);
+ final UserInfo guest1 = mUserManager.createUser("Guest 1", UserInfo.FLAG_GUEST);
+ assertThat(guest1).isNotNull();
+ assertThat(mUserManager.hasUserRestriction(UserManager.DISALLOW_FUN,
+ guest1.getUserHandle())).isEqualTo(isFunDisallowed);
+ removeUser(guest1.id, true);
+ // Cache return false after user was removed
+ assertThat(mUserManager.hasUserRestriction(UserManager.DISALLOW_FUN,
+ guest1.getUserHandle())).isFalse();
+
+ Bundle restrictions = new Bundle();
+ restrictions.putBoolean(UserManager.DISALLOW_FUN, !isFunDisallowed);
+ mUserManager.setDefaultGuestRestrictions(restrictions);
+ UserInfo guest2 = mUserManager.createUser("Guest 2", UserInfo.FLAG_GUEST);
+ assertThat(guest2).isNotNull();
+ assertThat(mUserManager.hasUserRestriction(UserManager.DISALLOW_FUN,
+ guest2.getUserHandle())).isNotEqualTo(isFunDisallowed);
+ removeUser(guest2.id, true);
+ assertThat(mUserManager.getUserInfo(guest2.id)).isNull();
+ assertThat(mUserManager.hasUserRestriction(UserManager.DISALLOW_FUN,
+ guest2.getUserHandle())).isFalse();
+ } finally {
+ mUserManager.setDefaultGuestRestrictions(origRestrictions);
+ }
+ }
+
+ @MediumTest
+ @Test
+ public void testCacheInvalidatedAfterUserAddedOrRemoved() {
+ final Bundle origRestrictions = mUserManager.getDefaultGuestRestrictions();
+ try {
+ final boolean isFunDisallowed = origRestrictions.getBoolean(UserManager.DISALLOW_FUN,
+ false);
+ final UserInfo guest1 = mUserManager.createUser("Guest 1", UserInfo.FLAG_GUEST);
+ assertThat(guest1).isNotNull();
+ assertThat(mUserManager.hasUserRestriction(UserManager.DISALLOW_FUN,
+ guest1.getUserHandle())).isEqualTo(isFunDisallowed);
+ removeUser(guest1.id, true);
+
+ Bundle restrictions = new Bundle();
+ restrictions.putBoolean(UserManager.DISALLOW_FUN, !isFunDisallowed);
+ mUserManager.setDefaultGuestRestrictions(restrictions);
+ int latest_id = guest1.id;
+ // Cache removed id and few next ids.
+ assertThat(mUserManager.hasUserRestriction(UserManager.DISALLOW_FUN,
+ UserHandle.of(latest_id))).isFalse();
+ assertThat(mUserManager.hasUserRestriction(UserManager.DISALLOW_FUN,
+ UserHandle.of(latest_id + 1))).isFalse();
+ assertThat(mUserManager.hasUserRestriction(UserManager.DISALLOW_FUN,
+ UserHandle.of(latest_id + 2))).isFalse();
+ assertThat(mUserManager.hasUserRestriction(UserManager.DISALLOW_FUN,
+ UserHandle.of(latest_id + 3))).isFalse();
+
+ UserInfo guest2 = mUserManager.createUser("Guest 2", UserInfo.FLAG_GUEST);
+ assertThat(guest2).isNotNull();
+ // Cache was invalidated after user was added
+ assertThat(mUserManager.hasUserRestriction(UserManager.DISALLOW_FUN,
+ guest2.getUserHandle())).isTrue();
+ removeUser(guest2.id, true);
+ assertThat(mUserManager.getUserInfo(guest2.id)).isNull();
+ // Cache was invalidated after user was removed
+ assertThat(mUserManager.hasUserRestriction(UserManager.DISALLOW_FUN,
+ guest2.getUserHandle())).isFalse();
+ } finally {
+ mUserManager.setDefaultGuestRestrictions(origRestrictions);
+ }
+ }
+
+
+ @MediumTest
+ @Test
+ public void testAddRemoveUsersAndRestrictions() {
+ try {
+ final UserInfo userInfo = mUserManager.createUser("Useroid",
+ UserManager.USER_TYPE_FULL_SECONDARY, 0);
+ mUsersToRemove.add(userInfo.id);
+ assertThat(mUserManager.hasUserRestriction(UserManager.DISALLOW_FUN,
+ userInfo.getUserHandle())).isFalse();
+ mUserManager.setUserRestriction(UserManager.DISALLOW_FUN, true,
+ userInfo.getUserHandle());
+
+ assertThat(mUserManager.hasUserRestriction(UserManager.DISALLOW_FUN,
+ userInfo.getUserHandle())).isTrue();
+ removeUser(userInfo.id, true);
+ assertThat(mUserManager.getUserSerialNumber(userInfo.id)).isEqualTo(-1);
+ assertThat(mUserManager.getUserInfo(userInfo.id)).isNull();
+ assertThat(mUserManager.hasUserRestriction(UserManager.DISALLOW_FUN,
+ userInfo.getUserHandle())).isFalse();
+ } catch (java.lang.Exception e) {
+ }
+ }
+
+
+ private void sleep(long millis) {
+ try {
+ Thread.sleep(millis);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+
+ @MediumTest
+ @Test
+ public void testDefaultUserRestrictionsForPrivateProfile() {
+ assumeTrue(mUserManager.canAddPrivateProfile());
+ final int currentUserId = ActivityManager.getCurrentUser();
+ UserInfo privateProfileInfo = null;
+ try {
+ privateProfileInfo = mUserManager.createProfileForUser(
+ "Private", UserManager.USER_TYPE_PROFILE_PRIVATE, 0, currentUserId, null);
+ assertThat(privateProfileInfo).isNotNull();
+ } catch (Exception e) {
+ fail("Creation of private profile failed due to " + e.getMessage());
+ }
+ assertDefaultPrivateProfileRestrictions(privateProfileInfo.getUserHandle());
+ // Assert cached values
+ assertDefaultPrivateProfileRestrictions(privateProfileInfo.getUserHandle());
+ }
+
+ private void assertDefaultPrivateProfileRestrictions(UserHandle userHandle) {
+ Bundle defaultPrivateProfileRestrictions =
+ UserTypeFactory.getDefaultPrivateProfileRestrictions();
+ for (String restriction : defaultPrivateProfileRestrictions.keySet()) {
+ assertThat(mUserManager.hasUserRestrictionForUser(restriction, userHandle)).isTrue();
+ }
+ }
+
private void assumeManagedUsersSupported() {
// In Automotive, if headless system user is enabled, a managed user cannot be created
// under a primary user.
@@ -270,9 +428,23 @@ public final class UserManagerCacheTest {
}
private void removeUser(int userId) {
+ removeUser(userId, false);
+ }
+
+ private void removeUser(int userId, boolean waitForCompleteRemoval) {
mUserManager.removeUser(userId);
mUserRemovalWaiter.waitFor(userId);
mUsersToRemove.remove(userId);
+ if (waitForCompleteRemoval) {
+ int serialNumber = mUserManager.getUserSerialNumber(userId);
+ int timeout = REMOVE_USER_TIMEOUT_SECONDS * 5; // called every 200ms
+ // Wait for the user to be removed from memory
+ while (serialNumber > 0 && timeout > 0) {
+ sleep(200);
+ timeout--;
+ serialNumber = mUserManager.getUserSerialNumber(userId);
+ }
+ }
}
private boolean isAutomotive() {
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index 661d07e09f99..5cb741fe81d4 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -2472,11 +2472,14 @@ public class ActivityRecordTests extends WindowTestsBase {
final ActivityRecord activity = new ActivityBuilder(mAtm).setCreateTask(true).build();
assertEquals(0, activity.getChildCount());
- final WindowState win1 = createWindow(null, TYPE_APPLICATION, activity, "win1");
- final WindowState startingWin = createWindow(null, TYPE_APPLICATION_STARTING, activity,
- "startingWin");
- final WindowState baseWin = createWindow(null, TYPE_BASE_APPLICATION, activity, "baseWin");
- final WindowState win4 = createWindow(null, TYPE_APPLICATION, activity, "win4");
+ final WindowState win1 = newWindowBuilder("app1", TYPE_APPLICATION).setWindowToken(
+ activity).build();
+ final WindowState startingWin = newWindowBuilder("startingWin",
+ TYPE_APPLICATION_STARTING).setWindowToken(activity).build();
+ final WindowState baseWin = newWindowBuilder("baseWin",
+ TYPE_BASE_APPLICATION).setWindowToken(activity).build();
+ final WindowState win4 = newWindowBuilder("win4", TYPE_APPLICATION).setWindowToken(
+ activity).build();
// Should not contain the windows that were added above.
assertEquals(4, activity.getChildCount());
@@ -2499,14 +2502,17 @@ public class ActivityRecordTests extends WindowTestsBase {
final ActivityRecord activity = new ActivityBuilder(mAtm).setCreateTask(true).build();
assertNull(activity.findMainWindow());
- final WindowState window1 = createWindow(null, TYPE_BASE_APPLICATION, activity, "window1");
- final WindowState window11 = createWindow(window1, FIRST_SUB_WINDOW, activity, "window11");
- final WindowState window12 = createWindow(window1, FIRST_SUB_WINDOW, activity, "window12");
+ final WindowState window1 = newWindowBuilder("window1",
+ TYPE_BASE_APPLICATION).setWindowToken(activity).build();
+ final WindowState window11 = newWindowBuilder("window11", FIRST_SUB_WINDOW).setParent(
+ window1).setWindowToken(activity).build();
+ final WindowState window12 = newWindowBuilder("window12", FIRST_SUB_WINDOW).setParent(
+ window1).setWindowToken(activity).build();
assertEquals(window1, activity.findMainWindow());
window1.mAnimatingExit = true;
assertEquals(window1, activity.findMainWindow());
- final WindowState window2 = createWindow(null, TYPE_APPLICATION_STARTING, activity,
- "window2");
+ final WindowState window2 = newWindowBuilder("window2",
+ TYPE_APPLICATION_STARTING).setWindowToken(activity).build();
assertEquals(window2, activity.findMainWindow());
activity.removeImmediately();
}
@@ -2651,8 +2657,8 @@ public class ActivityRecordTests extends WindowTestsBase {
@Test
public void testStuckExitingWindow() {
- final WindowState closingWindow = createWindow(null, FIRST_APPLICATION_WINDOW,
- "closingWindow");
+ final WindowState closingWindow = newWindowBuilder("closingWindow",
+ FIRST_APPLICATION_WINDOW).build();
closingWindow.mAnimatingExit = true;
closingWindow.mRemoveOnExit = true;
closingWindow.mActivityRecord.commitVisibility(
@@ -3313,7 +3319,7 @@ public class ActivityRecordTests extends WindowTestsBase {
@SetupWindows(addWindows = W_INPUT_METHOD)
@Test
public void testImeInsetsFrozenFlag_resetWhenNoImeFocusableInActivity() {
- final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
+ final WindowState app = newWindowBuilder("app", TYPE_APPLICATION).build();
makeWindowVisibleAndDrawn(app, mImeWindow);
mDisplayContent.setImeLayeringTarget(app);
mDisplayContent.setImeInputTarget(app);
@@ -3341,7 +3347,7 @@ public class ActivityRecordTests extends WindowTestsBase {
@SetupWindows(addWindows = W_INPUT_METHOD)
@Test
public void testImeInsetsFrozenFlag_resetWhenReportedToBeImeInputTarget() {
- final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
+ final WindowState app = newWindowBuilder("app", TYPE_APPLICATION).build();
mDisplayContent.getInsetsStateController().getImeSourceProvider().setWindowContainer(
mImeWindow, null, null);
@@ -3385,8 +3391,8 @@ public class ActivityRecordTests extends WindowTestsBase {
@Test
public void testImeInsetsFrozenFlag_noDispatchVisibleInsetsWhenAppNotRequest()
throws RemoteException {
- final WindowState app1 = createWindow(null, TYPE_APPLICATION, "app1");
- final WindowState app2 = createWindow(null, TYPE_APPLICATION, "app2");
+ final WindowState app1 = newWindowBuilder("app1", TYPE_APPLICATION).build();
+ final WindowState app2 = newWindowBuilder("app2", TYPE_APPLICATION).build();
mDisplayContent.getInsetsStateController().getImeSourceProvider().setWindowContainer(
mImeWindow, null, null);
@@ -3430,7 +3436,8 @@ public class ActivityRecordTests extends WindowTestsBase {
@Test
public void testImeInsetsFrozenFlag_multiWindowActivities() {
final WindowToken imeToken = createTestWindowToken(TYPE_INPUT_METHOD, mDisplayContent);
- final WindowState ime = createWindow(null, TYPE_INPUT_METHOD, imeToken, "ime");
+ final WindowState ime = newWindowBuilder("ime", TYPE_INPUT_METHOD).setWindowToken(
+ imeToken).build();
makeWindowVisibleAndDrawn(ime);
// Create a split-screen root task with activity1 and activity 2.
@@ -3451,8 +3458,10 @@ public class ActivityRecordTests extends WindowTestsBase {
activity1.mImeInsetsFrozenUntilStartInput = true;
activity2.mImeInsetsFrozenUntilStartInput = true;
- final WindowState app1 = createWindow(null, TYPE_APPLICATION, activity1, "app1");
- final WindowState app2 = createWindow(null, TYPE_APPLICATION, activity2, "app2");
+ final WindowState app1 = newWindowBuilder("app1", TYPE_APPLICATION).setWindowToken(
+ activity1).build();
+ final WindowState app2 = newWindowBuilder("app2", TYPE_APPLICATION).setWindowToken(
+ activity2).build();
makeWindowVisibleAndDrawn(app1, app2);
final InsetsStateController controller = mDisplayContent.getInsetsStateController();
@@ -3481,7 +3490,7 @@ public class ActivityRecordTests extends WindowTestsBase {
@Test
public void testInClosingAnimation_visibilityNotCommitted_doNotHideSurface() {
- final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
+ final WindowState app = newWindowBuilder("app", TYPE_APPLICATION).build();
makeWindowVisibleAndDrawn(app);
// Put the activity in close transition.
@@ -3508,7 +3517,7 @@ public class ActivityRecordTests extends WindowTestsBase {
@Test
public void testInClosingAnimation_visibilityCommitted_hideSurface() {
- final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
+ final WindowState app = newWindowBuilder("app", TYPE_APPLICATION).build();
makeWindowVisibleAndDrawn(app);
app.mActivityRecord.prepareSurfaces();
diff --git a/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java
index f339d292ed82..429a396ad997 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java
@@ -92,7 +92,7 @@ import java.util.concurrent.TimeUnit;
* Tests for the {@link DragDropController} class.
*
* Build/Install/Run:
- * atest WmTests:DragDropControllerTests
+ * atest WmTests:DragDropControllerTests
*/
@SmallTest
@Presubmit
@@ -146,12 +146,12 @@ public class DragDropControllerTests extends WindowTestsBase {
*/
private WindowState createDropTargetWindow(String name, int ownerId) {
final Task task = new TaskBuilder(mSupervisor).setUserId(ownerId).build();
- final ActivityRecord activity = new ActivityBuilder(mAtm).setTask(task)
- .setUseProcess(mProcess).build();
+ final ActivityRecord activity = new ActivityBuilder(mAtm).setTask(task).setUseProcess(
+ mProcess).build();
// Use a new TestIWindow so we don't collect events for other windows
- final WindowState window = createWindow(
- null, TYPE_BASE_APPLICATION, activity, name, ownerId, false, new TestIWindow());
+ final WindowState window = createWindow(null, TYPE_BASE_APPLICATION, activity, name,
+ ownerId, false, new TestIWindow());
InputChannel channel = new InputChannel();
window.openInputChannel(channel);
window.mHasSurface = true;
@@ -173,12 +173,11 @@ public class DragDropControllerTests extends WindowTestsBase {
@Before
public void setUp() throws Exception {
mTarget = new TestDragDropController(mWm, mWm.mH.getLooper());
- mProcess = mSystemServicesTestRule.addProcess(TEST_PACKAGE, "testProc",
- TEST_PID, TEST_UID);
+ mProcess = mSystemServicesTestRule.addProcess(TEST_PACKAGE, "testProc", TEST_PID, TEST_UID);
mWindow = createDropTargetWindow("Drag test window", 0);
doReturn(mWindow).when(mDisplayContent).getTouchableWinAtPointLocked(0, 0);
- when(mWm.mInputManager.startDragAndDrop(any(IBinder.class),
- any(IBinder.class))).thenReturn(true);
+ when(mWm.mInputManager.startDragAndDrop(any(IBinder.class), any(IBinder.class))).thenReturn(
+ true);
mWm.mWindowMap.put(mWindow.mClient.asBinder(), mWindow);
}
@@ -286,16 +285,15 @@ public class DragDropControllerTests extends WindowTestsBase {
// Verify the start-drag event is sent for the local and global intercept window
// but not the other window
assertTrue(nonLocalWindowDragEvents.isEmpty());
- assertTrue(localWindowDragEvents.get(0).getAction()
- == ACTION_DRAG_STARTED);
+ assertTrue(localWindowDragEvents.get(0).getAction() == ACTION_DRAG_STARTED);
assertTrue(globalInterceptWindowDragEvents.get(0).getAction()
== ACTION_DRAG_STARTED);
// Verify that only the global intercept window receives the clip data with the
// resolved activity info for the drag
assertNull(localWindowDragEvents.get(0).getClipData());
- assertTrue(globalInterceptWindowDragEvents.get(0).getClipData()
- .willParcelWithActivityInfo());
+ assertTrue(globalInterceptWindowDragEvents.get(
+ 0).getClipData().willParcelWithActivityInfo());
mTarget.reportDropWindow(globalInterceptWindow.mInputChannelToken, 0, 0);
mTarget.handleMotionEvent(false, 0, 0);
@@ -330,9 +328,8 @@ public class DragDropControllerTests extends WindowTestsBase {
// Verify the start-drag event has the drag flags
final DragEvent dragEvent = dragEvents.get(0);
assertTrue(dragEvent.getAction() == ACTION_DRAG_STARTED);
- assertTrue(dragEvent.getDragFlags() ==
- (View.DRAG_FLAG_GLOBAL
- | View.DRAG_FLAG_START_INTENT_SENDER_ON_UNHANDLED_DRAG));
+ assertTrue(dragEvent.getDragFlags() == (View.DRAG_FLAG_GLOBAL
+ | View.DRAG_FLAG_START_INTENT_SENDER_ON_UNHANDLED_DRAG));
try {
mTarget.mDeferDragStateClosed = true;
@@ -340,9 +337,8 @@ public class DragDropControllerTests extends WindowTestsBase {
// // Verify the drop event does not have the drag flags
mTarget.handleMotionEvent(false, 0, 0);
final DragEvent dropEvent = dragEvents.get(dragEvents.size() - 1);
- assertTrue(dropEvent.getDragFlags() ==
- (View.DRAG_FLAG_GLOBAL
- | View.DRAG_FLAG_START_INTENT_SENDER_ON_UNHANDLED_DRAG));
+ assertTrue(dropEvent.getDragFlags() == (View.DRAG_FLAG_GLOBAL
+ | View.DRAG_FLAG_START_INTENT_SENDER_ON_UNHANDLED_DRAG));
mTarget.reportDropResult(iwindow, true);
} finally {
@@ -385,16 +381,15 @@ public class DragDropControllerTests extends WindowTestsBase {
data.putExtra(Intent.EXTRA_USER, user);
}
final ClipData clipData = new ClipData(
- new ClipDescription("drag", new String[] {
- MIMETYPE_APPLICATION_ACTIVITY}),
+ new ClipDescription("drag", new String[]{MIMETYPE_APPLICATION_ACTIVITY}),
new ClipData.Item(data));
return clipData;
}
@Test
public void testValidateAppShortcutArguments() {
- doReturn(PERMISSION_GRANTED).when(mWm.mContext)
- .checkCallingOrSelfPermission(eq(START_TASKS_FROM_RECENTS));
+ doReturn(PERMISSION_GRANTED).when(mWm.mContext).checkCallingOrSelfPermission(
+ eq(START_TASKS_FROM_RECENTS));
final Session session = createTestSession(mAtm);
try {
session.validateAndResolveDragMimeTypeExtras(
@@ -414,8 +409,8 @@ public class DragDropControllerTests extends WindowTestsBase {
}
try {
session.validateAndResolveDragMimeTypeExtras(
- createClipDataForShortcut("test_package", "test_shortcut_id", null),
- TEST_UID, TEST_PID, TEST_PACKAGE);
+ createClipDataForShortcut("test_package", "test_shortcut_id", null), TEST_UID,
+ TEST_PID, TEST_PACKAGE);
fail("Expected failure without package name");
} catch (IllegalArgumentException e) {
// Expected failure
@@ -424,8 +419,8 @@ public class DragDropControllerTests extends WindowTestsBase {
@Test
public void testValidateProfileAppShortcutArguments_notCallingUid() {
- doReturn(PERMISSION_GRANTED).when(mWm.mContext)
- .checkCallingOrSelfPermission(eq(START_TASKS_FROM_RECENTS));
+ doReturn(PERMISSION_GRANTED).when(mWm.mContext).checkCallingOrSelfPermission(
+ eq(START_TASKS_FROM_RECENTS));
final Session session = createTestSession(mAtm);
final ShortcutServiceInternal shortcutService = mock(ShortcutServiceInternal.class);
final Intent[] shortcutIntents = new Intent[1];
@@ -438,10 +433,9 @@ public class DragDropControllerTests extends WindowTestsBase {
ArgumentCaptor<Integer> callingUser = ArgumentCaptor.forClass(Integer.class);
session.validateAndResolveDragMimeTypeExtras(
createClipDataForShortcut("test_package", "test_shortcut_id",
- mock(UserHandle.class)),
- TEST_PROFILE_UID, TEST_PID, TEST_PACKAGE);
- verify(shortcutService).createShortcutIntents(callingUser.capture(), any(),
- any(), any(), anyInt(), anyInt(), anyInt());
+ mock(UserHandle.class)), TEST_PROFILE_UID, TEST_PID, TEST_PACKAGE);
+ verify(shortcutService).createShortcutIntents(callingUser.capture(), any(), any(), any(),
+ anyInt(), anyInt(), anyInt());
assertTrue(callingUser.getValue() == UserHandle.getUserId(TEST_PROFILE_UID));
}
@@ -458,20 +452,19 @@ public class DragDropControllerTests extends WindowTestsBase {
data.putExtra(Intent.EXTRA_USER, user);
}
final ClipData clipData = new ClipData(
- new ClipDescription("drag", new String[] {
- MIMETYPE_APPLICATION_SHORTCUT}),
+ new ClipDescription("drag", new String[]{MIMETYPE_APPLICATION_SHORTCUT}),
new ClipData.Item(data));
return clipData;
}
@Test
public void testValidateAppTaskArguments() {
- doReturn(PERMISSION_GRANTED).when(mWm.mContext)
- .checkCallingOrSelfPermission(eq(START_TASKS_FROM_RECENTS));
+ doReturn(PERMISSION_GRANTED).when(mWm.mContext).checkCallingOrSelfPermission(
+ eq(START_TASKS_FROM_RECENTS));
final Session session = createTestSession(mAtm);
try {
final ClipData clipData = new ClipData(
- new ClipDescription("drag", new String[] { MIMETYPE_APPLICATION_TASK }),
+ new ClipDescription("drag", new String[]{MIMETYPE_APPLICATION_TASK}),
new ClipData.Item(new Intent()));
session.validateAndResolveDragMimeTypeExtras(clipData, TEST_UID, TEST_PID,
@@ -496,8 +489,8 @@ public class DragDropControllerTests extends WindowTestsBase {
@Test
public void testValidateFlagsWithPermission() {
- doReturn(PERMISSION_GRANTED).when(mWm.mContext)
- .checkCallingOrSelfPermission(eq(START_TASKS_FROM_RECENTS));
+ doReturn(PERMISSION_GRANTED).when(mWm.mContext).checkCallingOrSelfPermission(
+ eq(START_TASKS_FROM_RECENTS));
final Session session = createTestSession(mAtm);
try {
session.validateDragFlags(View.DRAG_FLAG_REQUEST_SURFACE_FOR_RETURN_ANIMATION,
@@ -533,8 +526,8 @@ public class DragDropControllerTests extends WindowTestsBase {
// Verify the DRAG_ENDED event does NOT include the drag surface
final DragEvent dropEvent = dragEvents.get(dragEvents.size() - 1);
- assertTrue(dragEvents.get(dragEvents.size() - 1).getAction()
- == ACTION_DRAG_ENDED);
+ assertTrue(
+ dragEvents.get(dragEvents.size() - 1).getAction() == ACTION_DRAG_ENDED);
assertTrue(dropEvent.getDragSurface() == null);
});
}
@@ -564,8 +557,8 @@ public class DragDropControllerTests extends WindowTestsBase {
// Verify the DRAG_ENDED event includes the drag surface
final DragEvent dropEvent = dragEvents.get(dragEvents.size() - 1);
- assertTrue(dragEvents.get(dragEvents.size() - 1).getAction()
- == ACTION_DRAG_ENDED);
+ assertTrue(
+ dragEvents.get(dragEvents.size() - 1).getAction() == ACTION_DRAG_ENDED);
assertTrue(dropEvent.getDragSurface() != null);
});
}
@@ -591,18 +584,18 @@ public class DragDropControllerTests extends WindowTestsBase {
final int invalidXY = 100_000;
startDrag(View.DRAG_FLAG_GLOBAL | View.DRAG_FLAG_START_INTENT_SENDER_ON_UNHANDLED_DRAG,
ClipData.newPlainText("label", "Test"), () -> {
- // Trigger an unhandled drop and verify the global drag listener was called
- mTarget.reportDropWindow(mWindow.mInputChannelToken, invalidXY, invalidXY);
- mTarget.handleMotionEvent(false /* keepHandling */, invalidXY, invalidXY);
- mTarget.reportDropResult(mWindow.mClient, false);
- mTarget.onUnhandledDropCallback(true);
- mToken = null;
- try {
- verify(listener, times(1)).onUnhandledDrop(any(), any());
- } catch (RemoteException e) {
- fail("Failed to verify unhandled drop: " + e);
- }
- });
+ // Trigger an unhandled drop and verify the global drag listener was called
+ mTarget.reportDropWindow(mWindow.mInputChannelToken, invalidXY, invalidXY);
+ mTarget.handleMotionEvent(false /* keepHandling */, invalidXY, invalidXY);
+ mTarget.reportDropResult(mWindow.mClient, false);
+ mTarget.onUnhandledDropCallback(true);
+ mToken = null;
+ try {
+ verify(listener, times(1)).onUnhandledDrop(any(), any());
+ } catch (RemoteException e) {
+ fail("Failed to verify unhandled drop: " + e);
+ }
+ });
}
@Test
@@ -615,17 +608,17 @@ public class DragDropControllerTests extends WindowTestsBase {
final int invalidXY = 100_000;
startDrag(View.DRAG_FLAG_GLOBAL | View.DRAG_FLAG_START_INTENT_SENDER_ON_UNHANDLED_DRAG,
ClipData.newPlainText("label", "Test"), () -> {
- // Trigger an unhandled drop and verify the global drag listener was called
- mTarget.reportDropWindow(mock(IBinder.class), invalidXY, invalidXY);
- mTarget.handleMotionEvent(false /* keepHandling */, invalidXY, invalidXY);
- mTarget.onUnhandledDropCallback(true);
- mToken = null;
- try {
- verify(listener, times(1)).onUnhandledDrop(any(), any());
- } catch (RemoteException e) {
- fail("Failed to verify unhandled drop: " + e);
- }
- });
+ // Trigger an unhandled drop and verify the global drag listener was called
+ mTarget.reportDropWindow(mock(IBinder.class), invalidXY, invalidXY);
+ mTarget.handleMotionEvent(false /* keepHandling */, invalidXY, invalidXY);
+ mTarget.onUnhandledDropCallback(true);
+ mToken = null;
+ try {
+ verify(listener, times(1)).onUnhandledDrop(any(), any());
+ } catch (RemoteException e) {
+ fail("Failed to verify unhandled drop: " + e);
+ }
+ });
}
@Test
@@ -636,18 +629,17 @@ public class DragDropControllerTests extends WindowTestsBase {
doReturn(mock(Binder.class)).when(listener).asBinder();
mTarget.setGlobalDragListener(listener);
final int invalidXY = 100_000;
- startDrag(View.DRAG_FLAG_GLOBAL,
- ClipData.newPlainText("label", "Test"), () -> {
- // Trigger an unhandled drop and verify the global drag listener was not called
- mTarget.reportDropWindow(mock(IBinder.class), invalidXY, invalidXY);
- mTarget.handleMotionEvent(false /* keepHandling */, invalidXY, invalidXY);
- mToken = null;
- try {
- verify(listener, never()).onUnhandledDrop(any(), any());
- } catch (RemoteException e) {
- fail("Failed to verify unhandled drop: " + e);
- }
- });
+ startDrag(View.DRAG_FLAG_GLOBAL, ClipData.newPlainText("label", "Test"), () -> {
+ // Trigger an unhandled drop and verify the global drag listener was not called
+ mTarget.reportDropWindow(mock(IBinder.class), invalidXY, invalidXY);
+ mTarget.handleMotionEvent(false /* keepHandling */, invalidXY, invalidXY);
+ mToken = null;
+ try {
+ verify(listener, never()).onUnhandledDrop(any(), any());
+ } catch (RemoteException e) {
+ fail("Failed to verify unhandled drop: " + e);
+ }
+ });
}
@Test
@@ -660,20 +652,22 @@ public class DragDropControllerTests extends WindowTestsBase {
final int invalidXY = 100_000;
startDrag(View.DRAG_FLAG_GLOBAL | View.DRAG_FLAG_START_INTENT_SENDER_ON_UNHANDLED_DRAG,
ClipData.newPlainText("label", "Test"), () -> {
- // Trigger an unhandled drop and verify the global drag listener was called
- mTarget.reportDropWindow(mock(IBinder.class), invalidXY, invalidXY);
- mTarget.handleMotionEvent(false /* keepHandling */, invalidXY, invalidXY);
+ // Trigger an unhandled drop and verify the global drag listener was called
+ mTarget.reportDropWindow(mock(IBinder.class), invalidXY, invalidXY);
+ mTarget.handleMotionEvent(false /* keepHandling */, invalidXY, invalidXY);
- // Verify that the unhandled drop listener callback timeout has been scheduled
- final Handler handler = mTarget.getHandler();
- assertTrue(handler.hasMessages(MSG_UNHANDLED_DROP_LISTENER_TIMEOUT));
+ // Verify that the unhandled drop listener callback timeout has been scheduled
+ final Handler handler = mTarget.getHandler();
+ assertTrue(handler.hasMessages(MSG_UNHANDLED_DROP_LISTENER_TIMEOUT));
- // Force trigger the timeout and verify that it actually cleans up the drag & timeout
- handler.handleMessage(Message.obtain(handler, MSG_UNHANDLED_DROP_LISTENER_TIMEOUT));
- assertFalse(handler.hasMessages(MSG_UNHANDLED_DROP_LISTENER_TIMEOUT));
- assertFalse(mTarget.dragDropActiveLocked());
- mToken = null;
- });
+ // Force trigger the timeout and verify that it actually cleans up the drag &
+ // timeout
+ handler.handleMessage(
+ Message.obtain(handler, MSG_UNHANDLED_DROP_LISTENER_TIMEOUT));
+ assertFalse(handler.hasMessages(MSG_UNHANDLED_DROP_LISTENER_TIMEOUT));
+ assertFalse(mTarget.dragDropActiveLocked());
+ mToken = null;
+ });
}
private void doDragAndDrop(int flags, ClipData data, float dropX, float dropY) {
@@ -690,15 +684,13 @@ public class DragDropControllerTests extends WindowTestsBase {
private void startDrag(int flag, ClipData data, Runnable r) {
final SurfaceSession appSession = new SurfaceSession();
try {
- final SurfaceControl surface = new SurfaceControl.Builder(appSession)
- .setName("drag surface")
- .setBufferSize(100, 100)
- .setFormat(PixelFormat.TRANSLUCENT)
- .build();
+ final SurfaceControl surface = new SurfaceControl.Builder(appSession).setName(
+ "drag surface").setBufferSize(100, 100).setFormat(
+ PixelFormat.TRANSLUCENT).build();
assertTrue(mWm.mInputManager.startDragAndDrop(new Binder(), new Binder()));
- mToken = mTarget.performDrag(TEST_PID, 0, mWindow.mClient,
- flag, surface, 0, 0, 0, 0, 0, 0, 0, data);
+ mToken = mTarget.performDrag(TEST_PID, 0, mWindow.mClient, flag, surface, 0, 0, 0, 0, 0,
+ 0, 0, data);
assertNotNull(mToken);
r.run();
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
index b27025c34d6b..b61dada809d8 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -89,6 +89,7 @@ import android.os.RemoteException;
import android.os.UserHandle;
import android.provider.Settings;
import android.service.voice.IVoiceInteractionSession;
+import android.tools.function.Supplier;
import android.util.MergedConfiguration;
import android.util.SparseArray;
import android.view.Display;
@@ -1804,6 +1805,124 @@ public class WindowTestsBase extends SystemServiceTestsBase {
}
}
+ protected WindowStateBuilder newWindowBuilder(String name, int type) {
+ return new WindowStateBuilder(name, type, mWm, mDisplayContent, mIWindow,
+ this::getTestSession, this::createWindowToken);
+ }
+
+ /**
+ * Builder for creating new window.
+ */
+ protected static class WindowStateBuilder {
+ private final String mName;
+ private final int mType;
+ private final WindowManagerService mWm;
+ private final DisplayContent mDefaultTargetDisplay;
+ private final Supplier<WindowToken, Session> mSessionSupplier;
+ private final WindowTokenCreator mWindowTokenCreator;
+
+ private int mActivityType = ACTIVITY_TYPE_STANDARD;
+ private IWindow mClientWindow;
+ private boolean mOwnerCanAddInternalSystemWindow = false;
+ private int mOwnerId = 0;
+ private WindowState mParent;
+ private DisplayContent mTargetDisplay;
+ private int mWindowingMode = WINDOWING_MODE_FULLSCREEN;
+ private WindowToken mWindowToken;
+
+ WindowStateBuilder(String name, int type, WindowManagerService windowManagerService,
+ DisplayContent dc, IWindow iWindow, Supplier<WindowToken, Session> sessionSupplier,
+ WindowTokenCreator windowTokenCreator) {
+ mName = name;
+ mType = type;
+ mClientWindow = iWindow;
+ mDefaultTargetDisplay = dc;
+ mSessionSupplier = sessionSupplier;
+ mWindowTokenCreator = windowTokenCreator;
+ mWm = windowManagerService;
+ }
+
+ WindowStateBuilder setActivityType(int activityType) {
+ mActivityType = activityType;
+ return this;
+ }
+
+ WindowStateBuilder setClientWindow(IWindow clientWindow) {
+ mClientWindow = clientWindow;
+ return this;
+ }
+
+ WindowStateBuilder setDisplay(DisplayContent displayContent) {
+ mTargetDisplay = displayContent;
+ return this;
+ }
+
+ WindowStateBuilder setOwnerCanAddInternalSystemWindow(
+ boolean ownerCanAddInternalSystemWindow) {
+ mOwnerCanAddInternalSystemWindow = ownerCanAddInternalSystemWindow;
+ return this;
+ }
+
+ WindowStateBuilder setOwnerId(int ownerId) {
+ mOwnerId = ownerId;
+ return this;
+ }
+
+ WindowStateBuilder setParent(WindowState parent) {
+ mParent = parent;
+ return this;
+ }
+
+ WindowStateBuilder setWindowToken(WindowToken token) {
+ mWindowToken = token;
+ return this;
+ }
+
+ WindowStateBuilder setWindowingMode(int windowingMode) {
+ mWindowingMode = windowingMode;
+ return this;
+ }
+
+ WindowState build() {
+ SystemServicesTestRule.checkHoldsLock(mWm.mGlobalLock);
+
+ final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(mType);
+ attrs.setTitle(mName);
+ attrs.packageName = "test";
+
+ assertFalse(
+ "targetDisplay shouldn't be specified together with windowToken, since"
+ + " windowToken will be derived from targetDisplay.",
+ mWindowToken != null && mTargetDisplay != null);
+
+ if (mWindowToken == null) {
+ if (mTargetDisplay != null) {
+ mWindowToken = mWindowTokenCreator.createWindowToken(mTargetDisplay,
+ mWindowingMode, mActivityType, mType);
+ } else if (mParent != null) {
+ mWindowToken = mParent.mToken;
+ } else {
+ // Use default mDisplayContent as window token.
+ mWindowToken = mWindowTokenCreator.createWindowToken(mDefaultTargetDisplay,
+ mWindowingMode, mActivityType, mType);
+ }
+ }
+
+ final WindowState w = new WindowState(mWm, mSessionSupplier.get(mWindowToken),
+ mClientWindow, mWindowToken, mParent, OP_NONE, attrs, VISIBLE, mOwnerId,
+ UserHandle.getUserId(mOwnerId), mOwnerCanAddInternalSystemWindow);
+ // TODO: Probably better to make this call in the WindowState ctor to avoid errors with
+ // adding it to the token...
+ mWindowToken.addWindow(w);
+ return w;
+ }
+
+ interface WindowTokenCreator {
+ WindowToken createWindowToken(DisplayContent dc, int windowingMode, int activityType,
+ int type);
+ }
+ }
+
static class TestStartingWindowOrganizer extends WindowOrganizerTests.StubOrganizer {
private final ActivityTaskManagerService mAtm;
private final WindowManagerService mWMService;
diff --git a/services/usb/java/com/android/server/usb/UsbAlsaDevice.java b/services/usb/java/com/android/server/usb/UsbAlsaDevice.java
index c508fa968b14..ce3cd29a3ce2 100644
--- a/services/usb/java/com/android/server/usb/UsbAlsaDevice.java
+++ b/services/usb/java/com/android/server/usb/UsbAlsaDevice.java
@@ -26,6 +26,7 @@ import android.util.Slog;
import com.android.internal.util.dump.DualDumpOutputStream;
import com.android.server.audio.AudioService;
+import com.android.server.usb.flags.Flags;
import java.util.Arrays;
@@ -211,6 +212,9 @@ public final class UsbAlsaDevice {
mIsSelected[direction] = true;
mState[direction] = 0;
startJackDetect();
+ if (direction == OUTPUT && Flags.maximizeUsbAudioVolumeWhenConnecting()) {
+ nativeSetVolume(mCardNum, 1.0f /*volume*/);
+ }
updateWiredDeviceConnectionState(direction, true /*enable*/);
}
@@ -412,5 +416,7 @@ public final class UsbAlsaDevice {
return result;
}
+
+ private native void nativeSetVolume(int card, float volume);
}
diff --git a/services/usb/java/com/android/server/usb/flags/usb_flags.aconfig b/services/usb/java/com/android/server/usb/flags/usb_flags.aconfig
index a2d0efd1d063..dfbd74c1f3e1 100644
--- a/services/usb/java/com/android/server/usb/flags/usb_flags.aconfig
+++ b/services/usb/java/com/android/server/usb/flags/usb_flags.aconfig
@@ -21,3 +21,10 @@ flag {
description: "This flag checks if phone is unlocked after boot"
bug: "73654179"
}
+
+flag {
+ name: "maximize_usb_audio_volume_when_connecting"
+ namespace: "usb"
+ description: "This flag maximizes the usb audio volume when it is connected"
+ bug: "245041322"
+}