Merge "al-ov: Use F4 to toggle Overview" into main
diff --git a/cmds/screencap/screencap.cpp b/cmds/screencap/screencap.cpp
index 7e4f95b..01b20f4 100644
--- a/cmds/screencap/screencap.cpp
+++ b/cmds/screencap/screencap.cpp
@@ -14,6 +14,9 @@
* limitations under the License.
*/
+#include <android/bitmap.h>
+#include <android/gui/DisplayCaptureArgs.h>
+#include <binder/ProcessState.h>
#include <errno.h>
#include <unistd.h>
#include <stdio.h>
@@ -33,7 +36,6 @@
#include <ftl/concat.h>
#include <ftl/optional.h>
-#include <gui/DisplayCaptureArgs.h>
#include <gui/ISurfaceComposer.h>
#include <gui/SurfaceComposerClient.h>
#include <gui/SyncScreenCaptureListener.h>
diff --git a/core/api/current.txt b/core/api/current.txt
index c1366a1..66a1d30 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -8741,6 +8741,31 @@
method @NonNull public android.app.appfunctions.ExecuteAppFunctionRequest.Builder setParameters(@NonNull android.app.appsearch.GenericDocument);
}
+ @FlaggedApi("android.app.appfunctions.flags.enable_app_function_manager") public final class ExecuteAppFunctionResponse implements android.os.Parcelable {
+ method public int describeContents();
+ method @Nullable public String getErrorMessage();
+ method @NonNull public android.os.Bundle getExtras();
+ method public int getResultCode();
+ method @NonNull public android.app.appsearch.GenericDocument getResultDocument();
+ method public boolean isSuccess();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.app.appfunctions.ExecuteAppFunctionResponse> CREATOR;
+ field public static final String PROPERTY_RETURN_VALUE = "returnValue";
+ field public static final int RESULT_APP_UNKNOWN_ERROR = 2; // 0x2
+ field public static final int RESULT_DENIED = 1; // 0x1
+ field public static final int RESULT_INTERNAL_ERROR = 3; // 0x3
+ field public static final int RESULT_INVALID_ARGUMENT = 4; // 0x4
+ field public static final int RESULT_OK = 0; // 0x0
+ field public static final int RESULT_TIMED_OUT = 5; // 0x5
+ }
+
+ @FlaggedApi("android.app.appfunctions.flags.enable_app_function_manager") public static final class ExecuteAppFunctionResponse.Builder {
+ ctor public ExecuteAppFunctionResponse.Builder(@NonNull android.app.appsearch.GenericDocument);
+ ctor public ExecuteAppFunctionResponse.Builder(int, @NonNull String);
+ method @NonNull public android.app.appfunctions.ExecuteAppFunctionResponse build();
+ method @NonNull public android.app.appfunctions.ExecuteAppFunctionResponse.Builder setExtras(@NonNull android.os.Bundle);
+ }
+
}
package android.app.assist {
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 0db91f5..177b859 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -941,7 +941,7 @@
method public int getAudioRecordingSessionId(int);
method public int getDeviceIdForDisplayId(int);
method public int getDevicePolicy(int, int);
- method @FlaggedApi("android.companion.virtual.flags.interactive_screen_mirror") public boolean isVirtualDeviceOwnedMirrorDisplay(int);
+ method public boolean isVirtualDeviceOwnedMirrorDisplay(int);
method public void playSoundEffect(int, int);
}
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 69b5222..3d1a785 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -393,7 +393,7 @@
* changes.
*
* <p>This broadcast is only sent to registered receivers and receivers in packages that have
- * been granted Do Not Disturb access (see {@link #isNotificationPolicyAccessGranted()}).
+ * been granted Notification Policy access (see {@link #isNotificationPolicyAccessGranted()}).
*/
@FlaggedApi(Flags.FLAG_MODES_API)
@SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
@@ -1627,7 +1627,7 @@
}
/**
- * Checks the ability to modify notification do not disturb policy for the calling package.
+ * Checks the ability to modify Notification Policy for the calling package.
*
* <p>
* Returns true if the calling package can modify notification policy.
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 114a2c4..cb38cf2 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -475,7 +475,7 @@
if (service == null
&& ctx.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH)
&& android.server.Flags.allowRemovingVpnService()) {
- throw new ServiceNotFoundException(Context.VPN_MANAGEMENT_SERVICE);
+ return null;
}
return new VpnManager(ctx, service);
}});
diff --git a/core/java/android/app/appfunctions/ExecuteAppFunctionAidlRequest.aidl b/core/java/android/app/appfunctions/ExecuteAppFunctionAidlRequest.aidl
new file mode 100644
index 0000000..42ec45d
--- /dev/null
+++ b/core/java/android/app/appfunctions/ExecuteAppFunctionAidlRequest.aidl
@@ -0,0 +1,23 @@
+
+/*
+ * 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 android.app.appfunctions;
+
+import android.app.appfunctions.ExecuteAppFunctionAidlRequest;
+
+/** {@hide} */
+parcelable ExecuteAppFunctionAidlRequest;
\ No newline at end of file
diff --git a/core/java/android/app/appfunctions/ExecuteAppFunctionAidlRequest.java b/core/java/android/app/appfunctions/ExecuteAppFunctionAidlRequest.java
new file mode 100644
index 0000000..2f3c555
--- /dev/null
+++ b/core/java/android/app/appfunctions/ExecuteAppFunctionAidlRequest.java
@@ -0,0 +1,113 @@
+/*
+ * 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 android.app.appfunctions;
+
+import static android.app.appfunctions.flags.Flags.FLAG_ENABLE_APP_FUNCTION_MANAGER;
+
+import android.annotation.FlaggedApi;
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.UserHandle;
+
+
+import java.util.Objects;
+
+/**
+ * An internal request to execute an app function.
+ *
+ * @hide
+ */
+@FlaggedApi(FLAG_ENABLE_APP_FUNCTION_MANAGER)
+public final class ExecuteAppFunctionAidlRequest implements Parcelable {
+
+ public static final Creator<ExecuteAppFunctionAidlRequest> CREATOR =
+ new Creator<ExecuteAppFunctionAidlRequest>() {
+ @Override
+ public ExecuteAppFunctionAidlRequest createFromParcel(Parcel in) {
+ ExecuteAppFunctionRequest clientRequest =
+ ExecuteAppFunctionRequest.CREATOR.createFromParcel(in);
+ UserHandle userHandle =
+ UserHandle.CREATOR.createFromParcel(in);
+ String callingPackage = in.readString8();
+ return new ExecuteAppFunctionAidlRequest(
+ clientRequest, userHandle, callingPackage);
+ }
+
+ @Override
+ public ExecuteAppFunctionAidlRequest[] newArray(int size) {
+ return new ExecuteAppFunctionAidlRequest[size];
+ }
+ };
+
+ /**
+ * The client request to execute an app function.
+ */
+ private final ExecuteAppFunctionRequest mClientRequest;
+
+ /**
+ * The user handle of the user to execute the app function.
+ */
+ private final UserHandle mUserHandle;
+
+ /**
+ * The package name of the app that is requesting to execute the app function.
+ */
+ private final String mCallingPackage;
+
+ public ExecuteAppFunctionAidlRequest(
+ ExecuteAppFunctionRequest clientRequest, UserHandle userHandle, String callingPackage) {
+ this.mClientRequest = Objects.requireNonNull(clientRequest);
+ this.mUserHandle = Objects.requireNonNull(userHandle);
+ this.mCallingPackage = Objects.requireNonNull(callingPackage);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ mClientRequest.writeToParcel(dest, flags);
+ mUserHandle.writeToParcel(dest, flags);
+ dest.writeString8(mCallingPackage);
+ }
+
+ /**
+ * Returns the client request to execute an app function.
+ */
+ @NonNull
+ public ExecuteAppFunctionRequest getClientRequest() {
+ return mClientRequest;
+ }
+
+ /**
+ * Returns the user handle of the user to execute the app function.
+ */
+ @NonNull
+ public UserHandle getUserHandle() {
+ return mUserHandle;
+ }
+
+ /**
+ * Returns the package name of the app that is requesting to execute the app function.
+ */
+ @NonNull
+ public String getCallingPackage() {
+ return mCallingPackage;
+ }
+}
diff --git a/core/java/android/app/appfunctions/ExecuteAppFunctionResponse.aidl b/core/java/android/app/appfunctions/ExecuteAppFunctionResponse.aidl
new file mode 100644
index 0000000..5194e7a
--- /dev/null
+++ b/core/java/android/app/appfunctions/ExecuteAppFunctionResponse.aidl
@@ -0,0 +1,21 @@
+/*
+ * 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 android.app.appfunctions;
+
+import android.app.appfunctions.ExecuteAppFunctionResponse;
+
+parcelable ExecuteAppFunctionResponse;
\ No newline at end of file
diff --git a/core/java/android/app/appfunctions/ExecuteAppFunctionResponse.java b/core/java/android/app/appfunctions/ExecuteAppFunctionResponse.java
new file mode 100644
index 0000000..72205d9
--- /dev/null
+++ b/core/java/android/app/appfunctions/ExecuteAppFunctionResponse.java
@@ -0,0 +1,294 @@
+/*
+ * 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 android.app.appfunctions;
+
+import static android.app.appfunctions.flags.Flags.FLAG_ENABLE_APP_FUNCTION_MANAGER;
+
+import android.annotation.FlaggedApi;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.appsearch.GenericDocument;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Objects;
+
+/**
+ * The response to an app function execution.
+ */
+@FlaggedApi(FLAG_ENABLE_APP_FUNCTION_MANAGER)
+public final class ExecuteAppFunctionResponse implements Parcelable {
+ @NonNull
+ public static final Creator<ExecuteAppFunctionResponse> CREATOR =
+ new Creator<ExecuteAppFunctionResponse>() {
+ @Override
+ public ExecuteAppFunctionResponse createFromParcel(Parcel parcel) {
+ GenericDocument result =
+ Objects.requireNonNull(GenericDocument.createFromParcel(parcel));
+ Bundle extras = Objects.requireNonNull(
+ parcel.readBundle(Bundle.class.getClassLoader()));
+ int resultCode = parcel.readInt();
+ String errorMessage = parcel.readString8();
+ return new ExecuteAppFunctionResponse(result, extras, resultCode, errorMessage);
+ }
+
+ @Override
+ public ExecuteAppFunctionResponse[] newArray(int size) {
+ return new ExecuteAppFunctionResponse[size];
+ }
+ };
+ /**
+ * The name of the property that stores the function return value within the
+ * {@code resultDocument}.
+ *
+ * <p>See {@link GenericDocument#getProperty(String)} for more information.
+ *
+ * <p>If the function returns {@code void} or throws an error, the {@code resultDocument}
+ * will be empty {@link GenericDocument}.
+ *
+ * <p>If the {@code resultDocument} is empty, {@link GenericDocument#getProperty(String)} will
+ * return {@code null}.
+ *
+ * <p>See {@link #getResultDocument} for more information on extracting the return value.
+ */
+ public static final String PROPERTY_RETURN_VALUE = "returnValue";
+
+ /**
+ * The call was successful.
+ */
+ public static final int RESULT_OK = 0;
+
+ /**
+ * The caller does not have the permission to execute an app function.
+ */
+ public static final int RESULT_DENIED = 1;
+
+ /**
+ * An unknown error occurred while processing the call in the AppFunctionService.
+ */
+ public static final int RESULT_APP_UNKNOWN_ERROR = 2;
+
+ /**
+ * An internal error occurred within AppFunctionManagerService.
+ *
+ * <p>This error may be considered similar to {@link IllegalStateException}
+ */
+ public static final int RESULT_INTERNAL_ERROR = 3;
+
+ /**
+ * The caller supplied invalid arguments to the call.
+ *
+ * <p>This error may be considered similar to {@link IllegalArgumentException}.
+ */
+ public static final int RESULT_INVALID_ARGUMENT = 4;
+
+ /**
+ * The operation was timed out.
+ */
+ public static final int RESULT_TIMED_OUT = 5;
+
+ /**
+ * The result code of the app function execution.
+ */
+ @ResultCode
+ private final int mResultCode;
+
+ /**
+ * The error message associated with the result, if any. This is {@code null} if the result code
+ * is {@link #RESULT_OK}.
+ */
+ @Nullable
+ private final String mErrorMessage;
+
+ /**
+ * Returns the return value of the executed function.
+ *
+ * <p>The return value is stored in a {@link GenericDocument} with the key
+ * {@link #PROPERTY_RETURN_VALUE}.
+ *
+ * <p>See {@link #getResultDocument} for more information on extracting the return value.
+ */
+ @NonNull
+ private final GenericDocument mResultDocument;
+
+ /**
+ * Returns the additional metadata data relevant to this function execution response.
+ */
+ @NonNull
+ private final Bundle mExtras;
+
+ private ExecuteAppFunctionResponse(@NonNull GenericDocument resultDocument,
+ @NonNull Bundle extras,
+ @ResultCode int resultCode,
+ @Nullable String errorMessage) {
+ mResultDocument = Objects.requireNonNull(resultDocument);
+ mExtras = Objects.requireNonNull(extras);
+ mResultCode = resultCode;
+ mErrorMessage = errorMessage;
+ }
+
+ /**
+ * Returns a generic document containing the return value of the executed function.
+ *
+ * <p>The {@link #PROPERTY_RETURN_VALUE} key can be used to obtain the return value.</p>
+ *
+ * <p>An empty document is returned if {@link #isSuccess} is {@code false} or if the executed
+ * function does not produce a return value.
+ *
+ * <p>Sample code for extracting the return value:
+ * <pre>
+ * GenericDocument resultDocument = response.getResultDocument();
+ * Object returnValue = resultDocument.getProperty(PROPERTY_RETURN_VALUE);
+ * if (returnValue != null) {
+ * // Cast returnValue to expected type, or use {@link GenericDocument#getPropertyString},
+ * // {@link GenericDocument#getPropertyLong} etc.
+ * // Do something with the returnValue
+ * }
+ * </pre>
+ */
+ @NonNull
+ public GenericDocument getResultDocument() {
+ return mResultDocument;
+ }
+
+ /**
+ * Returns the extras of the app function execution.
+ */
+ @NonNull
+ public Bundle getExtras() {
+ return mExtras;
+ }
+
+ /**
+ * Returns {@code true} if {@link #getResultCode} equals
+ * {@link ExecuteAppFunctionResponse#RESULT_OK}.
+ */
+ public boolean isSuccess() {
+ return getResultCode() == RESULT_OK;
+ }
+
+ /**
+ * Returns one of the {@code RESULT} constants defined in {@link ExecuteAppFunctionResponse}.
+ */
+ @ResultCode
+ public int getResultCode() {
+ return mResultCode;
+ }
+
+ /**
+ * Returns the error message associated with this result.
+ *
+ * <p>If {@link #isSuccess} is {@code true}, the error message is always {@code null}.
+ */
+ @Nullable
+ public String getErrorMessage() {
+ return mErrorMessage;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ mResultDocument.writeToParcel(dest, flags);
+ dest.writeBundle(mExtras);
+ dest.writeInt(mResultCode);
+ dest.writeString8(mErrorMessage);
+ }
+
+ /**
+ * Result codes.
+ *
+ * @hide
+ */
+ @IntDef(
+ prefix = {"RESULT_"},
+ value = {
+ RESULT_OK,
+ RESULT_DENIED,
+ RESULT_APP_UNKNOWN_ERROR,
+ RESULT_INTERNAL_ERROR,
+ RESULT_INVALID_ARGUMENT,
+ RESULT_TIMED_OUT,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ResultCode {
+ }
+
+ /**
+ * The builder for creating {@link ExecuteAppFunctionResponse} instances.
+ */
+ @FlaggedApi(FLAG_ENABLE_APP_FUNCTION_MANAGER)
+ public static final class Builder {
+ @NonNull
+ private GenericDocument mResultDocument = new GenericDocument.Builder<>("", "", "").build();
+ @NonNull
+ private Bundle mExtras = Bundle.EMPTY;
+ private int mResultCode;
+ @Nullable
+ private String mErrorMessage;
+
+ /**
+ * Creates a new builder for {@link ExecuteAppFunctionResponse}.
+ */
+ private Builder() {
+ }
+
+ /**
+ * Creates a new builder for {@link ExecuteAppFunctionResponse} to build a success response
+ * with a result code of {@link #RESULT_OK} and a resultDocument.
+ */
+ public Builder(@NonNull GenericDocument resultDocument) {
+ mResultDocument = Objects.requireNonNull(resultDocument);
+ mResultCode = RESULT_OK;
+ }
+
+ /**
+ * Creates a new builder for {@link ExecuteAppFunctionResponse} to build an error response
+ * with a result code and an error message.
+ */
+ public Builder(@ResultCode int resultCode,
+ @NonNull String errorMessage) {
+ mResultCode = resultCode;
+ mErrorMessage = Objects.requireNonNull(errorMessage);
+ }
+
+ /**
+ * Sets the extras of the app function execution.
+ */
+ @NonNull
+ public Builder setExtras(@NonNull Bundle extras) {
+ mExtras = Objects.requireNonNull(extras);
+ return this;
+ }
+
+ /**
+ * Builds the {@link ExecuteAppFunctionResponse} instance.
+ */
+ @NonNull
+ public ExecuteAppFunctionResponse build() {
+ return new ExecuteAppFunctionResponse(
+ mResultDocument, mExtras, mResultCode, mErrorMessage);
+ }
+ }
+}
diff --git a/core/java/android/app/notification.aconfig b/core/java/android/app/notification.aconfig
index f751a23..f05c24f 100644
--- a/core/java/android/app/notification.aconfig
+++ b/core/java/android/app/notification.aconfig
@@ -21,6 +21,13 @@
}
flag {
+ name: "modes_ui_test"
+ namespace: "systemui"
+ description: "Guards new CTS tests for Modes; dependent on flags modes_api and modes_ui"
+ bug: "360862012"
+}
+
+flag {
name: "api_tvextender"
is_exported: true
namespace: "systemui"
diff --git a/core/java/android/companion/virtual/VirtualDeviceManager.java b/core/java/android/companion/virtual/VirtualDeviceManager.java
index 8b60580..d07fb25 100644
--- a/core/java/android/companion/virtual/VirtualDeviceManager.java
+++ b/core/java/android/companion/virtual/VirtualDeviceManager.java
@@ -531,7 +531,6 @@
*
* @hide
*/
- @FlaggedApi(Flags.FLAG_INTERACTIVE_SCREEN_MIRROR)
@TestApi
public boolean isVirtualDeviceOwnedMirrorDisplay(int displayId) {
if (mService == null) {
diff --git a/core/java/android/companion/virtual/flags.aconfig b/core/java/android/companion/virtual/flags.aconfig
index 91586b6..fc9c94d 100644
--- a/core/java/android/companion/virtual/flags.aconfig
+++ b/core/java/android/companion/virtual/flags.aconfig
@@ -35,13 +35,6 @@
}
flag {
- name: "consistent_display_flags"
- namespace: "virtual_devices"
- description: "Make virtual display flags consistent with display manager"
- bug: "300905478"
-}
-
-flag {
name: "vdm_custom_ime"
is_exported: true
namespace: "virtual_devices"
@@ -89,14 +82,6 @@
}
flag {
- name: "interactive_screen_mirror"
- is_exported: true
- namespace: "virtual_devices"
- description: "Enable interactive screen mirroring using Virtual Devices"
- bug: "292212199"
-}
-
-flag {
name: "virtual_stylus"
is_exported: true
namespace: "virtual_devices"
diff --git a/core/java/android/hardware/input/input_framework.aconfig b/core/java/android/hardware/input/input_framework.aconfig
index 6f1d63d8..83c4de3 100644
--- a/core/java/android/hardware/input/input_framework.aconfig
+++ b/core/java/android/hardware/input/input_framework.aconfig
@@ -92,3 +92,10 @@
description: "Dump keyboard shortcuts in dumpsys window"
bug: "351963350"
}
+
+flag {
+ name: "modifier_shortcut_manager_refactor"
+ namespace: "input"
+ description: "Refactor ModifierShortcutManager internal representation of shortcuts."
+ bug: "358603902"
+}
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 28f2c25..536eca6 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -969,9 +969,7 @@
/**
* Specifies if a user is disallowed from adding new users. This can only be set by device
- * owners or profile owners on the primary user. The default value is <code>false</code>.
- * <p>This restriction has no effect on secondary users and managed profiles since only the
- * primary user can add other users.
+ * owners or profile owners on the main user. The default value is <code>false</code>.
* <p> When the device is an organization-owned device provisioned with a managed profile,
* this restriction will be set as a base restriction which cannot be removed by any admin.
*
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 7ca40ea..85d2325 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1972,10 +1972,10 @@
"android.provider.extra.NOTIFICATION_LISTENER_COMPONENT_NAME";
/**
- * Activity Action: Show Do Not Disturb access settings.
+ * Activity Action: Show Notification Policy access settings.
* <p>
- * Users can grant and deny access to Do Not Disturb configuration from here. Managed
- * profiles cannot grant Do Not Disturb access.
+ * Users can grant and deny access to Notification Policy (DND / Priority Modes) configuration
+ * from here. Managed profiles cannot grant Notification Policy access.
* See {@link android.app.NotificationManager#isNotificationPolicyAccessGranted()} for more
* details.
* <p>
@@ -14953,6 +14953,7 @@
*
* @hide
*/
+ @Readable
public static final String MUTE_ALARM_STREAM_WITH_RINGER_MODE =
"mute_alarm_stream_with_ringer_mode";
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 08e51a1..1734223 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -1078,6 +1078,9 @@
out.print(prefix); out.print("mDisplay="); out.println(mDisplay);
out.print(prefix); out.print("mCreated="); out.print(mCreated);
out.print(" mSurfaceCreated="); out.print(mSurfaceCreated);
+ if (noDuplicateSurfaceDestroyedEvents()) {
+ out.print(" mReportedSurfaceCreated="); out.print(mReportedSurfaceCreated);
+ }
out.print(" mIsCreating="); out.print(mIsCreating);
out.print(" mDrawingAllowed="); out.println(mDrawingAllowed);
out.print(prefix); out.print("mWidth="); out.print(mWidth);
diff --git a/core/java/android/text/flags/flags.aconfig b/core/java/android/text/flags/flags.aconfig
index 1c3d738..40070c7 100644
--- a/core/java/android/text/flags/flags.aconfig
+++ b/core/java/android/text/flags/flags.aconfig
@@ -259,6 +259,16 @@
}
flag {
+ name: "dont_break_email_in_nobreak_tag"
+ namespace: "text"
+ description: "Prevent line break inside email."
+ bug: "350691716"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
name: "handwriting_gesture_with_transformation"
namespace: "text"
description: "Fix handwriting gesture is not working when view has transformation."
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 017e004..67a207e 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -3462,6 +3462,15 @@
public static final int PRIVATE_FLAG_NOT_MAGNIFIABLE = 1 << 22;
/**
+ * Indicates that the window should receive key events including Action/Meta key.
+ * They will not be intercepted as usual and instead will be passed to the window with other
+ * key events.
+ * TODO(b/358569822) Remove this once we have nicer API for listening to shortcuts
+ * @hide
+ */
+ public static final int PRIVATE_FLAG_ALLOW_ACTION_KEY_EVENTS = 1 << 23;
+
+ /**
* Flag to indicate that the window is color space agnostic, and the color can be
* interpreted to any color space.
* @hide
diff --git a/core/java/android/view/inputmethod/InputConnection.java b/core/java/android/view/inputmethod/InputConnection.java
index 1840bcb..4742f1e 100644
--- a/core/java/android/view/inputmethod/InputConnection.java
+++ b/core/java/android/view/inputmethod/InputConnection.java
@@ -625,8 +625,7 @@
* the text you are providing so it is not possible to correctly
* specify locations there.
* @param textAttribute The extra information about the text.
- * @return true on success, false if the input connection is no longer
- *
+ * @return true on success, false if the input connection is no longer valid.
*/
default boolean setComposingText(@NonNull CharSequence text, int newCursorPosition,
@Nullable TextAttribute textAttribute) {
@@ -753,7 +752,7 @@
* you are providing so it is not possible to correctly specify
* locations there.
* @param textAttribute The extra information about the text.
- * @return true on success, false if the input connection is no longer
+ * @return true on success, false if the input connection is no longer valid.
*/
default boolean commitText(@NonNull CharSequence text, int newCursorPosition,
@Nullable TextAttribute textAttribute) {
diff --git a/core/java/android/view/inputmethod/InputMethodInfo.java b/core/java/android/view/inputmethod/InputMethodInfo.java
index 0e66f7a..806a593 100644
--- a/core/java/android/view/inputmethod/InputMethodInfo.java
+++ b/core/java/android/view/inputmethod/InputMethodInfo.java
@@ -878,15 +878,18 @@
/**
* Returns {@link Intent} for IME language settings activity with
- * {@link Intent#getAction() Intent action} {@link #ACTION_IME_LANGUAGE_SETTINGS},
- * else <code>null</code> if
- * {@link android.R.styleable#InputMethod_languageSettingsActivity} is not defined.
+ * {@link Intent#getAction() Intent action} {@link #ACTION_IME_LANGUAGE_SETTINGS}. If
+ * {@link android.R.styleable#InputMethod_languageSettingsActivity} is not defined, tries to
+ * fall back to the IME general settings activity. If
+ * {@link android.R.styleable#InputMethod_settingsActivity} is also not defined,
+ * returns {code null}.
*
* <p>To launch IME language settings, use this method to get the {@link Intent} to launch
* the IME language settings activity.</p>
* <p>e.g.<pre><code>startActivity(createImeLanguageSettingsActivityIntent());</code></pre></p>
*
* @attr ref R.styleable#InputMethod_languageSettingsActivity
+ * @attr ref R.styleable#InputMethod_settingsActivity
*/
@FlaggedApi(android.view.inputmethod.Flags.FLAG_IME_SWITCHER_REVAMP_API)
@Nullable
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index eb35817..1922327 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -83,6 +83,7 @@
import android.os.Process;
import android.os.RemoteException;
import android.os.StrictMode;
+import android.os.Trace;
import android.os.UserHandle;
import android.system.Os;
import android.text.TextUtils;
@@ -6246,6 +6247,18 @@
private View inflateView(Context context, RemoteViews rv, @Nullable ViewGroup parent,
@StyleRes int applyThemeResId, @Nullable ColorResources colorResources) {
+ try {
+ Trace.beginSection(rv.hasDrawInstructions()
+ ? "RemoteViews#inflateViewWithDrawInstructions"
+ : "RemoteViews#inflateView");
+ return inflateViewInternal(context, rv, parent, applyThemeResId, colorResources);
+ } finally {
+ Trace.endSection();
+ }
+ }
+
+ private View inflateViewInternal(Context context, RemoteViews rv, @Nullable ViewGroup parent,
+ @StyleRes int applyThemeResId, @Nullable ColorResources colorResources) {
// RemoteViews may be built by an application installed in another
// user. So build a context that loads resources from that user but
// still returns the current users userId so settings like data / time formats
@@ -6384,7 +6397,7 @@
private View mResult;
private ViewTree mTree;
- private Action[] mActions;
+ private List<Action> mActions;
private Exception mError;
private AsyncApplyTask(
@@ -6411,11 +6424,20 @@
if (mRV.mActions != null) {
int count = mRV.mActions.size();
- mActions = new Action[count];
- for (int i = 0; i < count && !isCancelled(); i++) {
- // TODO: check if isCancelled in nested views.
- mActions[i] = mRV.mActions.get(i)
- .initActionAsync(mTree, mParent, mApplyParams);
+ mActions = new ArrayList<>(count);
+ try {
+ Trace.beginSection(hasDrawInstructions()
+ ? "RemoteViews#initActionAsyncWithDrawInstructions"
+ : "RemoteViews#initActionAsync");
+ for (Action action : mRV.mActions) {
+ if (isCancelled()) {
+ break;
+ }
+ // TODO: check if isCancelled in nested views.
+ mActions.add(action.initActionAsync(mTree, mParent, mApplyParams));
+ }
+ } finally {
+ Trace.endSection();
}
} else {
mActions = null;
@@ -6437,14 +6459,7 @@
try {
if (mActions != null) {
-
- ActionApplyParams applyParams = mApplyParams.clone();
- if (applyParams.handler == null) {
- applyParams.handler = DEFAULT_INTERACTION_HANDLER;
- }
- for (Action a : mActions) {
- a.apply(viewTree.mRoot, mParent, applyParams);
- }
+ mRV.performApply(viewTree.mRoot, mParent, mApplyParams, mActions);
}
// If the parent of the view is has is a root, resolve the recycling.
if (mTopLevel && mResult instanceof ViewGroup) {
@@ -6620,6 +6635,11 @@
}
private void performApply(View v, ViewGroup parent, ActionApplyParams params) {
+ performApply(v, parent, params, mActions);
+ }
+
+ private void performApply(
+ View v, ViewGroup parent, ActionApplyParams params, List<Action> actions) {
params = params.clone();
if (params.handler == null) {
params.handler = DEFAULT_INTERACTION_HANDLER;
@@ -6630,8 +6650,15 @@
}
if (mActions != null) {
final int count = mActions.size();
- for (int i = 0; i < count; i++) {
- mActions.get(i).apply(v, parent, params);
+ try {
+ Trace.beginSection(hasDrawInstructions()
+ ? "RemoteViews#applyActionsWithDrawInstructions"
+ : "RemoteViews#applyActions");
+ for (int i = 0; i < count; i++) {
+ mActions.get(i).apply(v, parent, params);
+ }
+ } finally {
+ Trace.endSection();
}
}
}
diff --git a/core/java/android/window/TransitionRequestInfo.java b/core/java/android/window/TransitionRequestInfo.java
index 253337b..fe936f7 100644
--- a/core/java/android/window/TransitionRequestInfo.java
+++ b/core/java/android/window/TransitionRequestInfo.java
@@ -115,8 +115,11 @@
@DataClass(genToString = true, genSetters = true, genBuilder = false, genConstructor = false)
public static final class DisplayChange implements Parcelable {
private final int mDisplayId;
+
+ // If non-null, these bounds changes should ignore any potential rotation changes.
@Nullable private Rect mStartAbsBounds = null;
@Nullable private Rect mEndAbsBounds = null;
+
private int mStartRotation = WindowConfiguration.ROTATION_UNDEFINED;
private int mEndRotation = WindowConfiguration.ROTATION_UNDEFINED;
private boolean mPhysicalDisplayChanged = false;
diff --git a/core/java/com/android/internal/pm/pkg/component/ParsedProviderImpl.java b/core/java/com/android/internal/pm/pkg/component/ParsedProviderImpl.java
index 987fd41..ec5ff4c 100644
--- a/core/java/com/android/internal/pm/pkg/component/ParsedProviderImpl.java
+++ b/core/java/com/android/internal/pm/pkg/component/ParsedProviderImpl.java
@@ -174,7 +174,7 @@
// CHECKSTYLE:OFF Generated code
//
// To regenerate run:
- // $ codegen $ANDROID_BUILD_TOP/frameworks/base/services/core/java/com/android/server/pm/pkg/component/ParsedProviderImpl.java
+ // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/com/android/internal/pm/pkg/component/ParsedProviderImpl.java
//
// To exclude the generated code from IntelliJ auto-formatting enable (one-time):
// Settings > Editor > Code Style > Formatter Control
@@ -298,9 +298,9 @@
}
@DataClass.Generated(
- time = 1642560323360L,
+ time = 1723882842941L,
codegenVersion = "1.0.23",
- sourceFile = "frameworks/base/services/core/java/com/android/server/pm/pkg/component/ParsedProviderImpl.java",
+ sourceFile = "frameworks/base/core/java/com/android/internal/pm/pkg/component/ParsedProviderImpl.java",
inputSignatures = "private @android.annotation.Nullable @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) java.lang.String authority\nprivate boolean syncable\nprivate @android.annotation.Nullable @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) java.lang.String readPermission\nprivate @android.annotation.Nullable @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) java.lang.String writePermission\nprivate boolean grantUriPermissions\nprivate boolean forceUriPermissions\nprivate boolean multiProcess\nprivate int initOrder\nprivate @android.annotation.NonNull java.util.List<android.os.PatternMatcher> uriPermissionPatterns\nprivate @android.annotation.NonNull java.util.List<android.content.pm.PathPermission> pathPermissions\npublic static final @android.annotation.NonNull android.os.Parcelable.Creator<com.android.internal.pm.pkg.component.ParsedProviderImpl> CREATOR\npublic com.android.internal.pm.pkg.component.ParsedProviderImpl setReadPermission(java.lang.String)\npublic com.android.internal.pm.pkg.component.ParsedProviderImpl setWritePermission(java.lang.String)\npublic @android.annotation.NonNull com.android.internal.pm.pkg.component.ParsedProviderImpl addUriPermissionPattern(android.os.PatternMatcher)\npublic @android.annotation.NonNull com.android.internal.pm.pkg.component.ParsedProviderImpl addPathPermission(android.content.pm.PathPermission)\npublic java.lang.String toString()\npublic @java.lang.Override int describeContents()\npublic @java.lang.Override void writeToParcel(android.os.Parcel,int)\nclass ParsedProviderImpl extends com.android.internal.pm.pkg.component.ParsedMainComponentImpl implements [com.android.internal.pm.pkg.component.ParsedProvider, android.os.Parcelable]\n@com.android.internal.util.DataClass(genSetters=true, genGetters=true, genParcelable=false, genBuilder=false)")
@Deprecated
private void __metadata() {}
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index ec004d0..0d0207f 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -418,6 +418,7 @@
mElevation = preservedWindow.getElevation();
mLoadElevation = false;
mForceDecorInstall = true;
+ mDecorFitsSystemWindows = preservedWindow.decorFitsSystemWindows();
setSystemBarAppearance(preservedWindow.getSystemBarAppearance());
// If we're preserving window, carry over the app token from the preserved
// window, as we'll be skipping the addView in handleResumeActivity(), and
diff --git a/core/java/com/android/internal/protolog/LegacyProtoLogImpl.java b/core/java/com/android/internal/protolog/LegacyProtoLogImpl.java
index fcc3023..2feb3d5 100644
--- a/core/java/com/android/internal/protolog/LegacyProtoLogImpl.java
+++ b/core/java/com/android/internal/protolog/LegacyProtoLogImpl.java
@@ -419,7 +419,6 @@
return group.isLogToLogcat() || (group.isLogToProto() && isProtoEnabled());
}
- @Override
public void registerGroups(IProtoLogGroup... protoLogGroups) {
for (IProtoLogGroup group : protoLogGroups) {
mLogGroups.put(group.name(), group);
diff --git a/core/java/com/android/internal/protolog/LogcatOnlyProtoLogImpl.java b/core/java/com/android/internal/protolog/LogcatOnlyProtoLogImpl.java
index ebdad6d..e8d5195 100644
--- a/core/java/com/android/internal/protolog/LogcatOnlyProtoLogImpl.java
+++ b/core/java/com/android/internal/protolog/LogcatOnlyProtoLogImpl.java
@@ -79,9 +79,4 @@
public boolean isEnabled(IProtoLogGroup group, LogLevel level) {
return true;
}
-
- @Override
- public void registerGroups(IProtoLogGroup... protoLogGroups) {
- // Does nothing
- }
}
diff --git a/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java b/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java
index 79a5469..78b5cfe 100644
--- a/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java
+++ b/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java
@@ -89,6 +89,7 @@
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
+import java.util.stream.Stream;
/**
* A service for the ProtoLog logging system.
@@ -125,17 +126,18 @@
private final Lock mBackgroundServiceLock = new ReentrantLock();
private ExecutorService mBackgroundLoggingService = Executors.newSingleThreadExecutor();
- public PerfettoProtoLogImpl() {
- this(null, null, null, () -> {});
+ public PerfettoProtoLogImpl(@NonNull IProtoLogGroup[] groups) {
+ this(null, null, null, () -> {}, groups);
}
- public PerfettoProtoLogImpl(@NonNull Runnable cacheUpdater) {
- this(null, null, null, cacheUpdater);
+ public PerfettoProtoLogImpl(@NonNull Runnable cacheUpdater, @NonNull IProtoLogGroup[] groups) {
+ this(null, null, null, cacheUpdater, groups);
}
public PerfettoProtoLogImpl(
@NonNull String viewerConfigFilePath,
- @NonNull Runnable cacheUpdater) {
+ @NonNull Runnable cacheUpdater,
+ @NonNull IProtoLogGroup[] groups) {
this(viewerConfigFilePath,
null,
new ProtoLogViewerConfigReader(() -> {
@@ -146,22 +148,24 @@
"Failed to load viewer config file " + viewerConfigFilePath, e);
}
}),
- cacheUpdater);
+ cacheUpdater, groups);
}
@VisibleForTesting
public PerfettoProtoLogImpl(
@Nullable ViewerConfigInputStreamProvider viewerConfigInputStreamProvider,
@Nullable ProtoLogViewerConfigReader viewerConfigReader,
- @NonNull Runnable cacheUpdater) {
- this(null, viewerConfigInputStreamProvider, viewerConfigReader, cacheUpdater);
+ @NonNull Runnable cacheUpdater,
+ @NonNull IProtoLogGroup[] groups) {
+ this(null, viewerConfigInputStreamProvider, viewerConfigReader, cacheUpdater, groups);
}
private PerfettoProtoLogImpl(
@Nullable String viewerConfigFilePath,
@Nullable ViewerConfigInputStreamProvider viewerConfigInputStreamProvider,
@Nullable ProtoLogViewerConfigReader viewerConfigReader,
- @NonNull Runnable cacheUpdater) {
+ @NonNull Runnable cacheUpdater,
+ @NonNull IProtoLogGroup[] groups) {
if (viewerConfigFilePath != null && viewerConfigInputStreamProvider != null) {
throw new RuntimeException("Only one of viewerConfigFilePath and "
+ "viewerConfigInputStreamProvider can be set");
@@ -179,6 +183,8 @@
this.mViewerConfigReader = viewerConfigReader;
this.mCacheUpdater = cacheUpdater;
+ registerGroupsLocally(groups);
+
if (android.tracing.Flags.clientSideProtoLogging()) {
mProtoLogService =
IProtoLogService.Stub.asInterface(ServiceManager.getService(PROTOLOG_SERVICE));
@@ -192,6 +198,12 @@
args.setViewerConfigFile(viewerConfigFilePath);
}
+ final var groupArgs = Stream.of(groups)
+ .map(group -> new ProtoLogService.RegisterClientArgs.GroupConfig(
+ group.name(), group.isLogToLogcat()))
+ .toArray(ProtoLogService.RegisterClientArgs.GroupConfig[]::new);
+ args.setGroups(groupArgs);
+
mProtoLogService.registerClient(this, args);
} catch (RemoteException e) {
throw new RuntimeException("Failed to register ProtoLog client");
@@ -294,19 +306,22 @@
|| group.isLogToLogcat();
}
- @Override
- public void registerGroups(IProtoLogGroup... protoLogGroups) {
+ private void registerGroupsLocally(@NonNull IProtoLogGroup[] protoLogGroups) {
+ final var groupsLoggingToLogcat = new ArrayList<String>();
for (IProtoLogGroup protoLogGroup : protoLogGroups) {
mLogGroups.put(protoLogGroup.name(), protoLogGroup);
+
+ if (protoLogGroup.isLogToLogcat()) {
+ groupsLoggingToLogcat.add(protoLogGroup.name());
+ }
}
- final String[] groupsLoggingToLogcat = Arrays.stream(protoLogGroups)
- .filter(IProtoLogGroup::isLogToLogcat)
- .map(IProtoLogGroup::name)
- .toArray(String[]::new);
-
if (mViewerConfigReader != null) {
- mViewerConfigReader.loadViewerConfig(groupsLoggingToLogcat);
+ // Load in background to avoid delay in boot process.
+ // The caveat is that any log message that is also logged to logcat will not be
+ // successfully decoded until this completes.
+ mBackgroundLoggingService.execute(() -> mViewerConfigReader
+ .loadViewerConfig(groupsLoggingToLogcat.toArray(new String[0])));
}
}
diff --git a/core/java/com/android/internal/protolog/ProtoLog.java b/core/java/com/android/internal/protolog/ProtoLog.java
index 87678e5..f9b9894 100644
--- a/core/java/com/android/internal/protolog/ProtoLog.java
+++ b/core/java/com/android/internal/protolog/ProtoLog.java
@@ -50,6 +50,24 @@
private static IProtoLog sProtoLogInstance;
/**
+ * Initialize ProtoLog in this process.
+ * <p>
+ * This method MUST be called before any protologging is performed in this process.
+ * Ensure that all groups that will be used for protologging are registered.
+ *
+ * @param groups The ProtoLog groups that will be used in the process.
+ */
+ public static void init(IProtoLogGroup... groups) {
+ if (android.tracing.Flags.perfettoProtologTracing()) {
+ sProtoLogInstance = new PerfettoProtoLogImpl(groups);
+ } else {
+ // The first call to ProtoLog is likely to flip REQUIRE_PROTOLOGTOOL, which is when this
+ // static block will be executed before REQUIRE_PROTOLOGTOOL is actually set.
+ sProtoLogInstance = new LogcatOnlyProtoLogImpl();
+ }
+ }
+
+ /**
* DEBUG level log.
*
* @param group {@code IProtoLogGroup} controlling this log call.
@@ -150,14 +168,6 @@
return sProtoLogInstance;
}
- /**
- * Registers available protolog groups. A group must be registered before it can be used.
- * @param protoLogGroups The groups to register for use in protolog.
- */
- public static void registerGroups(IProtoLogGroup... protoLogGroups) {
- sProtoLogInstance.registerGroups(protoLogGroups);
- }
-
private static void logStringMessage(LogLevel logLevel, IProtoLogGroup group,
String stringMessage, Object... args) {
if (sProtoLogInstance == null) {
@@ -169,14 +179,4 @@
sProtoLogInstance.log(logLevel, group, stringMessage, args);
}
}
-
- static {
- if (android.tracing.Flags.perfettoProtologTracing()) {
- sProtoLogInstance = new PerfettoProtoLogImpl();
- } else {
- // The first call to ProtoLog is likely to flip REQUIRE_PROTOLOGTOOL, which is when this
- // static block will be executed before REQUIRE_PROTOLOGTOOL is actually set.
- sProtoLogInstance = new LogcatOnlyProtoLogImpl();
- }
- }
}
diff --git a/core/java/com/android/internal/protolog/ProtoLogImpl.java b/core/java/com/android/internal/protolog/ProtoLogImpl.java
index 8659a8f..da6d8cf 100644
--- a/core/java/com/android/internal/protolog/ProtoLogImpl.java
+++ b/core/java/com/android/internal/protolog/ProtoLogImpl.java
@@ -93,35 +93,30 @@
}
/**
- * Registers available protolog groups. A group must be registered before it can be used.
- * @param protoLogGroups The groups to register for use in protolog.
- */
- public static void registerGroups(IProtoLogGroup... protoLogGroups) {
- getSingleInstance().registerGroups(protoLogGroups);
- }
-
- /**
* Returns the single instance of the ProtoLogImpl singleton class.
*/
public static synchronized IProtoLog getSingleInstance() {
if (sServiceInstance == null) {
+ final var groups = sLogGroups.values().toArray(new IProtoLogGroup[0]);
+
if (android.tracing.Flags.perfettoProtologTracing()) {
File f = new File(sViewerConfigPath);
if (!ProtoLog.REQUIRE_PROTOLOGTOOL && !f.exists()) {
// TODO(b/353530422): Remove - temporary fix to unblock b/352290057
- // In so tests the viewer config file might not exist in which we don't
+ // In some tests the viewer config file might not exist in which we don't
// want to provide config path to the user
- sServiceInstance = new PerfettoProtoLogImpl(sCacheUpdater);
+ sServiceInstance = new PerfettoProtoLogImpl(sCacheUpdater, groups);
} else {
- sServiceInstance = new PerfettoProtoLogImpl(sViewerConfigPath, sCacheUpdater);
+ sServiceInstance =
+ new PerfettoProtoLogImpl(sViewerConfigPath, sCacheUpdater, groups);
}
} else {
- sServiceInstance = new LegacyProtoLogImpl(
+ var protologImpl = new LegacyProtoLogImpl(
sLegacyOutputFilePath, sLegacyViewerConfigPath, sCacheUpdater);
+ protologImpl.registerGroups(groups);
+ sServiceInstance = protologImpl;
}
- IProtoLogGroup[] groups = sLogGroups.values().toArray(new IProtoLogGroup[0]);
- sServiceInstance.registerGroups(groups);
sCacheUpdater.run();
}
return sServiceInstance;
diff --git a/core/java/com/android/internal/protolog/common/IProtoLog.java b/core/java/com/android/internal/protolog/common/IProtoLog.java
index f5695ac..d5c2ac1 100644
--- a/core/java/com/android/internal/protolog/common/IProtoLog.java
+++ b/core/java/com/android/internal/protolog/common/IProtoLog.java
@@ -68,10 +68,4 @@
* @return If we need to log this group and level to either ProtoLog or Logcat.
*/
boolean isEnabled(IProtoLogGroup group, LogLevel level);
-
- /**
- * Registers available protolog groups. A group must be registered before it can be used.
- * @param protoLogGroups The groups to register for use in protolog.
- */
- void registerGroups(IProtoLogGroup... protoLogGroups);
}
diff --git a/core/jni/android_window_ScreenCapture.cpp b/core/jni/android_window_ScreenCapture.cpp
index 1031542..b1a2cea 100644
--- a/core/jni/android_window_ScreenCapture.cpp
+++ b/core/jni/android_window_ScreenCapture.cpp
@@ -19,6 +19,7 @@
#include <android/gui/BnScreenCaptureListener.h>
#include <android_runtime/android_hardware_HardwareBuffer.h>
+#include <gui/AidlStatusUtil.h>
#include <gui/SurfaceComposerClient.h>
#include <jni.h>
#include <nativehelper/JNIHelp.h>
@@ -141,12 +142,13 @@
};
static void getCaptureArgs(JNIEnv* env, jobject captureArgsObject, CaptureArgs& captureArgs) {
- captureArgs.pixelFormat = static_cast<ui::PixelFormat>(
+ captureArgs.pixelFormat = static_cast<int32_t>(
env->GetIntField(captureArgsObject, gCaptureArgsClassInfo.pixelFormat));
- captureArgs.sourceCrop =
+ const auto sourceCrop =
JNICommon::rectFromObj(env,
env->GetObjectField(captureArgsObject,
gCaptureArgsClassInfo.sourceCrop));
+ captureArgs.sourceCrop = gui::aidl_utils::toARect(sourceCrop);
captureArgs.frameScaleX =
env->GetFloatField(captureArgsObject, gCaptureArgsClassInfo.frameScaleX);
captureArgs.frameScaleY =
@@ -172,7 +174,7 @@
jniThrowNullPointerException(env, "Exclude layer is null");
return;
}
- captureArgs.excludeHandles.emplace(excludeObject->getHandle());
+ captureArgs.excludeHandles.emplace_back(excludeObject->getHandle());
}
}
captureArgs.hintForSeamlessTransition =
@@ -182,18 +184,18 @@
static DisplayCaptureArgs displayCaptureArgsFromObject(JNIEnv* env,
jobject displayCaptureArgsObject) {
- DisplayCaptureArgs captureArgs;
- getCaptureArgs(env, displayCaptureArgsObject, captureArgs);
+ DisplayCaptureArgs displayCaptureArgs;
+ getCaptureArgs(env, displayCaptureArgsObject, displayCaptureArgs.captureArgs);
- captureArgs.displayToken =
+ displayCaptureArgs.displayToken =
ibinderForJavaObject(env,
env->GetObjectField(displayCaptureArgsObject,
gDisplayCaptureArgsClassInfo.displayToken));
- captureArgs.width =
+ displayCaptureArgs.width =
env->GetIntField(displayCaptureArgsObject, gDisplayCaptureArgsClassInfo.width);
- captureArgs.height =
+ displayCaptureArgs.height =
env->GetIntField(displayCaptureArgsObject, gDisplayCaptureArgsClassInfo.height);
- return captureArgs;
+ return displayCaptureArgs;
}
static jint nativeCaptureDisplay(JNIEnv* env, jclass clazz, jobject displayCaptureArgsObject,
@@ -212,8 +214,8 @@
static jint nativeCaptureLayers(JNIEnv* env, jclass clazz, jobject layerCaptureArgsObject,
jlong screenCaptureListenerObject, jboolean sync) {
- LayerCaptureArgs captureArgs;
- getCaptureArgs(env, layerCaptureArgsObject, captureArgs);
+ LayerCaptureArgs layerCaptureArgs;
+ getCaptureArgs(env, layerCaptureArgsObject, layerCaptureArgs.captureArgs);
SurfaceControl* layer = reinterpret_cast<SurfaceControl*>(
env->GetLongField(layerCaptureArgsObject, gLayerCaptureArgsClassInfo.layer));
@@ -221,13 +223,13 @@
return BAD_VALUE;
}
- captureArgs.layerHandle = layer->getHandle();
- captureArgs.childrenOnly =
+ layerCaptureArgs.layerHandle = layer->getHandle();
+ layerCaptureArgs.childrenOnly =
env->GetBooleanField(layerCaptureArgsObject, gLayerCaptureArgsClassInfo.childrenOnly);
sp<gui::IScreenCaptureListener> captureListener =
reinterpret_cast<gui::IScreenCaptureListener*>(screenCaptureListenerObject);
- return ScreenshotClient::captureLayers(captureArgs, captureListener, sync);
+ return ScreenshotClient::captureLayers(layerCaptureArgs, captureListener, sync);
}
static jlong nativeCreateScreenCaptureListener(JNIEnv* env, jclass clazz, jobject consumerObj) {
diff --git a/core/res/Android.bp b/core/res/Android.bp
index c1edb15..bcc0a97 100644
--- a/core/res/Android.bp
+++ b/core/res/Android.bp
@@ -165,6 +165,7 @@
"com.android.window.flags.window-aconfig",
"android.permission.flags-aconfig",
"android.os.flags-aconfig",
+ "android.os.vibrator.flags-aconfig",
"android.media.tv.flags-aconfig",
],
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 55c66e2..160f651 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2617,7 +2617,8 @@
@hide
-->
<permission android:name="android.permission.VIBRATE_VENDOR_EFFECTS"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged"
+ android:featureFlag="android.os.vibrator.vendor_vibration_effects" />
<!-- @SystemApi Allows access to the vibrator state.
<p>Protection level: signature
diff --git a/core/res/res/layout/input_method_switch_dialog_new.xml b/core/res/res/layout/input_method_switch_dialog_new.xml
index 610a212..058fe3f 100644
--- a/core/res/res/layout/input_method_switch_dialog_new.xml
+++ b/core/res/res/layout/input_method_switch_dialog_new.xml
@@ -71,9 +71,10 @@
android:layout_height="wrap_content"
android:background="@drawable/input_method_switch_button"
android:layout_gravity="end"
- android:text="@string/input_method_language_settings"
+ android:text="@string/input_method_switcher_settings_button"
android:fontFamily="google-sans-text"
android:textAppearance="?attr/textAppearance"
+ android:contentDescription="@string/input_method_language_settings"
android:visibility="gone"/>
</LinearLayout>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index cb58339..f404666 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3280,6 +3280,9 @@
<!-- Accessibility text for the long click action on the switch input method button. This will
be used following "Double-tap and hold to..." [CHAR LIMIT=NONE] -->
<string name="input_method_ime_switch_long_click_action_desc">Open input method picker</string>
+ <!-- Button to access the language settings of the current input method
+ from the Input Method Switcher menu. [CHAR LIMIT=50]-->
+ <string name="input_method_switcher_settings_button">Settings</string>
<!-- If the device is getting low on internal storage, a notification is shown to the user. This is the title of that notification. -->
<string name="low_internal_storage_view_title">Storage space running out</string>
@@ -3883,7 +3886,8 @@
<!-- Title of the pop-up dialog in which the user switches keyboard, also known as input method. -->
<string name="select_input_method">Choose input method</string>
- <!-- Button to access the language settings of the current input method. [CHAR LIMIT=50]-->
+ <!-- Content description of the button to access the language settings of the current input method
+ from the Input Method Switcher menu, for accessibility (not shown on the screen). [CHAR LIMIT=NONE]-->
<string name="input_method_language_settings">Language Settings</string>
<!-- Summary text of a toggle switch to enable/disable use of the IME while a physical
keyboard is connected -->
diff --git a/core/res/res/values/themes_device_defaults.xml b/core/res/res/values/themes_device_defaults.xml
index f5c6738..452ae04 100644
--- a/core/res/res/values/themes_device_defaults.xml
+++ b/core/res/res/values/themes_device_defaults.xml
@@ -212,30 +212,30 @@
<!-- Color palette -->
<item name="colorPrimary">@color/primary_device_default_dark</item>
- <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+ <item name="colorPrimaryDark">@color/primary_device_default_dark</item>
<item name="colorAccent">@color/accent_device_default_dark</item>
- <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
- <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
- <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
- <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_dark_device_default</item>
- <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_dark_device_default</item>
- <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_dark_device_default</item>
- <item name="colorSurface">@color/surface_dark</item>
- <item name="colorSurfaceHighlight">@color/surface_highlight_dark</item>
- <item name="colorSurfaceVariant">@color/surface_variant_dark</item>
- <item name="colorSurfaceHeader">@color/surface_header_dark</item>
+ <item name="colorAccentPrimary">@color/system_primary_dark</item>
+ <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+ <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+ <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item>
+ <item name="colorAccentSecondaryVariant">@color/system_secondary_container_dark</item>
+ <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_dark</item>
+ <item name="colorSurface">@color/system_surface_container_dark</item>
+ <item name="colorSurfaceHighlight">@color/system_surface_bright_dark</item>
+ <item name="colorSurfaceVariant">@color/system_surface_container_high_dark</item>
+ <item name="colorSurfaceHeader">@color/system_surface_container_highest_dark</item>
<item name="colorError">@color/error_color_device_default_dark</item>
- <item name="colorBackground">@color/background_device_default_dark</item>
+ <item name="colorBackground">@color/system_surface_container_dark</item>
<item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
<item name="colorPopupBackground">?attr/colorBackgroundFloating</item>
<item name="panelColorBackground">?attr/colorBackgroundFloating</item>
- <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
- <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
- <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
- <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item>
- <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item>
- <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item>
- <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+ <item name="textColorPrimary">@color/system_on_surface_dark</item>
+ <item name="textColorSecondary">@color/system_on_surface_variant_dark</item>
+ <item name="textColorTertiary">@color/system_outline_dark</item>
+ <item name="textColorPrimaryInverse">@color/system_on_surface_light</item>
+ <item name="textColorSecondaryInverse">@color/system_on_surface_variant_light</item>
+ <item name="textColorTertiaryInverse">@color/system_outline_light</item>
+ <item name="textColorOnAccent">@color/system_on_primary_dark</item>
<item name="colorForeground">@color/foreground_device_default_dark</item>
<item name="colorForegroundInverse">@color/foreground_device_default_light</item>
@@ -314,28 +314,28 @@
<style name="Theme.DeviceDefault.NoActionBar" parent="Theme.Material.NoActionBar">
<!-- Color palette -->
<item name="colorPrimary">@color/primary_device_default_dark</item>
- <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+ <item name="colorPrimaryDark">@color/primary_device_default_dark</item>
<item name="colorAccent">@color/accent_device_default_dark</item>
- <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
- <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
- <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
- <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_dark_device_default</item>
- <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_dark_device_default</item>
- <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_dark_device_default</item>
- <item name="colorSurface">@color/surface_dark</item>
- <item name="colorSurfaceHighlight">@color/surface_highlight_dark</item>
- <item name="colorSurfaceVariant">@color/surface_variant_dark</item>
- <item name="colorSurfaceHeader">@color/surface_header_dark</item>
+ <item name="colorAccentPrimary">@color/system_primary_dark</item>
+ <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+ <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+ <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item>
+ <item name="colorAccentSecondaryVariant">@color/system_secondary_container_dark</item>
+ <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_dark</item>
+ <item name="colorSurface">@color/system_surface_container_dark</item>
+ <item name="colorSurfaceHighlight">@color/system_surface_bright_dark</item>
+ <item name="colorSurfaceVariant">@color/system_surface_container_high_dark</item>
+ <item name="colorSurfaceHeader">@color/system_surface_container_highest_dark</item>
<item name="colorError">@color/error_color_device_default_dark</item>
- <item name="colorBackground">@color/background_device_default_dark</item>
+ <item name="colorBackground">@color/system_surface_container_dark</item>
<item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
- <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
- <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
- <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
- <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item>
- <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item>
- <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item>
- <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+ <item name="textColorPrimary">@color/system_on_surface_dark</item>
+ <item name="textColorSecondary">@color/system_on_surface_variant_dark</item>
+ <item name="textColorTertiary">@color/system_outline_dark</item>
+ <item name="textColorPrimaryInverse">@color/system_on_surface_light</item>
+ <item name="textColorSecondaryInverse">@color/system_on_surface_variant_light</item>
+ <item name="textColorTertiaryInverse">@color/system_outline_light</item>
+ <item name="textColorOnAccent">@color/system_on_primary_dark</item>
<item name="colorForeground">@color/foreground_device_default_dark</item>
<item name="colorForegroundInverse">@color/foreground_device_default_light</item>
@@ -431,28 +431,28 @@
<style name="Theme.DeviceDefault.NoActionBar.Fullscreen" parent="Theme.Material.NoActionBar.Fullscreen">
<!-- Color palette -->
<item name="colorPrimary">@color/primary_device_default_dark</item>
- <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+ <item name="colorPrimaryDark">@color/primary_device_default_dark</item>
<item name="colorAccent">@color/accent_device_default_dark</item>
- <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
- <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
- <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
- <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_dark_device_default</item>
- <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_dark_device_default</item>
- <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_dark_device_default</item>
- <item name="colorSurface">@color/surface_dark</item>
- <item name="colorSurfaceHighlight">@color/surface_highlight_dark</item>
- <item name="colorSurfaceVariant">@color/surface_variant_dark</item>
- <item name="colorSurfaceHeader">@color/surface_header_dark</item>
+ <item name="colorAccentPrimary">@color/system_primary_dark</item>
+ <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+ <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+ <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item>
+ <item name="colorAccentSecondaryVariant">@color/system_secondary_container_dark</item>
+ <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_dark</item>
+ <item name="colorSurface">@color/system_surface_container_dark</item>
+ <item name="colorSurfaceHighlight">@color/system_surface_bright_dark</item>
+ <item name="colorSurfaceVariant">@color/system_surface_container_high_dark</item>
+ <item name="colorSurfaceHeader">@color/system_surface_container_highest_dark</item>
<item name="colorError">@color/error_color_device_default_dark</item>
- <item name="colorBackground">@color/background_device_default_dark</item>
+ <item name="colorBackground">@color/system_surface_container_dark</item>
<item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
- <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
- <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
- <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
- <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item>
- <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item>
- <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item>
- <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+ <item name="textColorPrimary">@color/system_on_surface_dark</item>
+ <item name="textColorSecondary">@color/system_on_surface_variant_dark</item>
+ <item name="textColorTertiary">@color/system_outline_dark</item>
+ <item name="textColorPrimaryInverse">@color/system_on_surface_light</item>
+ <item name="textColorSecondaryInverse">@color/system_on_surface_variant_light</item>
+ <item name="textColorTertiaryInverse">@color/system_outline_light</item>
+ <item name="textColorOnAccent">@color/system_on_primary_dark</item>
<item name="colorForeground">@color/foreground_device_default_dark</item>
<item name="colorForegroundInverse">@color/foreground_device_default_light</item>
@@ -550,28 +550,28 @@
<style name="Theme.DeviceDefault.NoActionBar.Overscan" parent="Theme.Material.NoActionBar.Overscan">
<!-- Color palette -->
<item name="colorPrimary">@color/primary_device_default_dark</item>
- <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+ <item name="colorPrimaryDark">@color/primary_device_default_dark</item>
<item name="colorAccent">@color/accent_device_default_dark</item>
- <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
- <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
- <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
- <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_dark_device_default</item>
- <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_dark_device_default</item>
- <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_dark_device_default</item>
- <item name="colorSurface">@color/surface_dark</item>
- <item name="colorSurfaceHighlight">@color/surface_highlight_dark</item>
- <item name="colorSurfaceVariant">@color/surface_variant_dark</item>
- <item name="colorSurfaceHeader">@color/surface_header_dark</item>
+ <item name="colorAccentPrimary">@color/system_primary_dark</item>
+ <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+ <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+ <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item>
+ <item name="colorAccentSecondaryVariant">@color/system_secondary_container_dark</item>
+ <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_dark</item>
+ <item name="colorSurface">@color/system_surface_container_dark</item>
+ <item name="colorSurfaceHighlight">@color/system_surface_bright_dark</item>
+ <item name="colorSurfaceVariant">@color/system_surface_container_high_dark</item>
+ <item name="colorSurfaceHeader">@color/system_surface_container_highest_dark</item>
<item name="colorError">@color/error_color_device_default_dark</item>
- <item name="colorBackground">@color/background_device_default_dark</item>
+ <item name="colorBackground">@color/system_surface_container_dark</item>
<item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
- <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
- <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
- <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
- <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item>
- <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item>
- <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item>
- <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+ <item name="textColorPrimary">@color/system_on_surface_dark</item>
+ <item name="textColorSecondary">@color/system_on_surface_variant_dark</item>
+ <item name="textColorTertiary">@color/system_outline_dark</item>
+ <item name="textColorPrimaryInverse">@color/system_on_surface_light</item>
+ <item name="textColorSecondaryInverse">@color/system_on_surface_variant_light</item>
+ <item name="textColorTertiaryInverse">@color/system_outline_light</item>
+ <item name="textColorOnAccent">@color/system_on_primary_dark</item>
<item name="colorForeground">@color/foreground_device_default_dark</item>
<item name="colorForegroundInverse">@color/foreground_device_default_light</item>
@@ -668,28 +668,28 @@
<style name="Theme.DeviceDefault.NoActionBar.TranslucentDecor" parent="Theme.Material.NoActionBar.TranslucentDecor">
<!-- Color palette -->
<item name="colorPrimary">@color/primary_device_default_dark</item>
- <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+ <item name="colorPrimaryDark">@color/primary_device_default_dark</item>
<item name="colorAccent">@color/accent_device_default_dark</item>
- <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
- <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
- <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
- <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_dark_device_default</item>
- <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_dark_device_default</item>
- <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_dark_device_default</item>
- <item name="colorSurface">@color/surface_dark</item>
- <item name="colorSurfaceHighlight">@color/surface_highlight_dark</item>
- <item name="colorSurfaceVariant">@color/surface_variant_dark</item>
- <item name="colorSurfaceHeader">@color/surface_header_dark</item>
+ <item name="colorAccentPrimary">@color/system_primary_dark</item>
+ <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+ <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+ <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item>
+ <item name="colorAccentSecondaryVariant">@color/system_secondary_container_dark</item>
+ <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_dark</item>
+ <item name="colorSurface">@color/system_surface_container_dark</item>
+ <item name="colorSurfaceHighlight">@color/system_surface_bright_dark</item>
+ <item name="colorSurfaceVariant">@color/system_surface_container_high_dark</item>
+ <item name="colorSurfaceHeader">@color/system_surface_container_highest_dark</item>
<item name="colorError">@color/error_color_device_default_dark</item>
- <item name="colorBackground">@color/background_device_default_dark</item>
+ <item name="colorBackground">@color/system_surface_container_dark</item>
<item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
- <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
- <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
- <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
- <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item>
- <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item>
- <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item>
- <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+ <item name="textColorPrimary">@color/system_on_surface_dark</item>
+ <item name="textColorSecondary">@color/system_on_surface_variant_dark</item>
+ <item name="textColorTertiary">@color/system_outline_dark</item>
+ <item name="textColorPrimaryInverse">@color/system_on_surface_light</item>
+ <item name="textColorSecondaryInverse">@color/system_on_surface_variant_light</item>
+ <item name="textColorTertiaryInverse">@color/system_outline_light</item>
+ <item name="textColorOnAccent">@color/system_on_primary_dark</item>
<item name="colorForeground">@color/foreground_device_default_dark</item>
<item name="colorForegroundInverse">@color/foreground_device_default_light</item>
@@ -801,28 +801,28 @@
<!-- Color palette -->
<item name="colorPrimary">@color/primary_device_default_dark</item>
- <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+ <item name="colorPrimaryDark">@color/primary_device_default_dark</item>
<item name="colorAccent">@color/accent_device_default_dark</item>
- <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
- <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
- <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
- <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_dark_device_default</item>
- <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_dark_device_default</item>
- <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_dark_device_default</item>
- <item name="colorSurface">@color/surface_dark</item>
- <item name="colorSurfaceHighlight">@color/surface_highlight_dark</item>
- <item name="colorSurfaceVariant">@color/surface_variant_dark</item>
- <item name="colorSurfaceHeader">@color/surface_header_dark</item>
+ <item name="colorAccentPrimary">@color/system_primary_dark</item>
+ <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+ <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+ <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item>
+ <item name="colorAccentSecondaryVariant">@color/system_secondary_container_dark</item>
+ <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_dark</item>
+ <item name="colorSurface">@color/system_surface_container_dark</item>
+ <item name="colorSurfaceHighlight">@color/system_surface_bright_dark</item>
+ <item name="colorSurfaceVariant">@color/system_surface_container_high_dark</item>
+ <item name="colorSurfaceHeader">@color/system_surface_container_highest_dark</item>
<item name="colorError">@color/error_color_device_default_dark</item>
- <item name="colorBackground">@color/background_device_default_dark</item>
+ <item name="colorBackground">@color/system_surface_container_dark</item>
<item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
- <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
- <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
- <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
- <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item>
- <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item>
- <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item>
- <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+ <item name="textColorPrimary">@color/system_on_surface_dark</item>
+ <item name="textColorSecondary">@color/system_on_surface_variant_dark</item>
+ <item name="textColorTertiary">@color/system_outline_dark</item>
+ <item name="textColorPrimaryInverse">@color/system_on_surface_light</item>
+ <item name="textColorSecondaryInverse">@color/system_on_surface_variant_light</item>
+ <item name="textColorTertiaryInverse">@color/system_outline_light</item>
+ <item name="textColorOnAccent">@color/system_on_primary_dark</item>
<item name="colorForeground">@color/foreground_device_default_dark</item>
<item name="colorForegroundInverse">@color/foreground_device_default_light</item>
@@ -911,28 +911,28 @@
<style name="Theme.DeviceDefault.Dialog.MinWidth" parent="Theme.Material.Dialog.MinWidth">
<!-- Color palette -->
<item name="colorPrimary">@color/primary_device_default_dark</item>
- <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+ <item name="colorPrimaryDark">@color/primary_device_default_dark</item>
<item name="colorAccent">@color/accent_device_default_dark</item>
- <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
- <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
- <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
- <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_dark_device_default</item>
- <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_dark_device_default</item>
- <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_dark_device_default</item>
- <item name="colorSurface">@color/surface_dark</item>
- <item name="colorSurfaceHighlight">@color/surface_highlight_dark</item>
- <item name="colorSurfaceVariant">@color/surface_variant_dark</item>
- <item name="colorSurfaceHeader">@color/surface_header_dark</item>
+ <item name="colorAccentPrimary">@color/system_primary_dark</item>
+ <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+ <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+ <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item>
+ <item name="colorAccentSecondaryVariant">@color/system_secondary_container_dark</item>
+ <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_dark</item>
+ <item name="colorSurface">@color/system_surface_container_dark</item>
+ <item name="colorSurfaceHighlight">@color/system_surface_bright_dark</item>
+ <item name="colorSurfaceVariant">@color/system_surface_container_high_dark</item>
+ <item name="colorSurfaceHeader">@color/system_surface_container_highest_dark</item>
<item name="colorError">@color/error_color_device_default_dark</item>
- <item name="colorBackground">@color/background_device_default_dark</item>
+ <item name="colorBackground">@color/system_surface_container_dark</item>
<item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
- <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
- <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
- <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
- <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item>
- <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item>
- <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item>
- <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+ <item name="textColorPrimary">@color/system_on_surface_dark</item>
+ <item name="textColorSecondary">@color/system_on_surface_variant_dark</item>
+ <item name="textColorTertiary">@color/system_outline_dark</item>
+ <item name="textColorPrimaryInverse">@color/system_on_surface_light</item>
+ <item name="textColorSecondaryInverse">@color/system_on_surface_variant_light</item>
+ <item name="textColorTertiaryInverse">@color/system_outline_light</item>
+ <item name="textColorOnAccent">@color/system_on_primary_dark</item>
<item name="colorForeground">@color/foreground_device_default_dark</item>
<item name="colorForegroundInverse">@color/foreground_device_default_light</item>
@@ -1027,28 +1027,28 @@
<style name="Theme.DeviceDefault.Dialog.NoActionBar" parent="Theme.Material.Dialog.NoActionBar">
<!-- Color palette -->
<item name="colorPrimary">@color/primary_device_default_dark</item>
- <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+ <item name="colorPrimaryDark">@color/primary_device_default_dark</item>
<item name="colorAccent">@color/accent_device_default_dark</item>
- <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
- <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
- <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
- <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_dark_device_default</item>
- <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_dark_device_default</item>
- <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_dark_device_default</item>
- <item name="colorSurface">@color/surface_dark</item>
- <item name="colorSurfaceHighlight">@color/surface_highlight_dark</item>
- <item name="colorSurfaceVariant">@color/surface_variant_dark</item>
- <item name="colorSurfaceHeader">@color/surface_header_dark</item>
+ <item name="colorAccentPrimary">@color/system_primary_dark</item>
+ <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+ <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+ <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item>
+ <item name="colorAccentSecondaryVariant">@color/system_secondary_container_dark</item>
+ <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_dark</item>
+ <item name="colorSurface">@color/system_surface_container_dark</item>
+ <item name="colorSurfaceHighlight">@color/system_surface_bright_dark</item>
+ <item name="colorSurfaceVariant">@color/system_surface_container_high_dark</item>
+ <item name="colorSurfaceHeader">@color/system_surface_container_highest_dark</item>
<item name="colorError">@color/error_color_device_default_dark</item>
- <item name="colorBackground">@color/background_device_default_dark</item>
+ <item name="colorBackground">@color/system_surface_container_dark</item>
<item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
- <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
- <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
- <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
- <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item>
- <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item>
- <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item>
- <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+ <item name="textColorPrimary">@color/system_on_surface_dark</item>
+ <item name="textColorSecondary">@color/system_on_surface_variant_dark</item>
+ <item name="textColorTertiary">@color/system_outline_dark</item>
+ <item name="textColorPrimaryInverse">@color/system_on_surface_light</item>
+ <item name="textColorSecondaryInverse">@color/system_on_surface_variant_light</item>
+ <item name="textColorTertiaryInverse">@color/system_outline_light</item>
+ <item name="textColorOnAccent">@color/system_on_primary_dark</item>
<item name="colorForeground">@color/foreground_device_default_dark</item>
<item name="colorForegroundInverse">@color/foreground_device_default_light</item>
@@ -1144,28 +1144,28 @@
<style name="Theme.DeviceDefault.Dialog.NoActionBar.MinWidth" parent="Theme.Material.Dialog.NoActionBar.MinWidth">
<!-- Color palette -->
<item name="colorPrimary">@color/primary_device_default_dark</item>
- <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+ <item name="colorPrimaryDark">@color/primary_device_default_dark</item>
<item name="colorAccent">@color/accent_device_default_dark</item>
- <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
- <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
- <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
- <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_dark_device_default</item>
- <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_dark_device_default</item>
- <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_dark_device_default</item>
- <item name="colorSurface">@color/surface_dark</item>
- <item name="colorSurfaceHighlight">@color/surface_highlight_dark</item>
- <item name="colorSurfaceVariant">@color/surface_variant_dark</item>
- <item name="colorSurfaceHeader">@color/surface_header_dark</item>
+ <item name="colorAccentPrimary">@color/system_primary_dark</item>
+ <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+ <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+ <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item>
+ <item name="colorAccentSecondaryVariant">@color/system_secondary_container_dark</item>
+ <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_dark</item>
+ <item name="colorSurface">@color/system_surface_container_dark</item>
+ <item name="colorSurfaceHighlight">@color/system_surface_bright_dark</item>
+ <item name="colorSurfaceVariant">@color/system_surface_container_high_dark</item>
+ <item name="colorSurfaceHeader">@color/system_surface_container_highest_dark</item>
<item name="colorError">@color/error_color_device_default_dark</item>
- <item name="colorBackground">@color/background_device_default_dark</item>
+ <item name="colorBackground">@color/system_surface_container_dark</item>
<item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
- <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
- <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
- <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
- <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item>
- <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item>
- <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item>
- <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+ <item name="textColorPrimary">@color/system_on_surface_dark</item>
+ <item name="textColorSecondary">@color/system_on_surface_variant_dark</item>
+ <item name="textColorTertiary">@color/system_outline_dark</item>
+ <item name="textColorPrimaryInverse">@color/system_on_surface_light</item>
+ <item name="textColorSecondaryInverse">@color/system_on_surface_variant_light</item>
+ <item name="textColorTertiaryInverse">@color/system_outline_light</item>
+ <item name="textColorOnAccent">@color/system_on_primary_dark</item>
<item name="colorForeground">@color/foreground_device_default_dark</item>
<item name="colorForegroundInverse">@color/foreground_device_default_light</item>
@@ -1277,28 +1277,28 @@
<style name="Theme.DeviceDefault.DialogWhenLarge" parent="Theme.Material.DialogWhenLarge">
<!-- Color palette -->
<item name="colorPrimary">@color/primary_device_default_dark</item>
- <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+ <item name="colorPrimaryDark">@color/primary_device_default_dark</item>
<item name="colorAccent">@color/accent_device_default_dark</item>
- <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
- <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
- <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
- <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_dark_device_default</item>
- <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_dark_device_default</item>
- <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_dark_device_default</item>
- <item name="colorSurface">@color/surface_dark</item>
- <item name="colorSurfaceHighlight">@color/surface_highlight_dark</item>
- <item name="colorSurfaceVariant">@color/surface_variant_dark</item>
- <item name="colorSurfaceHeader">@color/surface_header_dark</item>
+ <item name="colorAccentPrimary">@color/system_primary_dark</item>
+ <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+ <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+ <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item>
+ <item name="colorAccentSecondaryVariant">@color/system_secondary_container_dark</item>
+ <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_dark</item>
+ <item name="colorSurface">@color/system_surface_container_dark</item>
+ <item name="colorSurfaceHighlight">@color/system_surface_bright_dark</item>
+ <item name="colorSurfaceVariant">@color/system_surface_container_high_dark</item>
+ <item name="colorSurfaceHeader">@color/system_surface_container_highest_dark</item>
<item name="colorError">@color/error_color_device_default_dark</item>
- <item name="colorBackground">@color/background_device_default_dark</item>
+ <item name="colorBackground">@color/system_surface_container_dark</item>
<item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
- <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
- <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
- <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
- <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item>
- <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item>
- <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item>
- <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+ <item name="textColorPrimary">@color/system_on_surface_dark</item>
+ <item name="textColorSecondary">@color/system_on_surface_variant_dark</item>
+ <item name="textColorTertiary">@color/system_outline_dark</item>
+ <item name="textColorPrimaryInverse">@color/system_on_surface_light</item>
+ <item name="textColorSecondaryInverse">@color/system_on_surface_variant_light</item>
+ <item name="textColorTertiaryInverse">@color/system_outline_light</item>
+ <item name="textColorOnAccent">@color/system_on_primary_dark</item>
<item name="colorForeground">@color/foreground_device_default_dark</item>
<item name="colorForegroundInverse">@color/foreground_device_default_light</item>
@@ -1395,28 +1395,28 @@
<style name="Theme.DeviceDefault.DialogWhenLarge.NoActionBar" parent="Theme.Material.DialogWhenLarge.NoActionBar">
<!-- Color palette -->
<item name="colorPrimary">@color/primary_device_default_dark</item>
- <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+ <item name="colorPrimaryDark">@color/primary_device_default_dark</item>
<item name="colorAccent">@color/accent_device_default_dark</item>
- <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
- <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
- <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
- <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_dark_device_default</item>
- <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_dark_device_default</item>
- <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_dark_device_default</item>
- <item name="colorSurface">@color/surface_dark</item>
- <item name="colorSurfaceHighlight">@color/surface_highlight_dark</item>
- <item name="colorSurfaceVariant">@color/surface_variant_dark</item>
- <item name="colorSurfaceHeader">@color/surface_header_dark</item>
+ <item name="colorAccentPrimary">@color/system_primary_dark</item>
+ <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+ <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+ <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item>
+ <item name="colorAccentSecondaryVariant">@color/system_secondary_container_dark</item>
+ <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_dark</item>
+ <item name="colorSurface">@color/system_surface_container_dark</item>
+ <item name="colorSurfaceHighlight">@color/system_surface_bright_dark</item>
+ <item name="colorSurfaceVariant">@color/system_surface_container_high_dark</item>
+ <item name="colorSurfaceHeader">@color/system_surface_container_highest_dark</item>
<item name="colorError">@color/error_color_device_default_dark</item>
- <item name="colorBackground">@color/background_device_default_dark</item>
+ <item name="colorBackground">@color/system_surface_container_dark</item>
<item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
- <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
- <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
- <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
- <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item>
- <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item>
- <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item>
- <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+ <item name="textColorPrimary">@color/system_on_surface_dark</item>
+ <item name="textColorSecondary">@color/system_on_surface_variant_dark</item>
+ <item name="textColorTertiary">@color/system_outline_dark</item>
+ <item name="textColorPrimaryInverse">@color/system_on_surface_light</item>
+ <item name="textColorSecondaryInverse">@color/system_on_surface_variant_light</item>
+ <item name="textColorTertiaryInverse">@color/system_outline_light</item>
+ <item name="textColorOnAccent">@color/system_on_primary_dark</item>
<item name="colorForeground">@color/foreground_device_default_dark</item>
<item name="colorForegroundInverse">@color/foreground_device_default_light</item>
@@ -1511,28 +1511,28 @@
<style name="Theme.DeviceDefault.Dialog.Presentation" parent="Theme.Material.Dialog.Presentation">
<!-- Color palette -->
<item name="colorPrimary">@color/primary_device_default_dark</item>
- <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+ <item name="colorPrimaryDark">@color/primary_device_default_dark</item>
<item name="colorAccent">@color/accent_device_default_dark</item>
- <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
- <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
- <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
- <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_dark_device_default</item>
- <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_dark_device_default</item>
- <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_dark_device_default</item>
- <item name="colorSurface">@color/surface_dark</item>
- <item name="colorSurfaceHighlight">@color/surface_highlight_dark</item>
- <item name="colorSurfaceVariant">@color/surface_variant_dark</item>
- <item name="colorSurfaceHeader">@color/surface_header_dark</item>
+ <item name="colorAccentPrimary">@color/system_primary_dark</item>
+ <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+ <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+ <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item>
+ <item name="colorAccentSecondaryVariant">@color/system_secondary_container_dark</item>
+ <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_dark</item>
+ <item name="colorSurface">@color/system_surface_container_dark</item>
+ <item name="colorSurfaceHighlight">@color/system_surface_bright_dark</item>
+ <item name="colorSurfaceVariant">@color/system_surface_container_high_dark</item>
+ <item name="colorSurfaceHeader">@color/system_surface_container_highest_dark</item>
<item name="colorError">@color/error_color_device_default_dark</item>
- <item name="colorBackground">@color/background_device_default_dark</item>
+ <item name="colorBackground">@color/system_surface_container_dark</item>
<item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
- <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
- <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
- <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
- <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item>
- <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item>
- <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item>
- <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+ <item name="textColorPrimary">@color/system_on_surface_dark</item>
+ <item name="textColorSecondary">@color/system_on_surface_variant_dark</item>
+ <item name="textColorTertiary">@color/system_outline_dark</item>
+ <item name="textColorPrimaryInverse">@color/system_on_surface_light</item>
+ <item name="textColorSecondaryInverse">@color/system_on_surface_variant_light</item>
+ <item name="textColorTertiaryInverse">@color/system_outline_light</item>
+ <item name="textColorOnAccent">@color/system_on_primary_dark</item>
<item name="colorForeground">@color/foreground_device_default_dark</item>
<item name="colorForegroundInverse">@color/foreground_device_default_light</item>
@@ -1629,28 +1629,28 @@
<style name="Theme.DeviceDefault.Panel" parent="Theme.Material.Panel">
<!-- Color palette -->
<item name="colorPrimary">@color/primary_device_default_dark</item>
- <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+ <item name="colorPrimaryDark">@color/primary_device_default_dark</item>
<item name="colorAccent">@color/accent_device_default_dark</item>
- <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
- <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
- <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
- <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_dark_device_default</item>
- <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_dark_device_default</item>
- <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_dark_device_default</item>
- <item name="colorSurface">@color/surface_dark</item>
- <item name="colorSurfaceHighlight">@color/surface_highlight_dark</item>
- <item name="colorSurfaceVariant">@color/surface_variant_dark</item>
- <item name="colorSurfaceHeader">@color/surface_header_dark</item>
+ <item name="colorAccentPrimary">@color/system_primary_dark</item>
+ <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+ <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+ <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item>
+ <item name="colorAccentSecondaryVariant">@color/system_secondary_container_dark</item>
+ <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_dark</item>
+ <item name="colorSurface">@color/system_surface_container_dark</item>
+ <item name="colorSurfaceHighlight">@color/system_surface_bright_dark</item>
+ <item name="colorSurfaceVariant">@color/system_surface_container_high_dark</item>
+ <item name="colorSurfaceHeader">@color/system_surface_container_highest_dark</item>
<item name="colorError">@color/error_color_device_default_dark</item>
- <item name="colorBackground">@color/background_device_default_dark</item>
+ <item name="colorBackground">@color/system_surface_container_dark</item>
<item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
- <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
- <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
- <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
- <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item>
- <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item>
- <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item>
- <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+ <item name="textColorPrimary">@color/system_on_surface_dark</item>
+ <item name="textColorSecondary">@color/system_on_surface_variant_dark</item>
+ <item name="textColorTertiary">@color/system_outline_dark</item>
+ <item name="textColorPrimaryInverse">@color/system_on_surface_light</item>
+ <item name="textColorSecondaryInverse">@color/system_on_surface_variant_light</item>
+ <item name="textColorTertiaryInverse">@color/system_outline_light</item>
+ <item name="textColorOnAccent">@color/system_on_primary_dark</item>
<item name="colorForeground">@color/foreground_device_default_dark</item>
<item name="colorForegroundInverse">@color/foreground_device_default_light</item>
@@ -1746,28 +1746,28 @@
<style name="Theme.DeviceDefault.Wallpaper" parent="Theme.Material.Wallpaper">
<!-- Color palette -->
<item name="colorPrimary">@color/primary_device_default_dark</item>
- <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+ <item name="colorPrimaryDark">@color/primary_device_default_dark</item>
<item name="colorAccent">@color/accent_device_default_dark</item>
- <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
- <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
- <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
- <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_dark_device_default</item>
- <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_dark_device_default</item>
- <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_dark_device_default</item>
- <item name="colorSurface">@color/surface_dark</item>
- <item name="colorSurfaceHighlight">@color/surface_highlight_dark</item>
- <item name="colorSurfaceVariant">@color/surface_variant_dark</item>
- <item name="colorSurfaceHeader">@color/surface_header_dark</item>
+ <item name="colorAccentPrimary">@color/system_primary_dark</item>
+ <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+ <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+ <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item>
+ <item name="colorAccentSecondaryVariant">@color/system_secondary_container_dark</item>
+ <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_dark</item>
+ <item name="colorSurface">@color/system_surface_container_dark</item>
+ <item name="colorSurfaceHighlight">@color/system_surface_bright_dark</item>
+ <item name="colorSurfaceVariant">@color/system_surface_container_high_dark</item>
+ <item name="colorSurfaceHeader">@color/system_surface_container_highest_dark</item>
<item name="colorError">@color/error_color_device_default_dark</item>
- <item name="colorBackground">@color/background_device_default_dark</item>
+ <item name="colorBackground">@color/system_surface_container_dark</item>
<item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
- <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
- <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
- <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
- <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item>
- <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item>
- <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item>
- <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+ <item name="textColorPrimary">@color/system_on_surface_dark</item>
+ <item name="textColorSecondary">@color/system_on_surface_variant_dark</item>
+ <item name="textColorTertiary">@color/system_outline_dark</item>
+ <item name="textColorPrimaryInverse">@color/system_on_surface_light</item>
+ <item name="textColorSecondaryInverse">@color/system_on_surface_variant_light</item>
+ <item name="textColorTertiaryInverse">@color/system_outline_light</item>
+ <item name="textColorOnAccent">@color/system_on_primary_dark</item>
<item name="colorForeground">@color/foreground_device_default_dark</item>
<item name="colorForegroundInverse">@color/foreground_device_default_light</item>
@@ -1863,28 +1863,28 @@
<style name="Theme.DeviceDefault.Wallpaper.NoTitleBar" parent="Theme.Material.Wallpaper.NoTitleBar">
<!-- Color palette -->
<item name="colorPrimary">@color/primary_device_default_dark</item>
- <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+ <item name="colorPrimaryDark">@color/primary_device_default_dark</item>
<item name="colorAccent">@color/accent_device_default_dark</item>
- <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
- <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
- <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
- <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_dark_device_default</item>
- <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_dark_device_default</item>
- <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_dark_device_default</item>
- <item name="colorSurface">@color/surface_dark</item>
- <item name="colorSurfaceHighlight">@color/surface_highlight_dark</item>
- <item name="colorSurfaceVariant">@color/surface_variant_dark</item>
- <item name="colorSurfaceHeader">@color/surface_header_dark</item>
+ <item name="colorAccentPrimary">@color/system_primary_dark</item>
+ <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+ <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+ <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item>
+ <item name="colorAccentSecondaryVariant">@color/system_secondary_container_dark</item>
+ <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_dark</item>
+ <item name="colorSurface">@color/system_surface_container_dark</item>
+ <item name="colorSurfaceHighlight">@color/system_surface_bright_dark</item>
+ <item name="colorSurfaceVariant">@color/system_surface_container_high_dark</item>
+ <item name="colorSurfaceHeader">@color/system_surface_container_highest_dark</item>
<item name="colorError">@color/error_color_device_default_dark</item>
- <item name="colorBackground">@color/background_device_default_dark</item>
+ <item name="colorBackground">@color/system_surface_container_dark</item>
<item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
- <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
- <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
- <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
- <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item>
- <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item>
- <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item>
- <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+ <item name="textColorPrimary">@color/system_on_surface_dark</item>
+ <item name="textColorSecondary">@color/system_on_surface_variant_dark</item>
+ <item name="textColorTertiary">@color/system_outline_dark</item>
+ <item name="textColorPrimaryInverse">@color/system_on_surface_light</item>
+ <item name="textColorSecondaryInverse">@color/system_on_surface_variant_light</item>
+ <item name="textColorTertiaryInverse">@color/system_outline_light</item>
+ <item name="textColorOnAccent">@color/system_on_primary_dark</item>
<item name="colorForeground">@color/foreground_device_default_dark</item>
<item name="colorForegroundInverse">@color/foreground_device_default_light</item>
@@ -1980,28 +1980,28 @@
<style name="Theme.DeviceDefault.InputMethod" parent="Theme.Material.InputMethod">
<!-- Color palette -->
<item name="colorPrimary">@color/primary_device_default_light</item>
- <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+ <item name="colorPrimaryDark">@color/primary_device_default_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
- <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
- <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
- <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
- <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item>
- <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item>
- <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item>
- <item name="colorSurface">@color/surface_light</item>
- <item name="colorSurfaceHighlight">@color/surface_highlight_light</item>
- <item name="colorSurfaceVariant">@color/surface_variant_light</item>
- <item name="colorSurfaceHeader">@color/surface_header_light</item>
+ <item name="colorAccentPrimary">@color/system_primary_dark</item>
+ <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+ <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+ <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
+ <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item>
+ <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item>
+ <item name="colorSurface">@color/system_surface_container_light</item>
+ <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item>
+ <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item>
+ <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item>
<item name="colorError">@color/error_color_device_default_light</item>
- <item name="colorBackground">@color/background_device_default_light</item>
+ <item name="colorBackground">@color/system_surface_container_light</item>
<item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
- <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
- <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
- <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
- <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
- <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
- <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
- <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+ <item name="textColorPrimary">@color/system_on_surface_light</item>
+ <item name="textColorSecondary">@color/system_on_surface_variant_light</item>
+ <item name="textColorTertiary">@color/system_outline_light</item>
+ <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item>
+ <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item>
+ <item name="textColorTertiaryInverse">@color/system_outline_dark</item>
+ <item name="textColorOnAccent">@color/system_on_primary_dark</item>
<item name="colorForeground">@color/foreground_device_default_light</item>
<item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
@@ -2097,28 +2097,28 @@
<style name="Theme.DeviceDefault.VoiceInteractionSession" parent="Theme.Material.VoiceInteractionSession">
<!-- Color palette -->
<item name="colorPrimary">@color/primary_device_default_light</item>
- <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+ <item name="colorPrimaryDark">@color/primary_device_default_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
- <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
- <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
- <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
- <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item>
- <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item>
- <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item>
- <item name="colorSurface">@color/surface_light</item>
- <item name="colorSurfaceHighlight">@color/surface_highlight_light</item>
- <item name="colorSurfaceVariant">@color/surface_variant_light</item>
- <item name="colorSurfaceHeader">@color/surface_header_light</item>
+ <item name="colorAccentPrimary">@color/system_primary_dark</item>
+ <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+ <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+ <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
+ <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item>
+ <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item>
+ <item name="colorSurface">@color/system_surface_container_light</item>
+ <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item>
+ <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item>
+ <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item>
<item name="colorError">@color/error_color_device_default_light</item>
- <item name="colorBackground">@color/background_device_default_light</item>
+ <item name="colorBackground">@color/system_surface_container_light</item>
<item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
- <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
- <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
- <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
- <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
- <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
- <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
- <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+ <item name="textColorPrimary">@color/system_on_surface_light</item>
+ <item name="textColorSecondary">@color/system_on_surface_variant_light</item>
+ <item name="textColorTertiary">@color/system_outline_light</item>
+ <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item>
+ <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item>
+ <item name="textColorTertiaryInverse">@color/system_outline_dark</item>
+ <item name="textColorOnAccent">@color/system_on_primary_dark</item>
<item name="colorForeground">@color/foreground_device_default_light</item>
<item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
@@ -2218,28 +2218,28 @@
<!-- Color palette -->
<item name="colorPrimary">@color/primary_device_default_dark</item>
- <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+ <item name="colorPrimaryDark">@color/primary_device_default_dark</item>
<item name="colorAccent">@color/accent_device_default_dark</item>
- <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
- <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
- <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
- <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_dark_device_default</item>
- <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_dark_device_default</item>
- <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_dark_device_default</item>
- <item name="colorSurface">@color/surface_dark</item>
- <item name="colorSurfaceHighlight">@color/surface_highlight_dark</item>
- <item name="colorSurfaceVariant">@color/surface_variant_dark</item>
- <item name="colorSurfaceHeader">@color/surface_header_dark</item>
+ <item name="colorAccentPrimary">@color/system_primary_dark</item>
+ <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+ <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+ <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item>
+ <item name="colorAccentSecondaryVariant">@color/system_secondary_container_dark</item>
+ <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_dark</item>
+ <item name="colorSurface">@color/system_surface_container_dark</item>
+ <item name="colorSurfaceHighlight">@color/system_surface_bright_dark</item>
+ <item name="colorSurfaceVariant">@color/system_surface_container_high_dark</item>
+ <item name="colorSurfaceHeader">@color/system_surface_container_highest_dark</item>
<item name="colorError">@color/error_color_device_default_dark</item>
- <item name="colorBackground">@color/background_device_default_dark</item>
+ <item name="colorBackground">@color/system_surface_container_dark</item>
<item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
- <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
- <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
- <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
- <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item>
- <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item>
- <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item>
- <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+ <item name="textColorPrimary">@color/system_on_surface_dark</item>
+ <item name="textColorSecondary">@color/system_on_surface_variant_dark</item>
+ <item name="textColorTertiary">@color/system_outline_dark</item>
+ <item name="textColorPrimaryInverse">@color/system_on_surface_light</item>
+ <item name="textColorSecondaryInverse">@color/system_on_surface_variant_light</item>
+ <item name="textColorTertiaryInverse">@color/system_outline_light</item>
+ <item name="textColorOnAccent">@color/system_on_primary_dark</item>
<item name="colorForeground">@color/foreground_device_default_dark</item>
<item name="colorForegroundInverse">@color/foreground_device_default_light</item>
@@ -2336,28 +2336,28 @@
<style name="Theme.DeviceDefault.SearchBar" parent="Theme.Material.SearchBar">
<!-- Color palette -->
<item name="colorPrimary">@color/primary_device_default_dark</item>
- <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+ <item name="colorPrimaryDark">@color/primary_device_default_dark</item>
<item name="colorAccent">@color/accent_device_default_dark</item>
- <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
- <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
- <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
- <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_dark_device_default</item>
- <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_dark_device_default</item>
- <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_dark_device_default</item>
- <item name="colorSurface">@color/surface_dark</item>
- <item name="colorSurfaceHighlight">@color/surface_highlight_dark</item>
- <item name="colorSurfaceVariant">@color/surface_variant_dark</item>
- <item name="colorSurfaceHeader">@color/surface_header_dark</item>
+ <item name="colorAccentPrimary">@color/system_primary_dark</item>
+ <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+ <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+ <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item>
+ <item name="colorAccentSecondaryVariant">@color/system_secondary_container_dark</item>
+ <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_dark</item>
+ <item name="colorSurface">@color/system_surface_container_dark</item>
+ <item name="colorSurfaceHighlight">@color/system_surface_bright_dark</item>
+ <item name="colorSurfaceVariant">@color/system_surface_container_high_dark</item>
+ <item name="colorSurfaceHeader">@color/system_surface_container_highest_dark</item>
<item name="colorError">@color/error_color_device_default_dark</item>
- <item name="colorBackground">@color/background_device_default_dark</item>
+ <item name="colorBackground">@color/system_surface_container_dark</item>
<item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
- <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
- <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
- <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
- <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item>
- <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item>
- <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item>
- <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+ <item name="textColorPrimary">@color/system_on_surface_dark</item>
+ <item name="textColorSecondary">@color/system_on_surface_variant_dark</item>
+ <item name="textColorTertiary">@color/system_outline_dark</item>
+ <item name="textColorPrimaryInverse">@color/system_on_surface_light</item>
+ <item name="textColorSecondaryInverse">@color/system_on_surface_variant_light</item>
+ <item name="textColorTertiaryInverse">@color/system_outline_light</item>
+ <item name="textColorOnAccent">@color/system_on_primary_dark</item>
<item name="colorForeground">@color/foreground_device_default_dark</item>
<item name="colorForegroundInverse">@color/foreground_device_default_light</item>
@@ -2451,28 +2451,28 @@
<style name="Theme.DeviceDefault.Dialog.NoFrame" parent="Theme.Material.Dialog.NoFrame">
<!-- Color palette -->
<item name="colorPrimary">@color/primary_device_default_dark</item>
- <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+ <item name="colorPrimaryDark">@color/primary_device_default_dark</item>
<item name="colorAccent">@color/accent_device_default_dark</item>
- <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
- <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
- <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
- <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_dark_device_default</item>
- <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_dark_device_default</item>
- <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_dark_device_default</item>
- <item name="colorSurface">@color/surface_dark</item>
- <item name="colorSurfaceHighlight">@color/surface_highlight_dark</item>
- <item name="colorSurfaceVariant">@color/surface_variant_dark</item>
- <item name="colorSurfaceHeader">@color/surface_header_dark</item>
+ <item name="colorAccentPrimary">@color/system_primary_dark</item>
+ <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+ <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+ <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item>
+ <item name="colorAccentSecondaryVariant">@color/system_secondary_container_dark</item>
+ <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_dark</item>
+ <item name="colorSurface">@color/system_surface_container_dark</item>
+ <item name="colorSurfaceHighlight">@color/system_surface_bright_dark</item>
+ <item name="colorSurfaceVariant">@color/system_surface_container_high_dark</item>
+ <item name="colorSurfaceHeader">@color/system_surface_container_highest_dark</item>
<item name="colorError">@color/error_color_device_default_dark</item>
- <item name="colorBackground">@color/background_device_default_dark</item>
+ <item name="colorBackground">@color/system_surface_container_dark</item>
<item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
- <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
- <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
- <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
- <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item>
- <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item>
- <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item>
- <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+ <item name="textColorPrimary">@color/system_on_surface_dark</item>
+ <item name="textColorSecondary">@color/system_on_surface_variant_dark</item>
+ <item name="textColorTertiary">@color/system_outline_dark</item>
+ <item name="textColorPrimaryInverse">@color/system_on_surface_light</item>
+ <item name="textColorSecondaryInverse">@color/system_on_surface_variant_light</item>
+ <item name="textColorTertiaryInverse">@color/system_outline_light</item>
+ <item name="textColorOnAccent">@color/system_on_primary_dark</item>
<item name="colorForeground">@color/foreground_device_default_dark</item>
<item name="colorForegroundInverse">@color/foreground_device_default_light</item>
@@ -2720,28 +2720,28 @@
<!-- Color palette -->
<item name="colorPrimary">@color/primary_device_default_light</item>
- <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+ <item name="colorPrimaryDark">@color/primary_device_default_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
- <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
- <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
- <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
- <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item>
- <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item>
- <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item>
- <item name="colorSurface">@color/surface_light</item>
- <item name="colorSurfaceHighlight">@color/surface_highlight_light</item>
- <item name="colorSurfaceVariant">@color/surface_variant_light</item>
- <item name="colorSurfaceHeader">@color/surface_header_light</item>
+ <item name="colorAccentPrimary">@color/system_primary_dark</item>
+ <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+ <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+ <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
+ <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item>
+ <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item>
+ <item name="colorSurface">@color/system_surface_container_light</item>
+ <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item>
+ <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item>
+ <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item>
<item name="colorError">@color/error_color_device_default_light</item>
- <item name="colorBackground">@color/background_device_default_light</item>
+ <item name="colorBackground">@color/system_surface_container_light</item>
<item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
- <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
- <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
- <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
- <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
- <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
- <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
- <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+ <item name="textColorPrimary">@color/system_on_surface_light</item>
+ <item name="textColorSecondary">@color/system_on_surface_variant_light</item>
+ <item name="textColorTertiary">@color/system_outline_light</item>
+ <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item>
+ <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item>
+ <item name="textColorTertiaryInverse">@color/system_outline_dark</item>
+ <item name="textColorOnAccent">@color/system_on_primary_dark</item>
<item name="colorForeground">@color/foreground_device_default_light</item>
<item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
<item name="colorPopupBackground">?attr/colorBackgroundFloating</item>
@@ -2821,28 +2821,28 @@
<style name="Theme.DeviceDefault.Light.DarkActionBar" parent="Theme.Material.Light.DarkActionBar">
<!-- Color palette -->
<item name="colorPrimary">@color/primary_device_default_dark</item>
- <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+ <item name="colorPrimaryDark">@color/primary_device_default_dark</item>
<item name="colorAccent">@color/accent_device_default_light</item>
- <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
- <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
- <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
- <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item>
- <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item>
- <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item>
- <item name="colorSurface">@color/surface_light</item>
- <item name="colorSurfaceHighlight">@color/surface_highlight_light</item>
- <item name="colorSurfaceVariant">@color/surface_variant_light</item>
- <item name="colorSurfaceHeader">@color/surface_header_light</item>
+ <item name="colorAccentPrimary">@color/system_primary_dark</item>
+ <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+ <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+ <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
+ <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item>
+ <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item>
+ <item name="colorSurface">@color/system_surface_container_light</item>
+ <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item>
+ <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item>
+ <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item>
<item name="colorError">@color/error_color_device_default_light</item>
- <item name="colorBackground">@color/background_device_default_light</item>
+ <item name="colorBackground">@color/system_surface_container_light</item>
<item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
- <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
- <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
- <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
- <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
- <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
- <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
- <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+ <item name="textColorPrimary">@color/system_on_surface_light</item>
+ <item name="textColorSecondary">@color/system_on_surface_variant_light</item>
+ <item name="textColorTertiary">@color/system_outline_light</item>
+ <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item>
+ <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item>
+ <item name="textColorTertiaryInverse">@color/system_outline_dark</item>
+ <item name="textColorOnAccent">@color/system_on_primary_dark</item>
<item name="colorForeground">@color/foreground_device_default_light</item>
<item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
@@ -2937,28 +2937,28 @@
<style name="Theme.DeviceDefault.Light.NoActionBar" parent="Theme.Material.Light.NoActionBar">
<!-- Color palette -->
<item name="colorPrimary">@color/primary_device_default_light</item>
- <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+ <item name="colorPrimaryDark">@color/primary_device_default_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
- <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
- <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
- <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
- <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item>
- <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item>
- <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item>
- <item name="colorSurface">@color/surface_light</item>
- <item name="colorSurfaceHighlight">@color/surface_highlight_light</item>
- <item name="colorSurfaceVariant">@color/surface_variant_light</item>
- <item name="colorSurfaceHeader">@color/surface_header_light</item>
+ <item name="colorAccentPrimary">@color/system_primary_dark</item>
+ <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+ <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+ <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
+ <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item>
+ <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item>
+ <item name="colorSurface">@color/system_surface_container_light</item>
+ <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item>
+ <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item>
+ <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item>
<item name="colorError">@color/error_color_device_default_light</item>
- <item name="colorBackground">@color/background_device_default_light</item>
+ <item name="colorBackground">@color/system_surface_container_light</item>
<item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
- <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
- <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
- <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
- <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
- <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
- <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
- <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+ <item name="textColorPrimary">@color/system_on_surface_light</item>
+ <item name="textColorSecondary">@color/system_on_surface_variant_light</item>
+ <item name="textColorTertiary">@color/system_outline_light</item>
+ <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item>
+ <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item>
+ <item name="textColorTertiaryInverse">@color/system_outline_dark</item>
+ <item name="textColorOnAccent">@color/system_on_primary_dark</item>
<item name="colorForeground">@color/foreground_device_default_light</item>
<item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
@@ -3054,28 +3054,28 @@
<style name="Theme.DeviceDefault.Light.NoActionBar.Fullscreen" parent="Theme.Material.Light.NoActionBar.Fullscreen">
<!-- Color palette -->
<item name="colorPrimary">@color/primary_device_default_light</item>
- <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+ <item name="colorPrimaryDark">@color/primary_device_default_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
- <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
- <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
- <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
- <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item>
- <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item>
- <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item>
- <item name="colorSurface">@color/surface_light</item>
- <item name="colorSurfaceHighlight">@color/surface_highlight_light</item>
- <item name="colorSurfaceVariant">@color/surface_variant_light</item>
- <item name="colorSurfaceHeader">@color/surface_header_light</item>
+ <item name="colorAccentPrimary">@color/system_primary_dark</item>
+ <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+ <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+ <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
+ <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item>
+ <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item>
+ <item name="colorSurface">@color/system_surface_container_light</item>
+ <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item>
+ <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item>
+ <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item>
<item name="colorError">@color/error_color_device_default_light</item>
- <item name="colorBackground">@color/background_device_default_light</item>
+ <item name="colorBackground">@color/system_surface_container_light</item>
<item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
- <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
- <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
- <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
- <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
- <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
- <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
- <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+ <item name="textColorPrimary">@color/system_on_surface_light</item>
+ <item name="textColorSecondary">@color/system_on_surface_variant_light</item>
+ <item name="textColorTertiary">@color/system_outline_light</item>
+ <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item>
+ <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item>
+ <item name="textColorTertiaryInverse">@color/system_outline_dark</item>
+ <item name="textColorOnAccent">@color/system_on_primary_dark</item>
<item name="colorForeground">@color/foreground_device_default_light</item>
<item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
@@ -3173,28 +3173,28 @@
<style name="Theme.DeviceDefault.Light.NoActionBar.Overscan" parent="Theme.Material.Light.NoActionBar.Overscan">
<!-- Color palette -->
<item name="colorPrimary">@color/primary_device_default_light</item>
- <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+ <item name="colorPrimaryDark">@color/primary_device_default_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
- <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
- <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
- <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
- <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item>
- <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item>
- <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item>
- <item name="colorSurface">@color/surface_light</item>
- <item name="colorSurfaceHighlight">@color/surface_highlight_light</item>
- <item name="colorSurfaceVariant">@color/surface_variant_light</item>
- <item name="colorSurfaceHeader">@color/surface_header_light</item>
+ <item name="colorAccentPrimary">@color/system_primary_dark</item>
+ <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+ <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+ <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
+ <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item>
+ <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item>
+ <item name="colorSurface">@color/system_surface_container_light</item>
+ <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item>
+ <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item>
+ <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item>
<item name="colorError">@color/error_color_device_default_light</item>
- <item name="colorBackground">@color/background_device_default_light</item>
+ <item name="colorBackground">@color/system_surface_container_light</item>
<item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
- <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
- <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
- <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
- <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
- <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
- <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
- <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+ <item name="textColorPrimary">@color/system_on_surface_light</item>
+ <item name="textColorSecondary">@color/system_on_surface_variant_light</item>
+ <item name="textColorTertiary">@color/system_outline_light</item>
+ <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item>
+ <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item>
+ <item name="textColorTertiaryInverse">@color/system_outline_dark</item>
+ <item name="textColorOnAccent">@color/system_on_primary_dark</item>
<item name="colorForeground">@color/foreground_device_default_light</item>
<item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
@@ -3291,28 +3291,28 @@
<style name="Theme.DeviceDefault.Light.NoActionBar.TranslucentDecor" parent="Theme.Material.Light.NoActionBar.TranslucentDecor">
<!-- Color palette -->
<item name="colorPrimary">@color/primary_device_default_light</item>
- <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+ <item name="colorPrimaryDark">@color/primary_device_default_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
- <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
- <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
- <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
- <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item>
- <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item>
- <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item>
- <item name="colorSurface">@color/surface_light</item>
- <item name="colorSurfaceHighlight">@color/surface_highlight_light</item>
- <item name="colorSurfaceVariant">@color/surface_variant_light</item>
- <item name="colorSurfaceHeader">@color/surface_header_light</item>
+ <item name="colorAccentPrimary">@color/system_primary_dark</item>
+ <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+ <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+ <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
+ <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item>
+ <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item>
+ <item name="colorSurface">@color/system_surface_container_light</item>
+ <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item>
+ <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item>
+ <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item>
<item name="colorError">@color/error_color_device_default_light</item>
- <item name="colorBackground">@color/background_device_default_light</item>
+ <item name="colorBackground">@color/system_surface_container_light</item>
<item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
- <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
- <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
- <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
- <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
- <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
- <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
- <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+ <item name="textColorPrimary">@color/system_on_surface_light</item>
+ <item name="textColorSecondary">@color/system_on_surface_variant_light</item>
+ <item name="textColorTertiary">@color/system_outline_light</item>
+ <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item>
+ <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item>
+ <item name="textColorTertiaryInverse">@color/system_outline_dark</item>
+ <item name="textColorOnAccent">@color/system_on_primary_dark</item>
<item name="colorForeground">@color/foreground_device_default_light</item>
<item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
@@ -3426,28 +3426,28 @@
<!-- Color palette -->
<item name="colorPrimary">@color/primary_device_default_light</item>
- <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+ <item name="colorPrimaryDark">@color/primary_device_default_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
- <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
- <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
- <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
- <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item>
- <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item>
- <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item>
- <item name="colorSurface">@color/surface_light</item>
- <item name="colorSurfaceHighlight">@color/surface_highlight_light</item>
- <item name="colorSurfaceVariant">@color/surface_variant_light</item>
- <item name="colorSurfaceHeader">@color/surface_header_light</item>
+ <item name="colorAccentPrimary">@color/system_primary_dark</item>
+ <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+ <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+ <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
+ <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item>
+ <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item>
+ <item name="colorSurface">@color/system_surface_container_light</item>
+ <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item>
+ <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item>
+ <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item>
<item name="colorError">@color/error_color_device_default_light</item>
- <item name="colorBackground">@color/background_device_default_light</item>
+ <item name="colorBackground">@color/system_surface_container_light</item>
<item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
- <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
- <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
- <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
- <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
- <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
- <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
- <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+ <item name="textColorPrimary">@color/system_on_surface_light</item>
+ <item name="textColorSecondary">@color/system_on_surface_variant_light</item>
+ <item name="textColorTertiary">@color/system_outline_light</item>
+ <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item>
+ <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item>
+ <item name="textColorTertiaryInverse">@color/system_outline_dark</item>
+ <item name="textColorOnAccent">@color/system_on_primary_dark</item>
<item name="colorForeground">@color/foreground_device_default_light</item>
<item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
@@ -3535,28 +3535,28 @@
<!-- Color palette -->
<item name="colorPrimary">@color/primary_device_default_light</item>
- <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+ <item name="colorPrimaryDark">@color/primary_device_default_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
- <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
- <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
- <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
- <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item>
- <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item>
- <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item>
- <item name="colorSurface">@color/surface_light</item>
- <item name="colorSurfaceHighlight">@color/surface_highlight_light</item>
- <item name="colorSurfaceVariant">@color/surface_variant_light</item>
- <item name="colorSurfaceHeader">@color/surface_header_light</item>
+ <item name="colorAccentPrimary">@color/system_primary_dark</item>
+ <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+ <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+ <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
+ <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item>
+ <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item>
+ <item name="colorSurface">@color/system_surface_container_light</item>
+ <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item>
+ <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item>
+ <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item>
<item name="colorError">@color/error_color_device_default_light</item>
- <item name="colorBackground">@color/background_device_default_light</item>
+ <item name="colorBackground">@color/system_surface_container_light</item>
<item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
- <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
- <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
- <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
- <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
- <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
- <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
- <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+ <item name="textColorPrimary">@color/system_on_surface_light</item>
+ <item name="textColorSecondary">@color/system_on_surface_variant_light</item>
+ <item name="textColorTertiary">@color/system_outline_light</item>
+ <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item>
+ <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item>
+ <item name="textColorTertiaryInverse">@color/system_outline_dark</item>
+ <item name="textColorOnAccent">@color/system_on_primary_dark</item>
<item name="colorForeground">@color/foreground_device_default_light</item>
<item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
@@ -3654,28 +3654,28 @@
<!-- Color palette -->
<item name="colorPrimary">@color/primary_device_default_light</item>
- <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+ <item name="colorPrimaryDark">@color/primary_device_default_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
- <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
- <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
- <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
- <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item>
- <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item>
- <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item>
- <item name="colorSurface">@color/surface_light</item>
- <item name="colorSurfaceHighlight">@color/surface_highlight_light</item>
- <item name="colorSurfaceVariant">@color/surface_variant_light</item>
- <item name="colorSurfaceHeader">@color/surface_header_light</item>
+ <item name="colorAccentPrimary">@color/system_primary_dark</item>
+ <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+ <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+ <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
+ <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item>
+ <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item>
+ <item name="colorSurface">@color/system_surface_container_light</item>
+ <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item>
+ <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item>
+ <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item>
<item name="colorError">@color/error_color_device_default_light</item>
- <item name="colorBackground">@color/background_device_default_light</item>
+ <item name="colorBackground">@color/system_surface_container_light</item>
<item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
- <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
- <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
- <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
- <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
- <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
- <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
- <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+ <item name="textColorPrimary">@color/system_on_surface_light</item>
+ <item name="textColorSecondary">@color/system_on_surface_variant_light</item>
+ <item name="textColorTertiary">@color/system_outline_light</item>
+ <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item>
+ <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item>
+ <item name="textColorTertiaryInverse">@color/system_outline_dark</item>
+ <item name="textColorOnAccent">@color/system_on_primary_dark</item>
<item name="colorForeground">@color/foreground_device_default_light</item>
<item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
@@ -3774,28 +3774,28 @@
<!-- Color palette -->
<item name="colorPrimary">@color/primary_device_default_light</item>
- <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+ <item name="colorPrimaryDark">@color/primary_device_default_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
- <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
- <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
- <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
- <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item>
- <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item>
- <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item>
- <item name="colorSurface">@color/surface_light</item>
- <item name="colorSurfaceHighlight">@color/surface_highlight_light</item>
- <item name="colorSurfaceVariant">@color/surface_variant_light</item>
- <item name="colorSurfaceHeader">@color/surface_header_light</item>
+ <item name="colorAccentPrimary">@color/system_primary_dark</item>
+ <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+ <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+ <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
+ <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item>
+ <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item>
+ <item name="colorSurface">@color/system_surface_container_light</item>
+ <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item>
+ <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item>
+ <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item>
<item name="colorError">@color/error_color_device_default_light</item>
- <item name="colorBackground">@color/background_device_default_light</item>
+ <item name="colorBackground">@color/system_surface_container_light</item>
<item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
- <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
- <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
- <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
- <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
- <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
- <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
- <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+ <item name="textColorPrimary">@color/system_on_surface_light</item>
+ <item name="textColorSecondary">@color/system_on_surface_variant_light</item>
+ <item name="textColorTertiary">@color/system_outline_light</item>
+ <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item>
+ <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item>
+ <item name="textColorTertiaryInverse">@color/system_outline_dark</item>
+ <item name="textColorOnAccent">@color/system_on_primary_dark</item>
<item name="colorForeground">@color/foreground_device_default_light</item>
<item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
@@ -3895,26 +3895,26 @@
<!-- Color palette -->
<item name="colorPrimary">@color/primary_device_default_light</item>
- <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+ <item name="colorPrimaryDark">@color/primary_device_default_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
- <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
- <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
- <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
- <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item>
- <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item>
- <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item>
- <item name="colorSurface">@color/surface_light</item>
- <item name="colorSurfaceHighlight">@color/surface_highlight_light</item>
- <item name="colorSurfaceVariant">@color/surface_variant_light</item>
- <item name="colorSurfaceHeader">@color/surface_header_light</item>
+ <item name="colorAccentPrimary">@color/system_primary_dark</item>
+ <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+ <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+ <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
+ <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item>
+ <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item>
+ <item name="colorSurface">@color/system_surface_container_light</item>
+ <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item>
+ <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item>
+ <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item>
<item name="colorError">@color/error_color_device_default_light</item>
- <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
- <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
- <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
- <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
- <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
- <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
- <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+ <item name="textColorPrimary">@color/system_on_surface_light</item>
+ <item name="textColorSecondary">@color/system_on_surface_variant_light</item>
+ <item name="textColorTertiary">@color/system_outline_light</item>
+ <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item>
+ <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item>
+ <item name="textColorTertiaryInverse">@color/system_outline_dark</item>
+ <item name="textColorOnAccent">@color/system_on_primary_dark</item>
<item name="colorForeground">@color/foreground_device_default_light</item>
<item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
@@ -3996,26 +3996,26 @@
<!-- Color palette -->
<item name="colorPrimary">@color/primary_device_default_light</item>
- <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+ <item name="colorPrimaryDark">@color/primary_device_default_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
- <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
- <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
- <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
- <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item>
- <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item>
- <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item>
- <item name="colorSurface">@color/surface_light</item>
- <item name="colorSurfaceHighlight">@color/surface_highlight_light</item>
- <item name="colorSurfaceVariant">@color/surface_variant_light</item>
- <item name="colorSurfaceHeader">@color/surface_header_light</item>
+ <item name="colorAccentPrimary">@color/system_primary_dark</item>
+ <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+ <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+ <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
+ <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item>
+ <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item>
+ <item name="colorSurface">@color/system_surface_container_light</item>
+ <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item>
+ <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item>
+ <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item>
<item name="colorError">@color/error_color_device_default_light</item>
- <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
- <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
- <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
- <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
- <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
- <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
- <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+ <item name="textColorPrimary">@color/system_on_surface_light</item>
+ <item name="textColorSecondary">@color/system_on_surface_variant_light</item>
+ <item name="textColorTertiary">@color/system_outline_light</item>
+ <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item>
+ <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item>
+ <item name="textColorTertiaryInverse">@color/system_outline_dark</item>
+ <item name="textColorOnAccent">@color/system_on_primary_dark</item>
<item name="colorForeground">@color/foreground_device_default_light</item>
<item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
@@ -4096,28 +4096,28 @@
<!-- Color palette -->
<item name="colorPrimary">@color/primary_device_default_light</item>
- <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+ <item name="colorPrimaryDark">@color/primary_device_default_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
- <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
- <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
- <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
- <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item>
- <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item>
- <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item>
- <item name="colorSurface">@color/surface_light</item>
- <item name="colorSurfaceHighlight">@color/surface_highlight_light</item>
- <item name="colorSurfaceVariant">@color/surface_variant_light</item>
- <item name="colorSurfaceHeader">@color/surface_header_light</item>
+ <item name="colorAccentPrimary">@color/system_primary_dark</item>
+ <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+ <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+ <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
+ <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item>
+ <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item>
+ <item name="colorSurface">@color/system_surface_container_light</item>
+ <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item>
+ <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item>
+ <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item>
<item name="colorError">@color/error_color_device_default_light</item>
- <item name="colorBackground">@color/background_device_default_light</item>
+ <item name="colorBackground">@color/system_surface_container_light</item>
<item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
- <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
- <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
- <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
- <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
- <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
- <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
- <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+ <item name="textColorPrimary">@color/system_on_surface_light</item>
+ <item name="textColorSecondary">@color/system_on_surface_variant_light</item>
+ <item name="textColorTertiary">@color/system_outline_light</item>
+ <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item>
+ <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item>
+ <item name="textColorTertiaryInverse">@color/system_outline_dark</item>
+ <item name="textColorOnAccent">@color/system_on_primary_dark</item>
<item name="colorForeground">@color/foreground_device_default_light</item>
<item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
@@ -4217,28 +4217,28 @@
<!-- Color palette -->
<item name="colorPrimary">@color/primary_device_default_light</item>
- <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+ <item name="colorPrimaryDark">@color/primary_device_default_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
- <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
- <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
- <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
- <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item>
- <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item>
- <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item>
- <item name="colorSurface">@color/surface_light</item>
- <item name="colorSurfaceHighlight">@color/surface_highlight_light</item>
- <item name="colorSurfaceVariant">@color/surface_variant_light</item>
- <item name="colorSurfaceHeader">@color/surface_header_light</item>
+ <item name="colorAccentPrimary">@color/system_primary_dark</item>
+ <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+ <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+ <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
+ <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item>
+ <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item>
+ <item name="colorSurface">@color/system_surface_container_light</item>
+ <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item>
+ <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item>
+ <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item>
<item name="colorError">@color/error_color_device_default_light</item>
- <item name="colorBackground">@color/background_device_default_light</item>
+ <item name="colorBackground">@color/system_surface_container_light</item>
<item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
- <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
- <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
- <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
- <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
- <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
- <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
- <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+ <item name="textColorPrimary">@color/system_on_surface_light</item>
+ <item name="textColorSecondary">@color/system_on_surface_variant_light</item>
+ <item name="textColorTertiary">@color/system_outline_light</item>
+ <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item>
+ <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item>
+ <item name="textColorTertiaryInverse">@color/system_outline_dark</item>
+ <item name="textColorOnAccent">@color/system_on_primary_dark</item>
<item name="colorForeground">@color/foreground_device_default_light</item>
<item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
@@ -4336,28 +4336,28 @@
<!-- Color palette -->
<item name="colorPrimary">@color/primary_device_default_light</item>
- <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+ <item name="colorPrimaryDark">@color/primary_device_default_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
- <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
- <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
- <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
- <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item>
- <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item>
- <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item>
- <item name="colorSurface">@color/surface_light</item>
- <item name="colorSurfaceHighlight">@color/surface_highlight_light</item>
- <item name="colorSurfaceVariant">@color/surface_variant_light</item>
- <item name="colorSurfaceHeader">@color/surface_header_light</item>
+ <item name="colorAccentPrimary">@color/system_primary_dark</item>
+ <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+ <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+ <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
+ <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item>
+ <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item>
+ <item name="colorSurface">@color/system_surface_container_light</item>
+ <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item>
+ <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item>
+ <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item>
<item name="colorError">@color/error_color_device_default_light</item>
- <item name="colorBackground">@color/background_device_default_light</item>
+ <item name="colorBackground">@color/system_surface_container_light</item>
<item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
- <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
- <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
- <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
- <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
- <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
- <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
- <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+ <item name="textColorPrimary">@color/system_on_surface_light</item>
+ <item name="textColorSecondary">@color/system_on_surface_variant_light</item>
+ <item name="textColorTertiary">@color/system_outline_light</item>
+ <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item>
+ <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item>
+ <item name="textColorTertiaryInverse">@color/system_outline_dark</item>
+ <item name="textColorOnAccent">@color/system_on_primary_dark</item>
<item name="colorForeground">@color/foreground_device_default_light</item>
<item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
@@ -4454,28 +4454,28 @@
<style name="Theme.DeviceDefault.Light.Panel" parent="Theme.Material.Light.Panel">
<!-- Color palette -->
<item name="colorPrimary">@color/primary_device_default_light</item>
- <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+ <item name="colorPrimaryDark">@color/primary_device_default_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
- <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
- <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
- <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
- <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item>
- <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item>
- <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item>
- <item name="colorSurface">@color/surface_light</item>
- <item name="colorSurfaceHighlight">@color/surface_highlight_light</item>
- <item name="colorSurfaceVariant">@color/surface_variant_light</item>
- <item name="colorSurfaceHeader">@color/surface_header_light</item>
+ <item name="colorAccentPrimary">@color/system_primary_dark</item>
+ <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+ <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+ <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
+ <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item>
+ <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item>
+ <item name="colorSurface">@color/system_surface_container_light</item>
+ <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item>
+ <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item>
+ <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item>
<item name="colorError">@color/error_color_device_default_light</item>
- <item name="colorBackground">@color/background_device_default_light</item>
+ <item name="colorBackground">@color/system_surface_container_light</item>
<item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
- <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
- <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
- <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
- <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
- <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
- <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
- <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+ <item name="textColorPrimary">@color/system_on_surface_light</item>
+ <item name="textColorSecondary">@color/system_on_surface_variant_light</item>
+ <item name="textColorTertiary">@color/system_outline_light</item>
+ <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item>
+ <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item>
+ <item name="textColorTertiaryInverse">@color/system_outline_dark</item>
+ <item name="textColorOnAccent">@color/system_on_primary_dark</item>
<item name="colorForeground">@color/foreground_device_default_light</item>
<item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
@@ -4571,28 +4571,28 @@
<!-- Color palette -->
<item name="colorPrimary">@color/primary_device_default_light</item>
- <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+ <item name="colorPrimaryDark">@color/primary_device_default_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
- <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
- <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
- <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
- <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item>
- <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item>
- <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item>
- <item name="colorSurface">@color/surface_light</item>
- <item name="colorSurfaceHighlight">@color/surface_highlight_light</item>
- <item name="colorSurfaceVariant">@color/surface_variant_light</item>
- <item name="colorSurfaceHeader">@color/surface_header_light</item>
+ <item name="colorAccentPrimary">@color/system_primary_dark</item>
+ <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+ <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+ <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
+ <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item>
+ <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item>
+ <item name="colorSurface">@color/system_surface_container_light</item>
+ <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item>
+ <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item>
+ <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item>
<item name="colorError">@color/error_color_device_default_light</item>
- <item name="colorBackground">@color/background_device_default_light</item>
+ <item name="colorBackground">@color/system_surface_container_light</item>
<item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
- <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
- <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
- <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
- <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
- <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
- <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
- <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+ <item name="textColorPrimary">@color/system_on_surface_light</item>
+ <item name="textColorSecondary">@color/system_on_surface_variant_light</item>
+ <item name="textColorTertiary">@color/system_outline_light</item>
+ <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item>
+ <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item>
+ <item name="textColorTertiaryInverse">@color/system_outline_dark</item>
+ <item name="textColorOnAccent">@color/system_on_primary_dark</item>
<item name="colorForeground">@color/foreground_device_default_light</item>
<item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
@@ -4688,28 +4688,28 @@
<style name="Theme.DeviceDefault.Light.SearchBar" parent="Theme.Material.Light.SearchBar">
<!-- Color palette -->
<item name="colorPrimary">@color/primary_device_default_light</item>
- <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+ <item name="colorPrimaryDark">@color/primary_device_default_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
- <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
- <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
- <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
- <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item>
- <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item>
- <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item>
- <item name="colorSurface">@color/surface_light</item>
- <item name="colorSurfaceHighlight">@color/surface_highlight_light</item>
- <item name="colorSurfaceVariant">@color/surface_variant_light</item>
- <item name="colorSurfaceHeader">@color/surface_header_light</item>
+ <item name="colorAccentPrimary">@color/system_primary_dark</item>
+ <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+ <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+ <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
+ <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item>
+ <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item>
+ <item name="colorSurface">@color/system_surface_container_light</item>
+ <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item>
+ <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item>
+ <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item>
<item name="colorError">@color/error_color_device_default_light</item>
- <item name="colorBackground">@color/background_device_default_light</item>
+ <item name="colorBackground">@color/system_surface_container_light</item>
<item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
- <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
- <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
- <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
- <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
- <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
- <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
- <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+ <item name="textColorPrimary">@color/system_on_surface_light</item>
+ <item name="textColorSecondary">@color/system_on_surface_variant_light</item>
+ <item name="textColorTertiary">@color/system_outline_light</item>
+ <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item>
+ <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item>
+ <item name="textColorTertiaryInverse">@color/system_outline_dark</item>
+ <item name="textColorOnAccent">@color/system_on_primary_dark</item>
<item name="colorForeground">@color/foreground_device_default_light</item>
<item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
@@ -4803,28 +4803,28 @@
<style name="Theme.DeviceDefault.Light.Voice" parent="Theme.Material.Light.Voice">
<!-- Color palette -->
<item name="colorPrimary">@color/primary_device_default_light</item>
- <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+ <item name="colorPrimaryDark">@color/primary_device_default_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
- <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
- <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
- <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
- <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item>
- <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item>
- <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item>
- <item name="colorSurface">@color/surface_light</item>
- <item name="colorSurfaceHighlight">@color/surface_highlight_light</item>
- <item name="colorSurfaceVariant">@color/surface_variant_light</item>
- <item name="colorSurfaceHeader">@color/surface_header_light</item>
+ <item name="colorAccentPrimary">@color/system_primary_dark</item>
+ <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+ <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+ <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
+ <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item>
+ <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item>
+ <item name="colorSurface">@color/system_surface_container_light</item>
+ <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item>
+ <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item>
+ <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item>
<item name="colorError">@color/error_color_device_default_light</item>
- <item name="colorBackground">@color/background_device_default_light</item>
+ <item name="colorBackground">@color/system_surface_container_light</item>
<item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
- <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
- <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
- <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
- <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
- <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
- <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
- <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+ <item name="textColorPrimary">@color/system_on_surface_light</item>
+ <item name="textColorSecondary">@color/system_on_surface_variant_light</item>
+ <item name="textColorTertiary">@color/system_outline_light</item>
+ <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item>
+ <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item>
+ <item name="textColorTertiaryInverse">@color/system_outline_dark</item>
+ <item name="textColorOnAccent">@color/system_on_primary_dark</item>
<item name="colorForeground">@color/foreground_device_default_light</item>
<item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
@@ -4932,21 +4932,21 @@
<item name="popupTheme">@style/ThemeOverlay.DeviceDefault.Popup.Light</item>
<!-- Color palette -->
- <item name="colorBackground">@color/background_device_default_light</item>
+ <item name="colorBackground">@color/system_surface_container_light</item>
<item name="colorPrimary">@color/primary_device_default_settings_light</item>
<item name="colorPrimaryDark">@color/primary_dark_device_default_settings_light</item>
<item name="colorSecondary">@color/secondary_device_default_settings_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
- <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
- <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
- <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
- <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item>
- <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item>
- <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item>
- <item name="colorSurface">@color/surface_light</item>
- <item name="colorSurfaceHighlight">@color/surface_highlight_light</item>
- <item name="colorSurfaceVariant">@color/surface_variant_light</item>
- <item name="colorSurfaceHeader">@color/surface_header_light</item>
+ <item name="colorAccentPrimary">@color/system_primary_dark</item>
+ <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+ <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+ <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
+ <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item>
+ <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item>
+ <item name="colorSurface">@color/system_surface_container_light</item>
+ <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item>
+ <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item>
+ <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item>
<item name="colorError">@color/error_color_device_default_light</item>
<item name="colorEdgeEffect">@color/edge_effect_device_default_light</item>
@@ -5044,16 +5044,16 @@
<item name="colorPrimaryDark">@color/primary_dark_device_default_settings_light</item>
<item name="colorSecondary">@color/secondary_device_default_settings_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
- <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
- <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
- <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
- <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item>
- <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item>
- <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item>
- <item name="colorSurface">@color/surface_light</item>
- <item name="colorSurfaceHighlight">@color/surface_highlight_light</item>
- <item name="colorSurfaceVariant">@color/surface_variant_light</item>
- <item name="colorSurfaceHeader">@color/surface_header_light</item>
+ <item name="colorAccentPrimary">@color/system_primary_dark</item>
+ <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+ <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+ <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
+ <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item>
+ <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item>
+ <item name="colorSurface">@color/system_surface_container_light</item>
+ <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item>
+ <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item>
+ <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item>
<item name="colorError">@color/error_color_device_default_light</item>
<item name="colorControlNormal">?attr/textColorPrimary</item>
<item name="alertDialogTheme">@style/Theme.DeviceDefault.Light.Dialog.Alert</item>
@@ -5148,16 +5148,16 @@
<item name="colorPrimaryDark">@color/primary_dark_device_default_settings_light</item>
<item name="colorSecondary">@color/secondary_device_default_settings_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
- <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
- <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
- <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
- <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item>
- <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item>
- <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item>
- <item name="colorSurface">@color/surface_light</item>
- <item name="colorSurfaceHighlight">@color/surface_highlight_light</item>
- <item name="colorSurfaceVariant">@color/surface_variant_light</item>
- <item name="colorSurfaceHeader">@color/surface_header_light</item>
+ <item name="colorAccentPrimary">@color/system_primary_dark</item>
+ <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+ <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+ <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
+ <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item>
+ <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item>
+ <item name="colorSurface">@color/system_surface_container_light</item>
+ <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item>
+ <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item>
+ <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item>
<item name="colorError">@color/error_color_device_default_light</item>
<item name="alertDialogTheme">@style/Theme.DeviceDefault.Light.Dialog.Alert</item>
@@ -5245,26 +5245,26 @@
<item name="colorPrimaryDark">@color/primary_dark_device_default_settings</item>
<item name="colorSecondary">@color/secondary_device_default_settings</item>
<item name="colorAccent">@color/accent_device_default_dark</item>
- <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
- <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
- <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
- <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_dark_device_default</item>
- <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_dark_device_default</item>
- <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_dark_device_default</item>
- <item name="colorSurface">@color/surface_dark</item>
- <item name="colorSurfaceHighlight">@color/surface_highlight_dark</item>
- <item name="colorSurfaceVariant">@color/surface_variant_dark</item>
- <item name="colorSurfaceHeader">@color/surface_header_dark</item>
+ <item name="colorAccentPrimary">@color/system_primary_dark</item>
+ <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+ <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+ <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item>
+ <item name="colorAccentSecondaryVariant">@color/system_secondary_container_dark</item>
+ <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_dark</item>
+ <item name="colorSurface">@color/system_surface_container_dark</item>
+ <item name="colorSurfaceHighlight">@color/system_surface_bright_dark</item>
+ <item name="colorSurfaceVariant">@color/system_surface_container_high_dark</item>
+ <item name="colorSurfaceHeader">@color/system_surface_container_highest_dark</item>
<item name="colorError">@color/error_color_device_default_dark</item>
- <item name="colorBackground">@color/background_device_default_dark</item>
+ <item name="colorBackground">@color/system_surface_container_dark</item>
<item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
- <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
- <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
- <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
- <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item>
- <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item>
- <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item>
- <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+ <item name="textColorPrimary">@color/system_on_surface_dark</item>
+ <item name="textColorSecondary">@color/system_on_surface_variant_dark</item>
+ <item name="textColorTertiary">@color/system_outline_dark</item>
+ <item name="textColorPrimaryInverse">@color/system_on_surface_light</item>
+ <item name="textColorSecondaryInverse">@color/system_on_surface_variant_light</item>
+ <item name="textColorTertiaryInverse">@color/system_outline_light</item>
+ <item name="textColorOnAccent">@color/system_on_primary_dark</item>
<item name="colorForeground">@color/foreground_device_default_dark</item>
<item name="colorForegroundInverse">@color/foreground_device_default_light</item>
@@ -5361,26 +5361,26 @@
<item name="colorPrimaryDark">@color/primary_dark_device_default_settings</item>
<item name="colorSecondary">@color/secondary_device_default_settings</item>
<item name="colorAccent">@color/accent_device_default_light</item>
- <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
- <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
- <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
- <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item>
- <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item>
- <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item>
- <item name="colorSurface">@color/surface_light</item>
- <item name="colorSurfaceHighlight">@color/surface_highlight_light</item>
- <item name="colorSurfaceVariant">@color/surface_variant_light</item>
- <item name="colorSurfaceHeader">@color/surface_header_light</item>
+ <item name="colorAccentPrimary">@color/system_primary_dark</item>
+ <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+ <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+ <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
+ <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item>
+ <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item>
+ <item name="colorSurface">@color/system_surface_container_light</item>
+ <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item>
+ <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item>
+ <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item>
<item name="colorError">@color/error_color_device_default_light</item>
- <item name="colorBackground">@color/background_device_default_light</item>
+ <item name="colorBackground">@color/system_surface_container_light</item>
<item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
- <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
- <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
- <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
- <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
- <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
- <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
- <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+ <item name="textColorPrimary">@color/system_on_surface_light</item>
+ <item name="textColorSecondary">@color/system_on_surface_variant_light</item>
+ <item name="textColorTertiary">@color/system_outline_light</item>
+ <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item>
+ <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item>
+ <item name="textColorTertiaryInverse">@color/system_outline_dark</item>
+ <item name="textColorOnAccent">@color/system_on_primary_dark</item>
<item name="colorForeground">@color/foreground_device_default_light</item>
<item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
@@ -5487,26 +5487,26 @@
<item name="colorPrimaryDark">@color/primary_dark_device_default_settings</item>
<item name="colorSecondary">@color/secondary_device_default_settings</item>
<item name="colorAccent">@color/accent_device_default_light</item>
- <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
- <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
- <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
- <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item>
- <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item>
- <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item>
- <item name="colorSurface">@color/surface_light</item>
- <item name="colorSurfaceHighlight">@color/surface_highlight_light</item>
- <item name="colorSurfaceVariant">@color/surface_variant_light</item>
- <item name="colorSurfaceHeader">@color/surface_header_light</item>
+ <item name="colorAccentPrimary">@color/system_primary_dark</item>
+ <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+ <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+ <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
+ <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item>
+ <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item>
+ <item name="colorSurface">@color/system_surface_container_light</item>
+ <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item>
+ <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item>
+ <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item>
<item name="colorError">@color/error_color_device_default_light</item>
- <item name="colorBackground">@color/background_device_default_light</item>
+ <item name="colorBackground">@color/system_surface_container_light</item>
<item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
- <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
- <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
- <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
- <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
- <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
- <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
- <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+ <item name="textColorPrimary">@color/system_on_surface_light</item>
+ <item name="textColorSecondary">@color/system_on_surface_variant_light</item>
+ <item name="textColorTertiary">@color/system_outline_light</item>
+ <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item>
+ <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item>
+ <item name="textColorTertiaryInverse">@color/system_outline_dark</item>
+ <item name="textColorOnAccent">@color/system_on_primary_dark</item>
<item name="colorForeground">@color/foreground_device_default_light</item>
<item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
@@ -5606,26 +5606,26 @@
<item name="colorPrimaryDark">@color/primary_dark_device_default_settings</item>
<item name="colorSecondary">@color/secondary_device_default_settings</item>
<item name="colorAccent">@color/accent_device_default_light</item>
- <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
- <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
- <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
- <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item>
- <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item>
- <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item>
- <item name="colorSurface">@color/surface_light</item>
- <item name="colorSurfaceHighlight">@color/surface_highlight_light</item>
- <item name="colorSurfaceVariant">@color/surface_variant_light</item>
- <item name="colorSurfaceHeader">@color/surface_header_light</item>
+ <item name="colorAccentPrimary">@color/system_primary_dark</item>
+ <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+ <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+ <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
+ <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item>
+ <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item>
+ <item name="colorSurface">@color/system_surface_container_light</item>
+ <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item>
+ <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item>
+ <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item>
<item name="colorError">@color/error_color_device_default_light</item>
- <item name="colorBackground">@color/background_device_default_light</item>
+ <item name="colorBackground">@color/system_surface_container_light</item>
<item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
- <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
- <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
- <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
- <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
- <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
- <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
- <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+ <item name="textColorPrimary">@color/system_on_surface_light</item>
+ <item name="textColorSecondary">@color/system_on_surface_variant_light</item>
+ <item name="textColorTertiary">@color/system_outline_light</item>
+ <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item>
+ <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item>
+ <item name="textColorTertiaryInverse">@color/system_outline_dark</item>
+ <item name="textColorOnAccent">@color/system_on_primary_dark</item>
<item name="colorForeground">@color/foreground_device_default_light</item>
<item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
@@ -5788,9 +5788,9 @@
<style name="ThemeOverlay.DeviceDefault.Accent">
<item name="colorAccent">@color/accent_device_default_dark</item>
- <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
- <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
- <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
+ <item name="colorAccentPrimary">@color/system_primary_dark</item>
+ <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+ <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
<item name="materialColorOnSecondaryFixedVariant">@color/system_on_secondary_fixed_variant</item>
<item name="materialColorOnTertiaryFixedVariant">@color/system_on_tertiary_fixed_variant</item>
@@ -5863,9 +5863,9 @@
<style name="ThemeOverlay.DeviceDefault.Accent.Light">
<item name="colorAccent">@color/accent_device_default_light</item>
- <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
- <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
- <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
+ <item name="colorAccentPrimary">@color/system_primary_dark</item>
+ <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+ <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
<item name="materialColorOnSecondaryFixedVariant">@color/system_on_secondary_fixed_variant</item>
<item name="materialColorOnTertiaryFixedVariant">@color/system_on_tertiary_fixed_variant</item>
@@ -5938,13 +5938,13 @@
<!-- Theme overlay that replaces colorAccent with the colorAccent from {@link #Theme_DeviceDefault_DayNight}. -->
<style name="ThemeOverlay.DeviceDefault.Accent.DayNight"
- parent="@style/ThemeOverlay.DeviceDefault.Accent.Light" />
+ parent="@style/ThemeOverlay.DeviceDefault.Accent.Light" />
<style name="ThemeOverlay.DeviceDefault.Dark.ActionBar.Accent" parent="ThemeOverlay.Material.Dark.ActionBar">
<item name="colorAccent">@color/accent_device_default_dark</item>
- <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
- <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
- <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
+ <item name="colorAccentPrimary">@color/system_primary_dark</item>
+ <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+ <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
<item name="materialColorOnSecondaryFixedVariant">@color/system_on_secondary_fixed_variant</item>
<item name="materialColorOnTertiaryFixedVariant">@color/system_on_tertiary_fixed_variant</item>
@@ -6016,7 +6016,7 @@
</style>
<style name="Theme.DeviceDefault.Light.Dialog.Alert.UserSwitchingDialog" parent="Theme.DeviceDefault.NoActionBar.Fullscreen">
- <item name="colorBackground">@color/background_device_default_light</item>
+ <item name="colorBackground">@color/system_surface_container_light</item>
<item name="colorBackgroundFloating">@color/background_device_default_light</item>
<item name="layout_gravity">center</item>
<item name="windowAnimationStyle">@style/Animation.DeviceDefault.Dialog</item>
diff --git a/data/etc/com.android.systemui.xml b/data/etc/com.android.systemui.xml
index a115c65..38ea4ac 100644
--- a/data/etc/com.android.systemui.xml
+++ b/data/etc/com.android.systemui.xml
@@ -93,5 +93,6 @@
<permission name="android.permission.MODIFY_DEFAULT_AUDIO_EFFECTS" />
<permission name="android.permission.CONTROL_UI_TRACING" />
<permission name="android.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND" />
+ <permission name="android.permission.OVERRIDE_SYSTEM_KEY_BEHAVIOR_IN_FOCUSED_WINDOW"/>
</privapp-permissions>
</permissions>
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 1fe6ca7..9a55b80 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -592,6 +592,10 @@
<permission name="android.permission.INTERACT_ACROSS_USERS" />
</privapp-permissions>
+ <privapp-permissions package="com.android.providers.tv">
+ <permission name="android.permission.INTERACT_ACROSS_USERS"/>
+ </privapp-permissions>
+
<privapp-permissions package="com.android.tv">
<permission name="android.permission.CHANGE_HDMI_CEC_ACTIVE_SOURCE"/>
<permission name="android.permission.DVB_DEVICE"/>
diff --git a/data/fonts/font_fallback.xml b/data/fonts/font_fallback.xml
index 53024ab..ae50da1 100644
--- a/data/fonts/font_fallback.xml
+++ b/data/fonts/font_fallback.xml
@@ -304,7 +304,7 @@
<font postScriptName="NotoSansBengali-Regular" supportedAxes="wght">
NotoSansBengali-VF.ttf
</font>
- <font fallbackFor="serif" postScriptName="NotoSerifBengali-Regular">
+ <font fallbackFor="serif" postScriptName="NotoSerifBengali-Regular" supportedAxes="wght">
NotoSerifBengali-VF.ttf
</font>
</family>
@@ -354,7 +354,7 @@
<font postScriptName="NotoSansSinhala-Regular" supportedAxes="wght">
NotoSansSinhala-VF.ttf
</font>
- <font fallbackFor="serif" postScriptName="NotoSerifSinhala-Regular">
+ <font fallbackFor="serif" postScriptName="NotoSerifSinhala-Regular" supportedAxes="wght">
NotoSerifSinhala-VF.ttf
</font>
</family>
@@ -927,23 +927,23 @@
NotoSansMedefaidrin-VF.ttf
</font>
</family>
- <family lang="und-Soyo" supportedAxes="wght">
- <font postScriptName="NotoSansSoyombo-Regular">
+ <family lang="und-Soyo">
+ <font postScriptName="NotoSansSoyombo-Regular" supportedAxes="wght">
NotoSansSoyombo-VF.ttf
</font>
</family>
- <family lang="und-Takr" supportedAxes="wght">
- <font postScriptName="NotoSansTakri-Regular">
+ <family lang="und-Takr">
+ <font postScriptName="NotoSansTakri-Regular" supportedAxes="wght">
NotoSansTakri-VF.ttf
</font>
</family>
- <family lang="und-Hmnp" supportedAxes="wght">
- <font postScriptName="NotoSerifHmongNyiakeng-Regular">
+ <family lang="und-Hmnp">
+ <font postScriptName="NotoSerifHmongNyiakeng-Regular" supportedAxes="wght">
NotoSerifNyiakengPuachueHmong-VF.ttf
</font>
</family>
- <family lang="und-Yezi" supportedAxes="wght">
- <font postScriptName="NotoSerifYezidi-Regular">
+ <family lang="und-Yezi">
+ <font postScriptName="NotoSerifYezidi-Regular" supportedAxes="wght">
NotoSerifYezidi-VF.ttf
</font>
</family>
diff --git a/data/fonts/font_fallback_cjkvf.xml b/data/fonts/font_fallback_cjkvf.xml
index a4ee825..407d704 100644
--- a/data/fonts/font_fallback_cjkvf.xml
+++ b/data/fonts/font_fallback_cjkvf.xml
@@ -304,7 +304,7 @@
<font postScriptName="NotoSansBengali-Regular" supportedAxes="wght">
NotoSansBengali-VF.ttf
</font>
- <font fallbackFor="serif" postScriptName="NotoSerifBengali-Regular">
+ <font fallbackFor="serif" postScriptName="NotoSerifBengali-Regular" supportedAxes="wght">
NotoSerifBengali-VF.ttf
</font>
</family>
@@ -354,7 +354,7 @@
<font postScriptName="NotoSansSinhala-Regular" supportedAxes="wght">
NotoSansSinhala-VF.ttf
</font>
- <font fallbackFor="serif" postScriptName="NotoSerifSinhala-Regular">
+ <font fallbackFor="serif" postScriptName="NotoSerifSinhala-Regular" supportedAxes="wght">
NotoSerifSinhala-VF.ttf
</font>
</family>
@@ -943,23 +943,23 @@
NotoSansMedefaidrin-VF.ttf
</font>
</family>
- <family lang="und-Soyo" supportedAxes="wght">
- <font postScriptName="NotoSansSoyombo-Regular">
+ <family lang="und-Soyo">
+ <font postScriptName="NotoSansSoyombo-Regular" supportedAxes="wght">
NotoSansSoyombo-VF.ttf
</font>
</family>
- <family lang="und-Takr" supportedAxes="wght">
- <font postScriptName="NotoSansTakri-Regular">
+ <family lang="und-Takr">
+ <font postScriptName="NotoSansTakri-Regular" supportedAxes="wght">
NotoSansTakri-VF.ttf
</font>
</family>
- <family lang="und-Hmnp" supportedAxes="wght">
- <font postScriptName="NotoSerifHmongNyiakeng-Regular">
+ <family lang="und-Hmnp">
+ <font postScriptName="NotoSerifHmongNyiakeng-Regular" supportedAxes="wght">
NotoSerifNyiakengPuachueHmong-VF.ttf
</font>
</family>
- <family lang="und-Yezi" supportedAxes="wght">
- <font postScriptName="NotoSerifYezidi-Regular">
+ <family lang="und-Yezi">
+ <font postScriptName="NotoSerifYezidi-Regular" supportedAxes="wght">
NotoSerifYezidi-VF.ttf
</font>
</family>
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/BackupHelper.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/BackupHelper.java
new file mode 100644
index 0000000..69a68c8
--- /dev/null
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/BackupHelper.java
@@ -0,0 +1,101 @@
+/*
+ * 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 androidx.window.extensions.embedding;
+
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Looper;
+import android.os.MessageQueue;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+
+import java.util.List;
+
+/**
+ * Helper class to back up and restore the TaskFragmentOrganizer state, in order to resume
+ * organizing the TaskFragments if the app process is restarted.
+ */
+@SuppressWarnings("GuardedBy")
+class BackupHelper {
+ private static final String TAG = "BackupHelper";
+ private static final boolean DEBUG = Build.isDebuggable();
+
+ private static final String KEY_TASK_CONTAINERS = "KEY_TASK_CONTAINERS";
+ @NonNull
+ private final SplitController mController;
+ @NonNull
+ private final BackupIdler mBackupIdler = new BackupIdler();
+ private boolean mBackupIdlerScheduled;
+
+ BackupHelper(@NonNull SplitController splitController, @NonNull Bundle savedState) {
+ mController = splitController;
+
+ if (!savedState.isEmpty()) {
+ restoreState(savedState);
+ }
+ }
+
+ /**
+ * Schedules a back-up request. It is no-op if there was a request scheduled and not yet
+ * completed.
+ */
+ void scheduleBackup() {
+ if (!mBackupIdlerScheduled) {
+ mBackupIdlerScheduled = true;
+ Looper.myQueue().addIdleHandler(mBackupIdler);
+ }
+ }
+
+ final class BackupIdler implements MessageQueue.IdleHandler {
+ @Override
+ public boolean queueIdle() {
+ synchronized (mController.mLock) {
+ mBackupIdlerScheduled = false;
+ startBackup();
+ }
+ return false;
+ }
+ }
+
+ private void startBackup() {
+ final List<TaskContainer> taskContainers = mController.getTaskContainers();
+ if (taskContainers.isEmpty()) {
+ Log.w(TAG, "No task-container to back up");
+ return;
+ }
+
+ if (DEBUG) Log.d(TAG, "Start to back up " + taskContainers);
+ final Bundle state = new Bundle();
+ state.setClassLoader(TaskContainer.class.getClassLoader());
+ state.putParcelableList(KEY_TASK_CONTAINERS, taskContainers);
+ mController.setSavedState(state);
+ }
+
+ private void restoreState(@NonNull Bundle savedState) {
+ if (savedState.isEmpty()) {
+ return;
+ }
+
+ final List<TaskContainer> taskContainers = savedState.getParcelableArrayList(
+ KEY_TASK_CONTAINERS, TaskContainer.class);
+ for (TaskContainer taskContainer : taskContainers) {
+ if (DEBUG) Log.d(TAG, "restore task " + taskContainer.getTaskId());
+ // TODO(b/289875940): implement the TaskContainer restoration.
+ }
+ }
+}
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
index 26d180c..bb384c5 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
@@ -2536,6 +2536,21 @@
return mTaskContainers.get(taskId);
}
+ @NonNull
+ @GuardedBy("mLock")
+ List<TaskContainer> getTaskContainers() {
+ final ArrayList<TaskContainer> taskContainers = new ArrayList<>();
+ for (int i = mTaskContainers.size() - 1; i >= 0; i--) {
+ taskContainers.add(mTaskContainers.valueAt(i));
+ }
+ return taskContainers;
+ }
+
+ @GuardedBy("mLock")
+ void setSavedState(@NonNull Bundle savedState) {
+ mPresenter.setSavedState(savedState);
+ }
+
@GuardedBy("mLock")
void addTaskContainer(int taskId, TaskContainer taskContainer) {
mTaskContainers.put(taskId, taskContainer);
@@ -2829,6 +2844,12 @@
return getActiveSplitForContainer(container) != null;
}
+ void scheduleBackup() {
+ synchronized (mLock) {
+ mPresenter.scheduleBackup();
+ }
+ }
+
private final class LifecycleCallbacks extends EmptyLifecycleCallbacksAdapter {
@Override
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
index 99716e7..fb8efc4 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
@@ -158,6 +158,8 @@
private final WindowLayoutComponentImpl mWindowLayoutComponent;
private final SplitController mController;
+ @NonNull
+ private final BackupHelper mBackupHelper;
SplitPresenter(@NonNull Executor executor,
@NonNull WindowLayoutComponentImpl windowLayoutComponent,
@@ -165,7 +167,18 @@
super(executor, controller);
mWindowLayoutComponent = windowLayoutComponent;
mController = controller;
- registerOrganizer();
+ final Bundle outSavedState = new Bundle();
+ if (Flags.aeBackStackRestore()) {
+ outSavedState.setClassLoader(TaskContainer.class.getClassLoader());
+ registerOrganizer(false /* isSystemOrganizer */, outSavedState);
+ } else {
+ registerOrganizer();
+ }
+ mBackupHelper = new BackupHelper(controller, outSavedState);
+ }
+
+ void scheduleBackup() {
+ mBackupHelper.scheduleBackup();
}
/**
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
index 20ad53e..5795e8d 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
@@ -32,6 +32,8 @@
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.IBinder;
+import android.os.Parcel;
+import android.os.Parcelable;
import android.util.ArraySet;
import android.util.DisplayMetrics;
import android.util.Log;
@@ -48,12 +50,14 @@
import androidx.window.extensions.embedding.SplitAttributes.SplitType.ExpandContainersSplitType;
import androidx.window.extensions.embedding.SplitAttributes.SplitType.RatioSplitType;
+import com.android.window.flags.Flags;
+
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
/** Represents TaskFragments and split pairs below a Task. */
-class TaskContainer {
+class TaskContainer implements Parcelable {
private static final String TAG = TaskContainer.class.getSimpleName();
/** The unique task id. */
@@ -80,6 +84,9 @@
@NonNull
private TaskFragmentParentInfo mInfo;
+ @NonNull
+ private SplitController mSplitController;
+
/**
* TaskFragments that the organizer has requested to be closed. They should be removed when
* the organizer receives
@@ -116,12 +123,14 @@
/**
* The {@link TaskContainer} constructor
*
- * @param taskId The ID of the Task, which must match {@link Activity#getTaskId()} with
- * {@code activityInTask}.
- * @param activityInTask The {@link Activity} in the Task with {@code taskId}. It is used to
- * initialize the {@link TaskContainer} properties.
+ * @param taskId The ID of the Task, which must match {@link Activity#getTaskId()} with
+ * {@code activityInTask}.
+ * @param activityInTask The {@link Activity} in the Task with {@code taskId}. It is used to
+ * initialize the {@link TaskContainer} properties.
+ * @param splitController The {@link SplitController}.
*/
- TaskContainer(int taskId, @NonNull Activity activityInTask) {
+ TaskContainer(int taskId, @NonNull Activity activityInTask,
+ @Nullable SplitController splitController) {
if (taskId == INVALID_TASK_ID) {
throw new IllegalArgumentException("Invalid Task id");
}
@@ -136,6 +145,7 @@
true /* visible */,
true /* hasDirectActivity */,
null /* decorSurface */);
+ mSplitController = splitController;
}
int getTaskId() {
@@ -571,6 +581,12 @@
// Update overlay container after split pin container since the overlay should be on top of
// pin container.
updateAlwaysOnTopOverlayIfNecessary();
+
+ // TODO(b/289875940): Making backup-restore as an opt-in solution, before the flag goes
+ // to next-food.
+ if (Flags.aeBackStackRestore()) {
+ mSplitController.scheduleBackup();
+ }
}
private void updateAlwaysOnTopOverlayIfNecessary() {
@@ -664,6 +680,34 @@
return activityStacks;
}
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(mTaskId);
+ // TODO(b/289875940)
+ }
+
+ protected TaskContainer(Parcel in) {
+ mTaskId = in.readInt();
+ // TODO(b/289875940)
+ }
+
+ public static final Creator<TaskContainer> CREATOR = new Creator<>() {
+ @Override
+ public TaskContainer createFromParcel(Parcel in) {
+ return new TaskContainer(in);
+ }
+
+ @Override
+ public TaskContainer[] newArray(int size) {
+ return new TaskContainer[size];
+ }
+ };
+
/** A wrapper class which contains the information of {@link TaskContainer} */
static final class TaskProperties {
private final int mDisplayId;
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
index ee3e6f3..dc6506b 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
@@ -1203,7 +1203,7 @@
if (taskContainer == null) {
// Adding a TaskContainer if no existed one.
- taskContainer = new TaskContainer(mTaskId, mActivityInTask);
+ taskContainer = new TaskContainer(mTaskId, mActivityInTask, mSplitController);
mSplitController.addTaskContainer(mTaskId, taskContainer);
}
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/EmbeddingTestUtils.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/EmbeddingTestUtils.java
index 7dc78fd..5c85778 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/EmbeddingTestUtils.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/EmbeddingTestUtils.java
@@ -222,7 +222,7 @@
doReturn(resources).when(activity).getResources();
doReturn(DEFAULT_DISPLAY).when(activity).getDisplayId();
- return new TaskContainer(TASK_ID, activity);
+ return new TaskContainer(TASK_ID, activity, mock(SplitController.class));
}
static TaskContainer createTestTaskContainer(@NonNull SplitController controller) {
diff --git a/libs/WindowManager/Shell/res/values/dimen.xml b/libs/WindowManager/Shell/res/values/dimen.xml
index 53ab2d5..08a746f 100644
--- a/libs/WindowManager/Shell/res/values/dimen.xml
+++ b/libs/WindowManager/Shell/res/values/dimen.xml
@@ -92,8 +92,11 @@
<dimen name="docked_divider_handle_width">16dp</dimen>
<dimen name="docked_divider_handle_height">2dp</dimen>
- <dimen name="split_divider_handle_region_width">96dp</dimen>
+ <dimen name="split_divider_handle_region_width">80dp</dimen>
<dimen name="split_divider_handle_region_height">48dp</dimen>
+ <!-- The divider touch zone height is intentionally halved in portrait to avoid colliding
+ with the app handle.-->
+ <dimen name="desktop_mode_portrait_split_divider_handle_region_height">24dp</dimen>
<!-- Divider handle size for split screen -->
<dimen name="split_divider_handle_width">40dp</dimen>
diff --git a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/split/SplitScreenConstants.java b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/split/SplitScreenConstants.java
index ebca5df..498dc8b 100644
--- a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/split/SplitScreenConstants.java
+++ b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/split/SplitScreenConstants.java
@@ -30,7 +30,7 @@
/** Duration used for every split fade-in or fade-out. */
public static final int FADE_DURATION = 133;
/** Duration where we keep an app veiled to allow it to redraw itself behind the scenes. */
- public static final int VEIL_DELAY_DURATION = 400;
+ public static final int VEIL_DELAY_DURATION = 300;
/** Key for passing in widget intents when invoking split from launcher workspace. */
public static final String KEY_EXTRA_WIDGET_INTENT = "key_extra_widget_intent";
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationBackground.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationBackground.java
index d754d04..26f7b36 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationBackground.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationBackground.java
@@ -20,6 +20,7 @@
import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.graphics.Color;
import android.graphics.Rect;
import android.view.SurfaceControl;
@@ -59,6 +60,23 @@
*/
public void ensureBackground(Rect startRect, int color,
@NonNull SurfaceControl.Transaction transaction, int statusbarHeight) {
+ ensureBackground(startRect, color, transaction, statusbarHeight,
+ null /* cropBounds */, 0 /* cornerRadius */);
+ }
+
+ /**
+ * Ensures the back animation background color layer is present.
+ *
+ * @param startRect The start bounds of the closing target.
+ * @param color The background color.
+ * @param transaction The animation transaction.
+ * @param statusbarHeight The height of the statusbar (in px).
+ * @param cropBounds The crop bounds of the surface, set to non-empty to show wallpaper.
+ * @param cornerRadius The radius of corner, only work when cropBounds is not empty.
+ */
+ public void ensureBackground(Rect startRect, int color,
+ @NonNull SurfaceControl.Transaction transaction, int statusbarHeight,
+ @Nullable Rect cropBounds, float cornerRadius) {
if (mBackgroundSurface != null) {
return;
}
@@ -78,6 +96,10 @@
transaction.setColor(mBackgroundSurface, colorComponents)
.setLayer(mBackgroundSurface, BACKGROUND_LAYER)
.show(mBackgroundSurface);
+ if (cropBounds != null && !cropBounds.isEmpty()) {
+ transaction.setCrop(mBackgroundSurface, cropBounds)
+ .setCornerRadius(mBackgroundSurface, cornerRadius);
+ }
mStartBounds = startRect;
mIsRequestingStatusBarAppearance = false;
mStatusbarHeight = statusbarHeight;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
index 356ecb3..d7da051 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
@@ -1313,15 +1313,18 @@
info.getChanges().remove(j);
}
}
- tmpSize = info.getChanges().size();
- for (int i = 0; i < tmpSize; ++i) {
- final TransitionInfo.Change change = init.getChanges().get(i);
- if (moveToTop) {
- if (isSameChangeTarget(openComponent, openTaskId, change)) {
- change.setFlags(change.getFlags() | FLAG_MOVED_TO_TOP);
+ // Ignore merge if there is no close target
+ if (!info.getChanges().isEmpty()) {
+ tmpSize = init.getChanges().size();
+ for (int i = 0; i < tmpSize; ++i) {
+ final TransitionInfo.Change change = init.getChanges().get(i);
+ if (moveToTop) {
+ if (isSameChangeTarget(openComponent, openTaskId, change)) {
+ change.setFlags(change.getFlags() | FLAG_MOVED_TO_TOP);
+ }
}
+ info.getChanges().add(i, change);
}
- info.getChanges().add(i, change);
}
} else {
// Open transition, the transition info should be:
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityBackAnimation.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityBackAnimation.kt
index 4fd8b8a..32e809a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityBackAnimation.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityBackAnimation.kt
@@ -189,10 +189,13 @@
preparePreCommitEnteringRectMovement()
background.ensureBackground(
- closingTarget!!.windowConfiguration.bounds,
- getBackgroundColor(),
- transaction,
- statusbarHeight
+ closingTarget!!.windowConfiguration.bounds,
+ getBackgroundColor(),
+ transaction,
+ statusbarHeight,
+ if (closingTarget!!.windowConfiguration.tasksAreFloating())
+ closingTarget!!.localBounds else null,
+ cornerRadius
)
ensureScrimLayer()
if (isLetterboxed && enteringHasSameLetterbox) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
index dabfeeb..3dc33c2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
@@ -2217,7 +2217,6 @@
// And since all children are removed, remove the summary.
removeCallback.accept(-1);
- // TODO: (b/145659174) remove references to mSuppressedGroupKeys once fully migrated
mBubbleData.addSummaryToSuppress(summary.getStatusBarNotification().getGroupKey(),
summary.getKey());
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayController.java
index dcbc72a..7c51a69 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayController.java
@@ -23,6 +23,7 @@
import android.hardware.display.DisplayManager;
import android.os.RemoteException;
import android.util.ArraySet;
+import android.util.Size;
import android.util.Slog;
import android.util.SparseArray;
import android.view.Display;
@@ -193,8 +194,8 @@
/** Called when a display rotate requested. */
- public void onDisplayRotateRequested(WindowContainerTransaction wct, int displayId,
- int fromRotation, int toRotation) {
+ public void onDisplayChangeRequested(WindowContainerTransaction wct, int displayId,
+ Rect startAbsBounds, Rect endAbsBounds, int fromRotation, int toRotation) {
synchronized (mDisplays) {
final DisplayRecord dr = mDisplays.get(displayId);
if (dr == null) {
@@ -203,6 +204,13 @@
}
if (dr.mDisplayLayout != null) {
+ if (endAbsBounds != null) {
+ // If there is a change in the display dimensions update the layout as well;
+ // note that endAbsBounds should ignore any potential rotation changes, so
+ // we still need to rotate the layout after if needed.
+ dr.mDisplayLayout.resizeTo(dr.mContext.getResources(),
+ new Size(endAbsBounds.width(), endAbsBounds.height()));
+ }
dr.mDisplayLayout.rotateTo(dr.mContext.getResources(), toRotation);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java
index 84e32a2..b6a1686 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java
@@ -35,6 +35,7 @@
import android.os.SystemProperties;
import android.provider.Settings;
import android.util.DisplayMetrics;
+import android.util.Size;
import android.view.Display;
import android.view.DisplayCutout;
import android.view.DisplayInfo;
@@ -244,6 +245,16 @@
recalcInsets(res);
}
+ /**
+ * Update the dimensions of this layout.
+ */
+ public void resizeTo(Resources res, Size displaySize) {
+ mWidth = displaySize.getWidth();
+ mHeight = displaySize.getHeight();
+
+ recalcInsets(res);
+ }
+
/** Get this layout's non-decor insets. */
public Rect nonDecorInsets() {
return mNonDecorInsets;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java
index 442036ff..e7848e2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java
@@ -58,6 +58,7 @@
import com.android.wm.shell.R;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
import com.android.wm.shell.shared.animation.Interpolators;
+import com.android.wm.shell.shared.desktopmode.DesktopModeStatus;
/**
* Divider for multi window splits.
@@ -228,7 +229,9 @@
: R.dimen.split_divider_handle_region_width);
mHandleRegionHeight = getResources().getDimensionPixelSize(isLeftRightSplit
? R.dimen.split_divider_handle_region_width
- : R.dimen.split_divider_handle_region_height);
+ : DesktopModeStatus.canEnterDesktopMode(mContext)
+ ? R.dimen.desktop_mode_portrait_split_divider_handle_region_height
+ : R.dimen.split_divider_handle_region_height);
}
void onInsetsChanged(InsetsState insetsState, boolean animate) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
index e807afb..2a934cb 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
@@ -27,6 +27,8 @@
import static com.android.internal.jank.InteractionJankMonitor.CUJ_SPLIT_SCREEN_DOUBLE_TAP_DIVIDER;
import static com.android.internal.jank.InteractionJankMonitor.CUJ_SPLIT_SCREEN_RESIZE;
import static com.android.wm.shell.shared.animation.Interpolators.DIM_INTERPOLATOR;
+import static com.android.wm.shell.shared.animation.Interpolators.EMPHASIZED;
+import static com.android.wm.shell.shared.animation.Interpolators.LINEAR;
import static com.android.wm.shell.shared.animation.Interpolators.SLOWDOWN_INTERPOLATOR;
import static com.android.wm.shell.shared.split.SplitScreenConstants.SNAP_TO_END_AND_DISMISS;
import static com.android.wm.shell.shared.split.SplitScreenConstants.SNAP_TO_START_AND_DISMISS;
@@ -813,7 +815,9 @@
float growPortion = 1 - shrinkPortion;
ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
- animator.setInterpolator(Interpolators.EMPHASIZED);
+ // Set the base animation to proceed linearly. Each component of the animation (movement,
+ // shrinking, growing) overrides it with a different interpolator later.
+ animator.setInterpolator(LINEAR);
animator.addUpdateListener(animation -> {
if (leash == null) return;
if (roundCorners) {
@@ -822,10 +826,11 @@
}
final float progress = (float) animation.getAnimatedValue();
- float instantaneousX = tempStart.left + progress * diffX;
- float instantaneousY = tempStart.top + progress * diffY;
- int width = (int) (tempStart.width() + progress * diffWidth);
- int height = (int) (tempStart.height() + progress * diffHeight);
+ final float moveProgress = EMPHASIZED.getInterpolation(progress);
+ float instantaneousX = tempStart.left + moveProgress * diffX;
+ float instantaneousY = tempStart.top + moveProgress * diffY;
+ int width = (int) (tempStart.width() + moveProgress * diffWidth);
+ int height = (int) (tempStart.height() + moveProgress * diffHeight);
if (isGoingBehind) {
float shrinkDiffX; // the position adjustments needed for this frame
@@ -897,8 +902,8 @@
taskInfo, mTempRect, t, isGoingBehind, leash, 0, 0);
}
} else {
- final int diffOffsetX = (int) (progress * offsetX);
- final int diffOffsetY = (int) (progress * offsetY);
+ final int diffOffsetX = (int) (moveProgress * offsetX);
+ final int diffOffsetY = (int) (moveProgress * offsetY);
t.setPosition(leash, instantaneousX + diffOffsetX, instantaneousY + diffOffsetY);
mTempRect.set(0, 0, width, height);
mTempRect.offsetTo(-diffOffsetX, -diffOffsetY);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
index aa42c67..ce054a8 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
@@ -304,6 +304,7 @@
ShellInit shellInit,
ShellTaskOrganizer shellTaskOrganizer,
Optional<DesktopModeTaskRepository> desktopModeTaskRepository,
+ LaunchAdjacentController launchAdjacentController,
WindowDecorViewModel windowDecorViewModel) {
// TODO(b/238217847): Temporarily add this check here until we can remove the dynamic
// override for this controller from the base module
@@ -311,7 +312,7 @@
? shellInit
: null;
return new FreeformTaskListener(context, init, shellTaskOrganizer,
- desktopModeTaskRepository, windowDecorViewModel);
+ desktopModeTaskRepository, launchAdjacentController, windowDecorViewModel);
}
@WMSingleton
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
index f36e620..33794d2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
@@ -150,12 +150,6 @@
visualIndicator?.releaseVisualIndicator(t)
visualIndicator = null
}
- private val taskVisibilityListener =
- object : VisibleTasksListener {
- override fun onTasksVisibilityChanged(displayId: Int, visibleTasksCount: Int) {
- launchAdjacentController.launchAdjacentEnabled = visibleTasksCount == 0
- }
- }
private val dragToDesktopStateListener =
object : DragToDesktopStateListener {
override fun onCommitToDesktopAnimationStart(tx: SurfaceControl.Transaction) {
@@ -201,7 +195,6 @@
this
)
transitions.addHandler(this)
- taskRepository.addVisibleTasksListener(taskVisibilityListener, mainExecutor)
dragToDesktopTransitionHandler.dragToDesktopStateListener = dragToDesktopStateListener
recentsTransitionHandler.addTransitionStateListener(
object : RecentsTransitionStateListener {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java
index 456767a..83cc18b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java
@@ -27,6 +27,7 @@
import com.android.internal.protolog.ProtoLog;
import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.common.LaunchAdjacentController;
import com.android.wm.shell.desktopmode.DesktopModeTaskRepository;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
import com.android.wm.shell.shared.desktopmode.DesktopModeStatus;
@@ -49,6 +50,7 @@
private final ShellTaskOrganizer mShellTaskOrganizer;
private final Optional<DesktopModeTaskRepository> mDesktopModeTaskRepository;
private final WindowDecorViewModel mWindowDecorationViewModel;
+ private final LaunchAdjacentController mLaunchAdjacentController;
private final SparseArray<State> mTasks = new SparseArray<>();
@@ -62,11 +64,13 @@
ShellInit shellInit,
ShellTaskOrganizer shellTaskOrganizer,
Optional<DesktopModeTaskRepository> desktopModeTaskRepository,
+ LaunchAdjacentController launchAdjacentController,
WindowDecorViewModel windowDecorationViewModel) {
mContext = context;
mShellTaskOrganizer = shellTaskOrganizer;
mWindowDecorationViewModel = windowDecorationViewModel;
mDesktopModeTaskRepository = desktopModeTaskRepository;
+ mLaunchAdjacentController = launchAdjacentController;
if (shellInit != null) {
shellInit.addInitCallback(this::onInit, this);
}
@@ -106,6 +110,7 @@
}
});
}
+ updateLaunchAdjacentController();
}
@Override
@@ -123,6 +128,7 @@
if (!Transitions.ENABLE_SHELL_TRANSITIONS) {
mWindowDecorationViewModel.destroyWindowDecoration(taskInfo);
}
+ updateLaunchAdjacentController();
}
@Override
@@ -144,6 +150,17 @@
taskInfo.isVisible);
});
}
+ updateLaunchAdjacentController();
+ }
+
+ private void updateLaunchAdjacentController() {
+ for (int i = 0; i < mTasks.size(); i++) {
+ if (mTasks.valueAt(i).mTaskInfo.isVisible) {
+ mLaunchAdjacentController.setLaunchAdjacentEnabled(false);
+ return;
+ }
+ }
+ mLaunchAdjacentController.setLaunchAdjacentEnabled(true);
}
@Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipController.java
index eb6caba..e9c4c14 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipController.java
@@ -29,7 +29,6 @@
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.Bundle;
-import android.view.InsetsState;
import android.view.SurfaceControl;
import android.window.DisplayAreaInfo;
import android.window.WindowContainerTransaction;
@@ -200,17 +199,8 @@
DisplayLayout layout = new DisplayLayout(mContext, mContext.getDisplay());
mPipDisplayLayoutState.setDisplayLayout(layout);
- mDisplayController.addDisplayWindowListener(this);
mDisplayController.addDisplayChangingController(this);
mDisplayInsetsController.addInsetsChangedListener(mPipDisplayLayoutState.getDisplayId(),
- new DisplayInsetsController.OnInsetsChangedListener() {
- @Override
- public void insetsChanged(InsetsState insetsState) {
- setDisplayLayout(mDisplayController
- .getDisplayLayout(mPipDisplayLayoutState.getDisplayId()));
- }
- });
- mDisplayInsetsController.addInsetsChangedListener(mPipDisplayLayoutState.getDisplayId(),
new ImeListener(mDisplayController, mPipDisplayLayoutState.getDisplayId()) {
@Override
public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {
@@ -285,34 +275,37 @@
setDisplayLayout(mDisplayController.getDisplayLayout(displayId));
}
- @Override
- public void onDisplayConfigurationChanged(int displayId, Configuration newConfig) {
- if (displayId != mPipDisplayLayoutState.getDisplayId()) {
- return;
- }
- setDisplayLayout(mDisplayController.getDisplayLayout(displayId));
- }
-
/**
* A callback for any observed transition that contains a display change in its
- * {@link android.window.TransitionRequestInfo} with a non-zero rotation delta.
+ * {@link android.window.TransitionRequestInfo},
*/
@Override
public void onDisplayChange(int displayId, int fromRotation, int toRotation,
@Nullable DisplayAreaInfo newDisplayAreaInfo, WindowContainerTransaction t) {
+ if (displayId != mPipDisplayLayoutState.getDisplayId()) {
+ return;
+ }
+ final float snapFraction = mPipBoundsAlgorithm.getSnapFraction(mPipBoundsState.getBounds());
+ final float boundsScale = mPipBoundsState.getBoundsScale();
+
+ // Update the display layout caches even if we are not in PiP.
+ setDisplayLayout(mDisplayController.getDisplayLayout(displayId));
+
if (!mPipTransitionState.isInPip()) {
return;
}
- // Calculate the snap fraction pre-rotation.
- float snapFraction = mPipBoundsAlgorithm.getSnapFraction(mPipBoundsState.getBounds());
+ mPipTouchHandler.updateMinMaxSize(mPipBoundsState.getAspectRatio());
- // Update the caches to reflect the new display layout and movement bounds.
- mPipDisplayLayoutState.rotateTo(toRotation);
+ // Update the caches to reflect the new display layout in the movement bounds;
+ // temporarily update bounds to be at the top left for the movement bounds calculation.
+ Rect toBounds = new Rect(0, 0,
+ (int) Math.ceil(mPipBoundsState.getMaxSize().x * boundsScale),
+ (int) Math.ceil(mPipBoundsState.getMaxSize().y * boundsScale));
+ mPipBoundsState.setBounds(toBounds);
mPipTouchHandler.updateMovementBounds();
- // The policy is to keep PiP width, height and snap fraction invariant.
- Rect toBounds = mPipBoundsState.getBounds();
+ // The policy is to keep PiP snap fraction invariant.
mPipBoundsAlgorithm.applySnapFraction(toBounds, snapFraction);
mPipBoundsState.setBounds(toBounds);
t.setBounds(mPipTransitionState.mPipTaskToken, toBounds);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellInit.java b/libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellInit.java
index 287e779..1140c82 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellInit.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellInit.java
@@ -48,7 +48,7 @@
public ShellInit(ShellExecutor mainExecutor) {
mMainExecutor = mainExecutor;
- ProtoLog.registerGroups(ShellProtoLogGroup.values());
+ ProtoLog.init(ShellProtoLogGroup.values());
}
/**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/OneShotRemoteHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/OneShotRemoteHandler.java
index b7b42c7..209fc39 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/OneShotRemoteHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/OneShotRemoteHandler.java
@@ -114,7 +114,6 @@
t.clear();
mMainExecutor.execute(() -> {
finishCallback.onTransitionFinished(wct);
- mRemote = null;
});
}
};
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
index 68217c0..f0d3668 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
@@ -1187,12 +1187,15 @@
}
if (request.getDisplayChange() != null) {
TransitionRequestInfo.DisplayChange change = request.getDisplayChange();
- if (change.getEndRotation() != change.getStartRotation()) {
- // Is a rotation, so dispatch to all displayChange listeners
+ if (change.getStartRotation() != change.getEndRotation()
+ || (change.getStartAbsBounds() != null
+ && !change.getStartAbsBounds().equals(change.getEndAbsBounds()))) {
+ // Is a display change, so dispatch to all displayChange listeners
if (wct == null) {
wct = new WindowContainerTransaction();
}
- mDisplayController.onDisplayRotateRequested(wct, change.getDisplayId(),
+ mDisplayController.onDisplayChangeRequested(wct, change.getDisplayId(),
+ change.getStartAbsBounds(), change.getEndAbsBounds(),
change.getStartRotation(), change.getEndRotation());
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragPositioningCallbackUtility.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragPositioningCallbackUtility.java
index 0f2de70..cb9781e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragPositioningCallbackUtility.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragPositioningCallbackUtility.java
@@ -82,32 +82,26 @@
final int oldRight = repositionTaskBounds.right;
final int oldBottom = repositionTaskBounds.bottom;
-
repositionTaskBounds.set(taskBoundsAtDragStart);
// Make sure the new resizing destination in any direction falls within the stable bounds.
- // If not, set the bounds back to the old location that was valid to avoid conflicts with
- // some regions such as the gesture area.
if ((ctrlType & CTRL_TYPE_LEFT) != 0) {
- final int candidateLeft = repositionTaskBounds.left + (int) delta.x;
- repositionTaskBounds.left = (candidateLeft > stableBounds.left)
- ? candidateLeft : oldLeft;
+ repositionTaskBounds.left = Math.max(repositionTaskBounds.left + (int) delta.x,
+ stableBounds.left);
}
if ((ctrlType & CTRL_TYPE_RIGHT) != 0) {
- final int candidateRight = repositionTaskBounds.right + (int) delta.x;
- repositionTaskBounds.right = (candidateRight < stableBounds.right)
- ? candidateRight : oldRight;
+ repositionTaskBounds.right = Math.min(repositionTaskBounds.right + (int) delta.x,
+ stableBounds.right);
}
if ((ctrlType & CTRL_TYPE_TOP) != 0) {
- final int candidateTop = repositionTaskBounds.top + (int) delta.y;
- repositionTaskBounds.top = (candidateTop > stableBounds.top)
- ? candidateTop : oldTop;
+ repositionTaskBounds.top = Math.max(repositionTaskBounds.top + (int) delta.y,
+ stableBounds.top);
}
if ((ctrlType & CTRL_TYPE_BOTTOM) != 0) {
- final int candidateBottom = repositionTaskBounds.bottom + (int) delta.y;
- repositionTaskBounds.bottom = (candidateBottom < stableBounds.bottom)
- ? candidateBottom : oldBottom;
+ repositionTaskBounds.bottom = Math.min(repositionTaskBounds.bottom + (int) delta.y,
+ stableBounds.bottom);
}
+
// If width or height are negative or exceeding the width or height constraints, revert the
// respective bounds to use previous bound dimensions.
if (isExceedingWidthConstraint(repositionTaskBounds, stableBounds, displayController,
@@ -120,14 +114,12 @@
repositionTaskBounds.top = oldTop;
repositionTaskBounds.bottom = oldBottom;
}
- // If there are no changes to the bounds after checking new bounds against minimum width
- // and height, do not set bounds and return false
- if (oldLeft == repositionTaskBounds.left && oldTop == repositionTaskBounds.top
- && oldRight == repositionTaskBounds.right
- && oldBottom == repositionTaskBounds.bottom) {
- return false;
- }
- return true;
+
+ // If there are no changes to the bounds after checking new bounds against minimum and
+ // maximum width and height, do not set bounds and return false
+ return oldLeft != repositionTaskBounds.left || oldTop != repositionTaskBounds.top
+ || oldRight != repositionTaskBounds.right
+ || oldBottom != repositionTaskBounds.bottom;
}
/**
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 fd7bed7..6dedf6d 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
@@ -16,6 +16,7 @@
package com.android.wm.shell.windowdecor;
+import static android.view.InputDevice.SOURCE_MOUSE;
import static android.view.InputDevice.SOURCE_TOUCHSCREEN;
import static com.android.wm.shell.shared.desktopmode.DesktopModeFlags.EDGE_DRAG_RESIZE;
@@ -166,7 +167,10 @@
static boolean isEdgeResizePermitted(@NonNull Context context, @NonNull MotionEvent e) {
if (EDGE_DRAG_RESIZE.isEnabled(context)) {
return e.getToolType(0) == MotionEvent.TOOL_TYPE_STYLUS
- || e.getToolType(0) == MotionEvent.TOOL_TYPE_MOUSE;
+ || e.getToolType(0) == MotionEvent.TOOL_TYPE_MOUSE
+ // Touchpad input
+ || (e.isFromSource(SOURCE_MOUSE)
+ && e.getToolType(0) == MotionEvent.TOOL_TYPE_FINGER);
} else {
return e.getToolType(0) == MotionEvent.TOOL_TYPE_MOUSE;
}
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/DragAppWindowMultiWindowAndPip.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/DragAppWindowMultiWindowAndPip.kt
new file mode 100644
index 0000000..6d52a11
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/DragAppWindowMultiWindowAndPip.kt
@@ -0,0 +1,73 @@
+/*
+ * 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.wm.shell.scenarios
+
+import android.platform.test.annotations.Postsubmit
+import com.android.server.wm.flicker.helpers.DesktopModeAppHelper
+import com.android.server.wm.flicker.helpers.ImeAppHelper
+import com.android.server.wm.flicker.helpers.MailAppHelper
+import com.android.server.wm.flicker.helpers.NewTasksAppHelper
+import com.android.server.wm.flicker.helpers.PipAppHelper
+import com.android.server.wm.flicker.helpers.SimpleAppHelper
+import com.android.window.flags.Flags
+import org.junit.After
+import org.junit.Assume
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.BlockJUnit4ClassRunner
+
+@RunWith(BlockJUnit4ClassRunner::class)
+@Postsubmit
+open class DragAppWindowMultiWindowAndPip : DragAppWindowScenarioTestBase()
+{
+ private val imeAppHelper = ImeAppHelper(instrumentation)
+ private val testApp = DesktopModeAppHelper(SimpleAppHelper(instrumentation))
+ private val pipApp = PipAppHelper(instrumentation)
+ private val mailApp = DesktopModeAppHelper(MailAppHelper(instrumentation))
+ private val newTasksApp = DesktopModeAppHelper(NewTasksAppHelper(instrumentation))
+ private val imeApp = DesktopModeAppHelper(ImeAppHelper(instrumentation))
+
+ @Before
+ fun setup() {
+ Assume.assumeTrue(Flags.enableDesktopWindowingMode() && tapl.isTablet)
+ // Set string extra to ensure the app is on PiP mode at launch
+ pipApp.launchViaIntentAndWaitForPip(wmHelper, stringExtras = mapOf("enter_pip" to "true"))
+ testApp.enterDesktopWithDrag(wmHelper, device)
+ mailApp.launchViaIntent(wmHelper)
+ newTasksApp.launchViaIntent(wmHelper)
+ imeApp.launchViaIntent(wmHelper)
+ }
+
+ @Test
+ override fun dragAppWindow() {
+ val (startXIme, startYIme) = getWindowDragStartCoordinate(imeAppHelper)
+
+ imeApp.dragWindow(startXIme, startYIme,
+ endX = startXIme + 150, endY = startYIme + 150,
+ wmHelper, device)
+ }
+
+ @After
+ fun teardown() {
+ testApp.exit(wmHelper)
+ pipApp.exit(wmHelper)
+ mailApp.exit(wmHelper)
+ newTasksApp.exit(wmHelper)
+ imeApp.exit(wmHelper)
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ResizeAppCornerMultiWindow.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ResizeAppCornerMultiWindow.kt
new file mode 100644
index 0000000..b6bca7a
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ResizeAppCornerMultiWindow.kt
@@ -0,0 +1,90 @@
+/*
+ * 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.wm.shell.scenarios
+
+import android.platform.test.annotations.Postsubmit
+import android.app.Instrumentation
+import android.tools.NavBar
+import android.tools.Rotation
+import android.tools.traces.parsers.WindowManagerStateHelper
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.uiautomator.UiDevice
+import com.android.launcher3.tapl.LauncherInstrumentation
+import com.android.server.wm.flicker.helpers.DesktopModeAppHelper
+import com.android.server.wm.flicker.helpers.ImeAppHelper
+import com.android.server.wm.flicker.helpers.MailAppHelper
+import com.android.server.wm.flicker.helpers.NewTasksAppHelper
+import com.android.server.wm.flicker.helpers.SimpleAppHelper
+import com.android.window.flags.Flags
+import com.android.wm.shell.Utils
+import org.junit.After
+import org.junit.Assume
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.BlockJUnit4ClassRunner
+
+@RunWith(BlockJUnit4ClassRunner::class)
+@Postsubmit
+open class ResizeAppCornerMultiWindow
+@JvmOverloads
+constructor(val rotation: Rotation = Rotation.ROTATION_0,
+ val horizontalChange: Int = 50,
+ val verticalChange: Int = -50) {
+
+ private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
+ private val tapl = LauncherInstrumentation()
+ private val wmHelper = WindowManagerStateHelper(instrumentation)
+ private val device = UiDevice.getInstance(instrumentation)
+ private val testApp = DesktopModeAppHelper(SimpleAppHelper(instrumentation))
+ private val mailApp = DesktopModeAppHelper(MailAppHelper(instrumentation))
+ private val newTasksApp = DesktopModeAppHelper(NewTasksAppHelper(instrumentation))
+ private val imeApp = DesktopModeAppHelper(ImeAppHelper(instrumentation))
+
+ @Rule
+ @JvmField
+ val testSetupRule = Utils.testSetupRule(NavBar.MODE_GESTURAL, rotation)
+
+ @Before
+ fun setup() {
+ Assume.assumeTrue(Flags.enableDesktopWindowingMode() && tapl.isTablet)
+ tapl.setEnableRotation(true)
+ tapl.setExpectedRotation(rotation.value)
+ testApp.enterDesktopWithDrag(wmHelper, device)
+ mailApp.launchViaIntent(wmHelper)
+ newTasksApp.launchViaIntent(wmHelper)
+ imeApp.launchViaIntent(wmHelper)
+ }
+
+ @Test
+ open fun resizeAppWithCornerResize() {
+ imeApp.cornerResize(wmHelper,
+ device,
+ DesktopModeAppHelper.Corners.RIGHT_TOP,
+ horizontalChange,
+ verticalChange)
+ }
+
+ @After
+ fun teardown() {
+ testApp.exit(wmHelper)
+ mailApp.exit(wmHelper)
+ newTasksApp.exit(wmHelper)
+ imeApp.exit(wmHelper)
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ResizeAppCornerMultiWindowAndPip.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ResizeAppCornerMultiWindowAndPip.kt
new file mode 100644
index 0000000..285ea13
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ResizeAppCornerMultiWindowAndPip.kt
@@ -0,0 +1,95 @@
+/*
+ * 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.wm.shell.scenarios
+
+import android.platform.test.annotations.Postsubmit
+import android.app.Instrumentation
+import android.tools.NavBar
+import android.tools.Rotation
+import android.tools.traces.parsers.WindowManagerStateHelper
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.uiautomator.UiDevice
+import com.android.launcher3.tapl.LauncherInstrumentation
+import com.android.server.wm.flicker.helpers.DesktopModeAppHelper
+import com.android.server.wm.flicker.helpers.ImeAppHelper
+import com.android.server.wm.flicker.helpers.MailAppHelper
+import com.android.server.wm.flicker.helpers.NewTasksAppHelper
+import com.android.server.wm.flicker.helpers.PipAppHelper
+import com.android.server.wm.flicker.helpers.SimpleAppHelper
+import com.android.window.flags.Flags
+import com.android.wm.shell.Utils
+import org.junit.After
+import org.junit.Assume
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.BlockJUnit4ClassRunner
+
+@RunWith(BlockJUnit4ClassRunner::class)
+@Postsubmit
+open class ResizeAppCornerMultiWindowAndPip
+@JvmOverloads
+constructor(val rotation: Rotation = Rotation.ROTATION_0,
+ val horizontalChange: Int = 50,
+ val verticalChange: Int = -50) {
+
+ private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
+ private val tapl = LauncherInstrumentation()
+ private val wmHelper = WindowManagerStateHelper(instrumentation)
+ private val device = UiDevice.getInstance(instrumentation)
+ private val testApp = DesktopModeAppHelper(SimpleAppHelper(instrumentation))
+ private val pipApp = PipAppHelper(instrumentation)
+ private val mailApp = DesktopModeAppHelper(MailAppHelper(instrumentation))
+ private val newTasksApp = DesktopModeAppHelper(NewTasksAppHelper(instrumentation))
+ private val imeApp = DesktopModeAppHelper(ImeAppHelper(instrumentation))
+
+ @Rule
+ @JvmField
+ val testSetupRule = Utils.testSetupRule(NavBar.MODE_GESTURAL, rotation)
+
+ @Before
+ fun setup() {
+ Assume.assumeTrue(Flags.enableDesktopWindowingMode() && tapl.isTablet)
+ tapl.setEnableRotation(true)
+ tapl.setExpectedRotation(rotation.value)
+ // Set string extra to ensure the app is on PiP mode at launch
+ pipApp.launchViaIntentAndWaitForPip(wmHelper, stringExtras = mapOf("enter_pip" to "true"))
+ testApp.enterDesktopWithDrag(wmHelper, device)
+ mailApp.launchViaIntent(wmHelper)
+ newTasksApp.launchViaIntent(wmHelper)
+ imeApp.launchViaIntent(wmHelper)
+ }
+
+ @Test
+ open fun resizeAppWithCornerResize() {
+ imeApp.cornerResize(wmHelper,
+ device,
+ DesktopModeAppHelper.Corners.RIGHT_TOP,
+ horizontalChange,
+ verticalChange)
+ }
+
+ @After
+ fun teardown() {
+ testApp.exit(wmHelper)
+ pipApp.exit(wmHelper)
+ mailApp.exit(wmHelper)
+ newTasksApp.exit(wmHelper)
+ imeApp.exit(wmHelper)
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
index ff52480..a841e16 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
@@ -2264,27 +2264,6 @@
}
@Test
- fun desktopTasksVisibilityChange_visible_setLaunchAdjacentDisabled() {
- val task = setUpFreeformTask()
- clearInvocations(launchAdjacentController)
-
- markTaskVisible(task)
- shellExecutor.flushAll()
- verify(launchAdjacentController).launchAdjacentEnabled = false
- }
-
- @Test
- fun desktopTasksVisibilityChange_invisible_setLaunchAdjacentEnabled() {
- val task = setUpFreeformTask()
- markTaskVisible(task)
- clearInvocations(launchAdjacentController)
-
- markTaskHidden(task)
- shellExecutor.flushAll()
- verify(launchAdjacentController).launchAdjacentEnabled = true
- }
-
- @Test
fun moveFocusedTaskToDesktop_fullscreenTaskIsMovedToDesktop() {
val task1 = setUpFullscreenTask()
val task2 = setUpFullscreenTask()
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/freeform/FreeformTaskListenerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/freeform/FreeformTaskListenerTests.java
index 6ec6bed..763d015 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/freeform/FreeformTaskListenerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/freeform/FreeformTaskListenerTests.java
@@ -27,6 +27,7 @@
import static org.mockito.Mockito.verify;
import android.app.ActivityManager;
+import android.view.SurfaceControl;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
@@ -35,6 +36,7 @@
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.ShellTestCase;
import com.android.wm.shell.TestRunningTaskInfoBuilder;
+import com.android.wm.shell.common.LaunchAdjacentController;
import com.android.wm.shell.desktopmode.DesktopModeTaskRepository;
import com.android.wm.shell.shared.desktopmode.DesktopModeStatus;
import com.android.wm.shell.sysui.ShellInit;
@@ -65,7 +67,11 @@
@Mock
private WindowDecorViewModel mWindowDecorViewModel;
@Mock
+ private SurfaceControl mMockSurfaceControl;
+ @Mock
private DesktopModeTaskRepository mDesktopModeTaskRepository;
+ @Mock
+ private LaunchAdjacentController mLaunchAdjacentController;
private FreeformTaskListener mFreeformTaskListener;
private StaticMockitoSession mMockitoSession;
@@ -80,6 +86,7 @@
mShellInit,
mTaskOrganizer,
Optional.of(mDesktopModeTaskRepository),
+ mLaunchAdjacentController,
mWindowDecorViewModel);
}
@@ -107,6 +114,31 @@
.addOrMoveFreeformTaskToTop(fullscreenTask.displayId, fullscreenTask.taskId);
}
+ @Test
+ public void testVisibilityTaskChanged_visible_setLaunchAdjacentDisabled() {
+ ActivityManager.RunningTaskInfo task = new TestRunningTaskInfoBuilder()
+ .setWindowingMode(WINDOWING_MODE_FREEFORM).build();
+ task.isVisible = true;
+
+ mFreeformTaskListener.onTaskAppeared(task, mMockSurfaceControl);
+
+ verify(mLaunchAdjacentController).setLaunchAdjacentEnabled(false);
+ }
+
+ @Test
+ public void testVisibilityTaskChanged_NotVisible_setLaunchAdjacentEnabled() {
+ ActivityManager.RunningTaskInfo task = new TestRunningTaskInfoBuilder()
+ .setWindowingMode(WINDOWING_MODE_FREEFORM).build();
+ task.isVisible = true;
+
+ mFreeformTaskListener.onTaskAppeared(task, mMockSurfaceControl);
+
+ task.isVisible = false;
+ mFreeformTaskListener.onTaskInfoChanged(task);
+
+ verify(mLaunchAdjacentController).setLaunchAdjacentEnabled(true);
+ }
+
@After
public void tearDown() {
mMockitoSession.finishMocking();
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
index b3d56b1..0054cb6 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
@@ -25,7 +25,6 @@
import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_MAIN;
import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_SIDE;
import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_UNDEFINED;
-import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_RETURN_HOME;
import static com.android.wm.shell.transition.Transitions.TRANSIT_SPLIT_DISMISS;
import static com.google.common.truth.Truth.assertThat;
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DragPositioningCallbackUtilityTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DragPositioningCallbackUtilityTest.kt
index e529711..1f33ae6 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DragPositioningCallbackUtilityTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DragPositioningCallbackUtilityTest.kt
@@ -93,7 +93,7 @@
fun setup() {
MockitoAnnotations.initMocks(this)
mockitoSession = ExtendedMockito.mockitoSession().strictness(Strictness.LENIENT)
- .spyStatic(DesktopModeStatus::class.java).startMocking()
+ .spyStatic(DesktopModeStatus::class.java).startMocking()
whenever(taskToken.asBinder()).thenReturn(taskBinder)
whenever(mockDisplayController.getDisplayLayout(DISPLAY_ID)).thenReturn(mockDisplayLayout)
@@ -108,9 +108,9 @@
whenever(mockContext.getResources()).thenReturn(mockResources)
whenever(mockWindowDecoration.mDecorWindowContext.resources).thenReturn(mockResources)
whenever(mockResources.getDimensionPixelSize(R.dimen.desktop_mode_minimum_window_width))
- .thenReturn(DESKTOP_MODE_MIN_WIDTH)
+ .thenReturn(DESKTOP_MODE_MIN_WIDTH)
whenever(mockResources.getDimensionPixelSize(R.dimen.desktop_mode_minimum_window_height))
- .thenReturn(DESKTOP_MODE_MIN_HEIGHT)
+ .thenReturn(DESKTOP_MODE_MIN_HEIGHT)
whenever(mockDisplay.displayId).thenAnswer { DISPLAY_ID }
}
@@ -129,9 +129,11 @@
val newY = STARTING_BOUNDS.top.toFloat() + 95
val delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint)
- DragPositioningCallbackUtility.changeBounds(CTRL_TYPE_RIGHT or CTRL_TYPE_TOP,
+ DragPositioningCallbackUtility.changeBounds(
+ CTRL_TYPE_RIGHT or CTRL_TYPE_TOP,
repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController,
- mockWindowDecoration)
+ mockWindowDecoration
+ )
assertThat(repositionTaskBounds.left).isEqualTo(STARTING_BOUNDS.left)
assertThat(repositionTaskBounds.top).isEqualTo(STARTING_BOUNDS.top)
@@ -149,9 +151,11 @@
val newY = STARTING_BOUNDS.top.toFloat() + 5
val delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint)
- DragPositioningCallbackUtility.changeBounds(CTRL_TYPE_RIGHT or CTRL_TYPE_TOP,
+ DragPositioningCallbackUtility.changeBounds(
+ CTRL_TYPE_RIGHT or CTRL_TYPE_TOP,
repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController,
- mockWindowDecoration)
+ mockWindowDecoration
+ )
assertThat(repositionTaskBounds.left).isEqualTo(STARTING_BOUNDS.left)
assertThat(repositionTaskBounds.top).isEqualTo(STARTING_BOUNDS.top + 5)
@@ -169,9 +173,11 @@
val newY = STARTING_BOUNDS.top.toFloat() + 105
val delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint)
- DragPositioningCallbackUtility.changeBounds(CTRL_TYPE_RIGHT or CTRL_TYPE_TOP,
+ DragPositioningCallbackUtility.changeBounds(
+ CTRL_TYPE_RIGHT or CTRL_TYPE_TOP,
repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController,
- mockWindowDecoration)
+ mockWindowDecoration
+ )
assertThat(repositionTaskBounds.left).isEqualTo(STARTING_BOUNDS.left)
assertThat(repositionTaskBounds.top).isEqualTo(STARTING_BOUNDS.top)
@@ -189,9 +195,11 @@
val newY = STARTING_BOUNDS.top.toFloat() + 80
val delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint)
- DragPositioningCallbackUtility.changeBounds(CTRL_TYPE_RIGHT or CTRL_TYPE_TOP,
+ DragPositioningCallbackUtility.changeBounds(
+ CTRL_TYPE_RIGHT or CTRL_TYPE_TOP,
repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController,
- mockWindowDecoration)
+ mockWindowDecoration
+ )
assertThat(repositionTaskBounds.left).isEqualTo(STARTING_BOUNDS.left)
assertThat(repositionTaskBounds.top).isEqualTo(STARTING_BOUNDS.top + 80)
assertThat(repositionTaskBounds.right).isEqualTo(STARTING_BOUNDS.right - 80)
@@ -208,9 +216,11 @@
val delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint)
- DragPositioningCallbackUtility.changeBounds(CTRL_TYPE_RIGHT or CTRL_TYPE_TOP,
+ DragPositioningCallbackUtility.changeBounds(
+ CTRL_TYPE_RIGHT or CTRL_TYPE_TOP,
repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController,
- mockWindowDecoration)
+ mockWindowDecoration
+ )
assertThat(repositionTaskBounds.left).isEqualTo(STARTING_BOUNDS.left)
assertThat(repositionTaskBounds.top).isEqualTo(STARTING_BOUNDS.top)
assertThat(repositionTaskBounds.right).isEqualTo(STARTING_BOUNDS.right)
@@ -221,52 +231,95 @@
fun testDragEndSnapsTaskBoundsWhenOutsideValidDragArea() {
val startingPoint = PointF(STARTING_BOUNDS.right.toFloat(), STARTING_BOUNDS.top.toFloat())
val repositionTaskBounds = Rect(STARTING_BOUNDS)
- val validDragArea = Rect(DISPLAY_BOUNDS.left - 100,
+ val validDragArea = Rect(
+ DISPLAY_BOUNDS.left - 100,
STABLE_BOUNDS.top,
DISPLAY_BOUNDS.right - 100,
- DISPLAY_BOUNDS.bottom - 100)
+ DISPLAY_BOUNDS.bottom - 100
+ )
- DragPositioningCallbackUtility.updateTaskBounds(repositionTaskBounds, STARTING_BOUNDS,
- startingPoint, startingPoint.x - 1000, (DISPLAY_BOUNDS.bottom + 1000).toFloat())
- DragPositioningCallbackUtility.snapTaskBoundsIfNecessary(repositionTaskBounds,
- validDragArea)
+ DragPositioningCallbackUtility.updateTaskBounds(
+ repositionTaskBounds, STARTING_BOUNDS,
+ startingPoint, startingPoint.x - 1000, (DISPLAY_BOUNDS.bottom + 1000).toFloat()
+ )
+ DragPositioningCallbackUtility.snapTaskBoundsIfNecessary(
+ repositionTaskBounds,
+ validDragArea
+ )
assertThat(repositionTaskBounds.left).isEqualTo(validDragArea.left)
assertThat(repositionTaskBounds.top).isEqualTo(validDragArea.bottom)
assertThat(repositionTaskBounds.right)
- .isEqualTo(validDragArea.left + STARTING_BOUNDS.width())
+ .isEqualTo(validDragArea.left + STARTING_BOUNDS.width())
assertThat(repositionTaskBounds.bottom)
- .isEqualTo(validDragArea.bottom + STARTING_BOUNDS.height())
+ .isEqualTo(validDragArea.bottom + STARTING_BOUNDS.height())
}
@Test
fun testChangeBounds_toDisallowedBounds_freezesAtLimit() {
- val startingPoint = PointF(STARTING_BOUNDS.right.toFloat(),
- STARTING_BOUNDS.bottom.toFloat())
+ val startingPoint = PointF(
+ STARTING_BOUNDS.right.toFloat(),
+ STARTING_BOUNDS.bottom.toFloat()
+ )
val repositionTaskBounds = Rect(STARTING_BOUNDS)
// Initial resize to width and height 110px.
var newX = STARTING_BOUNDS.right.toFloat() + 10
var newY = STARTING_BOUNDS.bottom.toFloat() + 10
var delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint)
- assertTrue(DragPositioningCallbackUtility.changeBounds(CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM,
- repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController,
- mockWindowDecoration))
+ assertTrue(
+ DragPositioningCallbackUtility.changeBounds(
+ CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM,
+ repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController,
+ mockWindowDecoration
+ )
+ )
// Resize width to 120px, height to disallowed area which should not result in a change.
newX += 10
newY = DISALLOWED_RESIZE_AREA.top.toFloat()
delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint)
- assertTrue(DragPositioningCallbackUtility.changeBounds(CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM,
- repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController,
- mockWindowDecoration))
+ assertTrue(
+ DragPositioningCallbackUtility.changeBounds(
+ CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM,
+ repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController,
+ mockWindowDecoration
+ )
+ )
assertThat(repositionTaskBounds.left).isEqualTo(STARTING_BOUNDS.left)
assertThat(repositionTaskBounds.top).isEqualTo(STARTING_BOUNDS.top)
assertThat(repositionTaskBounds.right).isEqualTo(STARTING_BOUNDS.right + 20)
- assertThat(repositionTaskBounds.bottom).isEqualTo(STARTING_BOUNDS.bottom + 10)
+ assertThat(repositionTaskBounds.bottom).isEqualTo(STABLE_BOUNDS.bottom)
+ }
+
+
+ @Test
+ fun testChangeBounds_beyondStableBounds_freezesAtStableBounds() {
+ val startingPoint = PointF(
+ STARTING_BOUNDS.right.toFloat(),
+ STARTING_BOUNDS.bottom.toFloat()
+ )
+ val repositionTaskBounds = Rect(STARTING_BOUNDS)
+
+ // Resize to beyond stable bounds.
+ val newX = STARTING_BOUNDS.right.toFloat() + STABLE_BOUNDS.width()
+ val newY = STARTING_BOUNDS.bottom.toFloat() + STABLE_BOUNDS.height()
+
+ val delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint)
+ assertTrue(
+ DragPositioningCallbackUtility.changeBounds(
+ CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM,
+ repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController,
+ mockWindowDecoration
+ )
+ )
+ assertThat(repositionTaskBounds.left).isEqualTo(STARTING_BOUNDS.left)
+ assertThat(repositionTaskBounds.top).isEqualTo(STARTING_BOUNDS.top)
+ assertThat(repositionTaskBounds.right).isEqualTo(STABLE_BOUNDS.right)
+ assertThat(repositionTaskBounds.bottom).isEqualTo(STABLE_BOUNDS.bottom)
}
@Test
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_SIZE_CONSTRAINTS)
fun taskMinWidthHeightUndefined_changeBoundsInDesktopModeLessThanMin_shouldNotChangeBounds() {
- doReturn(true).`when`{ DesktopModeStatus.canEnterDesktopMode(mockContext) }
+ doReturn(true).`when` { DesktopModeStatus.canEnterDesktopMode(mockContext) }
initializeTaskInfo(taskMinWidth = -1, taskMinHeight = -1)
val startingPoint =
PointF(STARTING_BOUNDS.right.toFloat(), STARTING_BOUNDS.bottom.toFloat())
@@ -277,9 +330,11 @@
val newY = STARTING_BOUNDS.bottom.toFloat() - 99
val delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint)
- DragPositioningCallbackUtility.changeBounds(CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM,
+ DragPositioningCallbackUtility.changeBounds(
+ CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM,
repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController,
- mockWindowDecoration)
+ mockWindowDecoration
+ )
assertThat(repositionTaskBounds.left).isEqualTo(STARTING_BOUNDS.left)
assertThat(repositionTaskBounds.top).isEqualTo(STARTING_BOUNDS.top)
assertThat(repositionTaskBounds.right).isEqualTo(STARTING_BOUNDS.right)
@@ -289,7 +344,7 @@
@Test
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_SIZE_CONSTRAINTS)
fun taskMinWidthHeightUndefined_changeBoundsInDesktopModeAllowedSize_shouldChangeBounds() {
- doReturn(true).`when`{ DesktopModeStatus.canEnterDesktopMode(mockContext) }
+ doReturn(true).`when` { DesktopModeStatus.canEnterDesktopMode(mockContext) }
initializeTaskInfo(taskMinWidth = -1, taskMinHeight = -1)
val startingPoint =
PointF(STARTING_BOUNDS.right.toFloat(), STARTING_BOUNDS.bottom.toFloat())
@@ -300,9 +355,11 @@
val newY = STARTING_BOUNDS.bottom.toFloat() - 80
val delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint)
- DragPositioningCallbackUtility.changeBounds(CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM,
+ DragPositioningCallbackUtility.changeBounds(
+ CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM,
repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController,
- mockWindowDecoration)
+ mockWindowDecoration
+ )
assertThat(repositionTaskBounds.left).isEqualTo(STARTING_BOUNDS.left)
assertThat(repositionTaskBounds.top).isEqualTo(STARTING_BOUNDS.top)
assertThat(repositionTaskBounds.right).isEqualTo(STARTING_BOUNDS.right - 80)
@@ -321,9 +378,11 @@
val newY = STARTING_BOUNDS.bottom.toFloat() - 99
val delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint)
- DragPositioningCallbackUtility.changeBounds(CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM,
+ DragPositioningCallbackUtility.changeBounds(
+ CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM,
repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController,
- mockWindowDecoration)
+ mockWindowDecoration
+ )
assertThat(repositionTaskBounds.left).isEqualTo(STARTING_BOUNDS.left)
assertThat(repositionTaskBounds.top).isEqualTo(STARTING_BOUNDS.top)
assertThat(repositionTaskBounds.right).isEqualTo(STARTING_BOUNDS.right)
@@ -342,9 +401,11 @@
val newY = STARTING_BOUNDS.bottom.toFloat() - 50
val delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint)
- DragPositioningCallbackUtility.changeBounds(CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM,
+ DragPositioningCallbackUtility.changeBounds(
+ CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM,
repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController,
- mockWindowDecoration)
+ mockWindowDecoration
+ )
assertThat(repositionTaskBounds.left).isEqualTo(STARTING_BOUNDS.left)
assertThat(repositionTaskBounds.top).isEqualTo(STARTING_BOUNDS.top)
assertThat(repositionTaskBounds.right).isEqualTo(STARTING_BOUNDS.right - 50)
@@ -355,8 +416,10 @@
@DisableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_SIZE_CONSTRAINTS)
fun testChangeBounds_windowSizeExceedsStableBounds_shouldBeAllowedToChangeBounds() {
val startingPoint =
- PointF(OFF_CENTER_STARTING_BOUNDS.right.toFloat(),
- OFF_CENTER_STARTING_BOUNDS.bottom.toFloat())
+ PointF(
+ OFF_CENTER_STARTING_BOUNDS.right.toFloat(),
+ OFF_CENTER_STARTING_BOUNDS.bottom.toFloat()
+ )
val repositionTaskBounds = Rect(OFF_CENTER_STARTING_BOUNDS)
// Increase height and width by STABLE_BOUNDS. Subtract by 5px so that it doesn't reach
// the disallowed drag area.
@@ -365,9 +428,11 @@
val newY = STABLE_BOUNDS.bottom.toFloat() - offset
val delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint)
- DragPositioningCallbackUtility.changeBounds(CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM,
+ DragPositioningCallbackUtility.changeBounds(
+ CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM,
repositionTaskBounds, OFF_CENTER_STARTING_BOUNDS, STABLE_BOUNDS, delta,
- mockDisplayController, mockWindowDecoration)
+ mockDisplayController, mockWindowDecoration
+ )
assertThat(repositionTaskBounds.width()).isGreaterThan(STABLE_BOUNDS.right)
assertThat(repositionTaskBounds.height()).isGreaterThan(STABLE_BOUNDS.bottom)
}
@@ -375,10 +440,12 @@
@Test
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_SIZE_CONSTRAINTS)
fun testChangeBoundsInDesktopMode_windowSizeExceedsStableBounds_shouldBeLimitedToDisplaySize() {
- doReturn(true).`when`{ DesktopModeStatus.canEnterDesktopMode(mockContext) }
+ doReturn(true).`when` { DesktopModeStatus.canEnterDesktopMode(mockContext) }
val startingPoint =
- PointF(OFF_CENTER_STARTING_BOUNDS.right.toFloat(),
- OFF_CENTER_STARTING_BOUNDS.bottom.toFloat())
+ PointF(
+ OFF_CENTER_STARTING_BOUNDS.right.toFloat(),
+ OFF_CENTER_STARTING_BOUNDS.bottom.toFloat()
+ )
val repositionTaskBounds = Rect(OFF_CENTER_STARTING_BOUNDS)
// Increase height and width by STABLE_BOUNDS. Subtract by 5px so that it doesn't reach
// the disallowed drag area.
@@ -387,9 +454,11 @@
val newY = STABLE_BOUNDS.bottom.toFloat() - offset
val delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint)
- DragPositioningCallbackUtility.changeBounds(CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM,
+ DragPositioningCallbackUtility.changeBounds(
+ CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM,
repositionTaskBounds, OFF_CENTER_STARTING_BOUNDS, STABLE_BOUNDS, delta,
- mockDisplayController, mockWindowDecoration)
+ mockDisplayController, mockWindowDecoration
+ )
assertThat(repositionTaskBounds.width()).isLessThan(STABLE_BOUNDS.right)
assertThat(repositionTaskBounds.height()).isLessThan(STABLE_BOUNDS.bottom)
}
@@ -423,7 +492,8 @@
DISPLAY_BOUNDS.left,
DISPLAY_BOUNDS.bottom - NAVBAR_HEIGHT,
DISPLAY_BOUNDS.right,
- DISPLAY_BOUNDS.bottom)
+ DISPLAY_BOUNDS.bottom
+ )
private val STABLE_BOUNDS = Rect(
DISPLAY_BOUNDS.left,
DISPLAY_BOUNDS.top,
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 2ce59ff..3a3e965 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
@@ -678,6 +678,7 @@
CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM)
val rectAfterDrag = Rect(STARTING_BOUNDS)
rectAfterDrag.right += 2000
+ rectAfterDrag.bottom = STABLE_BOUNDS_LANDSCAPE.bottom
// First drag; we should fetch stable bounds.
verify(mockDisplayLayout, Mockito.times(1)).getStableBounds(any())
verify(mockShellTaskOrganizer).applyTransaction(argThat { wct ->
@@ -705,8 +706,8 @@
STARTING_BOUNDS.right.toFloat(), STARTING_BOUNDS.bottom.toFloat(),
STARTING_BOUNDS.right.toFloat() + 2000, STARTING_BOUNDS.bottom.toFloat() + 2000,
CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM)
- rectAfterDrag.right -= 2000
- rectAfterDrag.bottom += 2000
+ rectAfterDrag.right = STABLE_BOUNDS_PORTRAIT.right
+ rectAfterDrag.bottom = STARTING_BOUNDS.bottom + 2000
verify(mockShellTaskOrganizer).applyTransaction(argThat { wct ->
return@argThat wct.changes.any { (token, change) ->
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 08a6e1b..6ae16ed 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
@@ -372,6 +372,7 @@
CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM)
val rectAfterDrag = Rect(STARTING_BOUNDS)
rectAfterDrag.right += 2000
+ rectAfterDrag.bottom = STABLE_BOUNDS_LANDSCAPE.bottom
// First drag; we should fetch stable bounds.
verify(mockDisplayLayout, times(1)).getStableBounds(any())
verify(mockTransitions).startTransition(eq(TRANSIT_CHANGE), argThat { wct ->
@@ -396,8 +397,8 @@
performDrag(STARTING_BOUNDS.right.toFloat(), STARTING_BOUNDS.bottom.toFloat(),
STARTING_BOUNDS.right.toFloat() + 2000, STARTING_BOUNDS.bottom.toFloat() + 2000,
CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM)
- rectAfterDrag.right -= 2000
- rectAfterDrag.bottom += 2000
+ rectAfterDrag.right = STABLE_BOUNDS_PORTRAIT.right
+ rectAfterDrag.bottom = STARTING_BOUNDS.bottom + 2000
verify(mockTransitions).startTransition(eq(TRANSIT_CHANGE), argThat { wct ->
return@argThat wct.changes.any { (token, change) ->
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index c36eda9..ca468fc 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -1027,7 +1027,7 @@
* <p>This method has no effect if the device implements a fixed volume policy
* as indicated by {@link #isVolumeFixed()}.
* <p>From N onward, ringer mode adjustments that would toggle Do Not Disturb are not allowed
- * unless the app has been granted Do Not Disturb Access.
+ * unless the app has been granted Notification Policy Access.
* See {@link NotificationManager#isNotificationPolicyAccessGranted()}.
*
* @param streamType The stream type to adjust. One of {@link #STREAM_VOICE_CALL},
@@ -1379,7 +1379,7 @@
* <p>This method has no effect if the device implements a fixed volume policy
* as indicated by {@link #isVolumeFixed()}.
* * <p>From N onward, ringer mode adjustments that would toggle Do Not Disturb are not allowed
- * unless the app has been granted Do Not Disturb Access.
+ * unless the app has been granted Notification Policy Access.
* See {@link NotificationManager#isNotificationPolicyAccessGranted()}.
* @param ringerMode The ringer mode, one of {@link #RINGER_MODE_NORMAL},
* {@link #RINGER_MODE_SILENT}, or {@link #RINGER_MODE_VIBRATE}.
@@ -1403,7 +1403,7 @@
* <p>This method has no effect if the device implements a fixed volume policy
* as indicated by {@link #isVolumeFixed()}.
* <p>From N onward, volume adjustments that would toggle Do Not Disturb are not allowed unless
- * the app has been granted Do Not Disturb Access.
+ * the app has been granted Notification Policy Access.
* See {@link NotificationManager#isNotificationPolicyAccessGranted()}.
* @param streamType The stream whose volume index should be set.
* @param index The volume index to set. See
@@ -8829,7 +8829,7 @@
* <p>This method has no effect if the device implements a fixed volume policy
* as indicated by {@link #isVolumeFixed()}.
* <p>From N onward, ringer mode adjustments that would toggle Do Not Disturb are not allowed
- * unless the app has been granted Do Not Disturb Access.
+ * unless the app has been granted Notification Policy Access.
* See {@link NotificationManager#isNotificationPolicyAccessGranted()}.
* <p>This API checks if the caller has the necessary permissions based on the provided
* component name, uid, and pid values.
@@ -8870,7 +8870,7 @@
* <p>This method has no effect if the device implements a fixed volume policy
* as indicated by {@link #isVolumeFixed()}.
* <p>From N onward, volume adjustments that would toggle Do Not Disturb are not allowed unless
- * the app has been granted Do Not Disturb Access.
+ * the app has been granted Notification Policy Access.
* See {@link NotificationManager#isNotificationPolicyAccessGranted()}.
* <p>This API checks if the caller has the necessary permissions based on the provided
* component name, uid, and pid values.
diff --git a/media/java/android/media/tv/ITvInputManager.aidl b/media/java/android/media/tv/ITvInputManager.aidl
index be93abb..87cb3e7 100644
--- a/media/java/android/media/tv/ITvInputManager.aidl
+++ b/media/java/android/media/tv/ITvInputManager.aidl
@@ -70,6 +70,7 @@
void releaseSession(in IBinder sessionToken, int userId);
int getClientPid(in String sessionId);
int getClientPriority(int useCase, in String sessionId);
+ int getClientUserId(in String sessionId);
void setMainSession(in IBinder sessionToken, int userId);
void setSurface(in IBinder sessionToken, in Surface surface, int userId);
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index aed3e60e..25b6bfa 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -760,6 +760,14 @@
* @hide
*/
public static final int UNKNOWN_CLIENT_PID = -1;
+ /**
+ * An unknown state of the client userId gets from the TvInputManager. Client gets this value
+ * when query through {@link #getClientUserId(String sessionId)} fails.
+ *
+ * @hide
+ */
+ @FlaggedApi(Flags.FLAG_KIDS_MODE_TVDB_SHARING)
+ public static final int UNKNOWN_CLIENT_USER_ID = -1;
/**
* Broadcast intent action when the user blocked content ratings change. For use with the
@@ -2510,6 +2518,21 @@
};
/**
+ * Get a the client user id when creating the session with the session id provided.
+ *
+ * @param sessionId a String of session id that is used to query the client user id.
+ * @return the client pid when created the session. Returns {@link #UNKNOWN_CLIENT_USER_ID}
+ * if the call fails.
+ *
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.TUNER_RESOURCE_ACCESS)
+ @FlaggedApi(Flags.FLAG_KIDS_MODE_TVDB_SHARING)
+ public int getClientUserId(@NonNull String sessionId) {
+ return getClientUserIdInternal(sessionId);
+ }
+
+ /**
* Returns a priority for the given use case type and the client's foreground or background
* status.
*
@@ -2599,6 +2622,18 @@
return clientPid;
}
+ @FlaggedApi(Flags.FLAG_KIDS_MODE_TVDB_SHARING)
+ private int getClientUserIdInternal(String sessionId) {
+ Preconditions.checkNotNull(sessionId);
+ int clientUserId = UNKNOWN_CLIENT_USER_ID;
+ try {
+ clientUserId = mService.getClientUserId(sessionId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ return clientUserId;
+ }
+
private int getClientPriorityInternal(int useCase, String sessionId) {
try {
return mService.getClientPriority(useCase, sessionId);
diff --git a/media/java/android/media/tv/flags/media_tv.aconfig b/media/java/android/media/tv/flags/media_tv.aconfig
index 3196ba1..d6e9e4e 100644
--- a/media/java/android/media/tv/flags/media_tv.aconfig
+++ b/media/java/android/media/tv/flags/media_tv.aconfig
@@ -31,4 +31,12 @@
namespace: "media_tv"
description: "Introduce ALWAYS_BOUND_TV_INPUT for TIS."
bug: "332201346"
+}
+
+flag {
+ name: "kids_mode_tvdb_sharing"
+ is_exported: true
+ namespace: "media_tv"
+ description: "Performance and Storage Optimization in Google TV Kids Mode."
+ bug: "288383796"
}
\ No newline at end of file
diff --git a/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenMode.java b/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenMode.java
index 69ef718..0d4ce5b 100644
--- a/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenMode.java
+++ b/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenMode.java
@@ -53,9 +53,11 @@
import com.android.settingslib.R;
import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableList;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
+import java.util.Comparator;
import java.util.Objects;
/**
@@ -88,6 +90,33 @@
.allowPriorityChannels(false)
.build();
+ private static final Comparator<Integer> PRIORITIZED_TYPE_COMPARATOR = new Comparator<>() {
+
+ private static final ImmutableList</* @AutomaticZenRule.Type */ Integer>
+ PRIORITIZED_TYPES = ImmutableList.of(
+ AutomaticZenRule.TYPE_BEDTIME,
+ AutomaticZenRule.TYPE_DRIVING);
+
+ @Override
+ public int compare(Integer first, Integer second) {
+ if (PRIORITIZED_TYPES.contains(first) && PRIORITIZED_TYPES.contains(second)) {
+ return PRIORITIZED_TYPES.indexOf(first) - PRIORITIZED_TYPES.indexOf(second);
+ } else if (PRIORITIZED_TYPES.contains(first)) {
+ return -1;
+ } else if (PRIORITIZED_TYPES.contains(second)) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+ };
+
+ // Manual DND first, Bedtime/Driving, then alphabetically.
+ static final Comparator<ZenMode> PRIORITIZING_COMPARATOR = Comparator
+ .comparing(ZenMode::isManualDnd).reversed()
+ .thenComparing(ZenMode::getType, PRIORITIZED_TYPE_COMPARATOR)
+ .thenComparing(ZenMode::getName);
+
public enum Status {
ENABLED,
ENABLED_AND_ACTIVE,
diff --git a/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenModesBackend.java b/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenModesBackend.java
index 64e503b32..c8a12f4 100644
--- a/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenModesBackend.java
+++ b/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenModesBackend.java
@@ -34,7 +34,6 @@
import java.time.Duration;
import java.util.ArrayList;
-import java.util.Comparator;
import java.util.List;
import java.util.Map;
@@ -92,10 +91,7 @@
}
}
- // Manual DND first, then alphabetically.
- modes.sort(Comparator.comparing(ZenMode::isManualDnd).reversed()
- .thenComparing(ZenMode::getName));
-
+ modes.sort(ZenMode.PRIORITIZING_COMPARATOR);
return modes;
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModeTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModeTest.java
index f464247..bab4bc3b 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModeTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModeTest.java
@@ -16,6 +16,12 @@
package com.android.settingslib.notification.modes;
+import static android.app.AutomaticZenRule.TYPE_BEDTIME;
+import static android.app.AutomaticZenRule.TYPE_DRIVING;
+import static android.app.AutomaticZenRule.TYPE_IMMERSIVE;
+import static android.app.AutomaticZenRule.TYPE_OTHER;
+import static android.app.AutomaticZenRule.TYPE_THEATER;
+import static android.app.AutomaticZenRule.TYPE_UNKNOWN;
import static android.app.NotificationManager.INTERRUPTION_FILTER_ALARMS;
import static android.app.NotificationManager.INTERRUPTION_FILTER_NONE;
import static android.app.NotificationManager.INTERRUPTION_FILTER_PRIORITY;
@@ -38,6 +44,9 @@
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
+import java.util.ArrayList;
+import java.util.List;
+
@RunWith(RobolectricTestRunner.class)
public class ZenModeTest {
@@ -46,7 +55,7 @@
private static final AutomaticZenRule ZEN_RULE =
new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
.setPackage("com.some.driving.thing")
- .setType(AutomaticZenRule.TYPE_DRIVING)
+ .setType(TYPE_DRIVING)
.setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
.setZenPolicy(ZEN_POLICY)
.build();
@@ -226,6 +235,28 @@
}
@Test
+ public void comparator_prioritizes() {
+ ZenMode manualDnd = TestModeBuilder.MANUAL_DND_INACTIVE;
+ ZenMode driving1 = new TestModeBuilder().setName("b1").setType(TYPE_DRIVING).build();
+ ZenMode driving2 = new TestModeBuilder().setName("b2").setType(TYPE_DRIVING).build();
+ ZenMode bedtime1 = new TestModeBuilder().setName("c1").setType(TYPE_BEDTIME).build();
+ ZenMode bedtime2 = new TestModeBuilder().setName("c2").setType(TYPE_BEDTIME).build();
+ ZenMode other = new TestModeBuilder().setName("a1").setType(TYPE_OTHER).build();
+ ZenMode immersive = new TestModeBuilder().setName("a2").setType(TYPE_IMMERSIVE).build();
+ ZenMode unknown = new TestModeBuilder().setName("a3").setType(TYPE_UNKNOWN).build();
+ ZenMode theater = new TestModeBuilder().setName("a4").setType(TYPE_THEATER).build();
+
+ ArrayList<ZenMode> list = new ArrayList<>(List.of(other, theater, bedtime1, unknown,
+ driving2, manualDnd, driving1, bedtime2, immersive));
+ list.sort(ZenMode.PRIORITIZING_COMPARATOR);
+
+ assertThat(list)
+ .containsExactly(manualDnd, bedtime1, bedtime2, driving1, driving2, other,
+ immersive, unknown, theater)
+ .inOrder();
+ }
+
+ @Test
public void writeToParcel_equals() {
assertUnparceledIsEqualToOriginal("example",
new ZenMode("id", ZEN_RULE, zenConfigRuleFor(ZEN_RULE, false)));
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 398c915..2e98c1f 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -376,6 +376,10 @@
<!-- Listen to (dis-)connection of external displays and enable / disable them. -->
<uses-permission android:name="android.permission.MANAGE_DISPLAYS" />
+ <!-- To be able to intercept meta key events, might need to be removed once b/358569822
+ is ready -->
+ <uses-permission android:name="android.permission.OVERRIDE_SYSTEM_KEY_BEHAVIOR_IN_FOCUSED_WINDOW" />
+
<protected-broadcast android:name="com.android.settingslib.action.REGISTER_SLICE_RECEIVER" />
<protected-broadcast android:name="com.android.settingslib.action.UNREGISTER_SLICE_RECEIVER" />
<protected-broadcast android:name="com.android.settings.flashlight.action.FLASHLIGHT_CHANGED" />
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig
index 047c097..476fd8b 100644
--- a/packages/SystemUI/aconfig/systemui.aconfig
+++ b/packages/SystemUI/aconfig/systemui.aconfig
@@ -541,6 +541,16 @@
}
flag {
+ name: "clipboard_image_timeout"
+ namespace: "systemui"
+ description: "Wait for clipboard image to load before showing UI"
+ bug: "359864629"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
name: "screenshot_action_dismiss_system_windows"
namespace: "systemui"
description: "Dismiss existing system windows when starting action from screenshot UI"
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PatternBouncer.kt b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PatternBouncer.kt
index 069113b..163b355 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PatternBouncer.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PatternBouncer.kt
@@ -511,7 +511,7 @@
private const val SELECTED_DOT_DIAMETER_DP = (DOT_DIAMETER_DP * 1.5).toInt()
private const val SELECTED_DOT_REACTION_ANIMATION_DURATION_MS = 83
private const val SELECTED_DOT_RETRACT_ANIMATION_DURATION_MS = 750
-private const val LINE_STROKE_WIDTH_DP = DOT_DIAMETER_DP
+private const val LINE_STROKE_WIDTH_DP = 22
private const val FAILURE_ANIMATION_DOT_DIAMETER_DP = (DOT_DIAMETER_DP * 0.81f).toInt()
private const val FAILURE_ANIMATION_DOT_SHRINK_ANIMATION_DURATION_MS = 50
private const val FAILURE_ANIMATION_DOT_SHRINK_STAGGER_DELAY_MS = 33
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt
index 7472d81..91a88bc 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt
@@ -170,7 +170,6 @@
import com.android.systemui.communal.ui.viewmodel.CommunalEditModeViewModel
import com.android.systemui.communal.ui.viewmodel.CommunalViewModel
import com.android.systemui.communal.util.DensityUtils.Companion.adjustedDp
-import com.android.systemui.communal.util.DensityUtils.Companion.scalingAdjustment
import com.android.systemui.communal.widgets.SmartspaceAppWidgetHostView
import com.android.systemui.communal.widgets.WidgetConfigurator
import com.android.systemui.res.R
@@ -478,8 +477,7 @@
}
val hubDimensions: Dimensions
- @Composable
- get() = Dimensions(LocalContext.current, LocalConfiguration.current, LocalDensity.current)
+ @Composable get() = Dimensions(LocalContext.current, LocalConfiguration.current)
@Composable
private fun DisclaimerBottomSheetContent(onButtonClicked: () -> Unit) {
@@ -1288,8 +1286,9 @@
modifier =
modifier
.background(
- MaterialTheme.colorScheme.surfaceVariant,
- RoundedCornerShape(dimensionResource(system_app_widget_background_radius))
+ color = MaterialTheme.colorScheme.surfaceVariant,
+ shape =
+ RoundedCornerShape(dimensionResource(system_app_widget_background_radius))
)
.clickable(
enabled = !viewModel.isEditMode,
@@ -1325,10 +1324,8 @@
Column(
modifier =
modifier.background(
- MaterialTheme.colorScheme.surfaceVariant,
- RoundedCornerShape(
- dimensionResource(system_app_widget_background_radius) * scalingAdjustment
- )
+ color = MaterialTheme.colorScheme.surfaceVariant,
+ shape = RoundedCornerShape(dimensionResource(system_app_widget_background_radius))
),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
@@ -1514,21 +1511,24 @@
fun toOffset(): Offset = Offset(start, top)
}
-class Dimensions(val context: Context, val config: Configuration, val density: Density) {
+class Dimensions(val context: Context, val config: Configuration) {
val GridTopSpacing: Dp
get() {
- if (config.orientation == Configuration.ORIENTATION_LANDSCAPE) {
- return 114.adjustedDp
- } else {
- val windowMetrics =
- WindowMetricsCalculator.getOrCreate().computeCurrentWindowMetrics(context)
- val screenHeight = with(density) { windowMetrics.bounds.height().adjustedDp }
-
- return (screenHeight - CardHeightFull) / 2
- }
+ val result =
+ if (config.orientation == Configuration.ORIENTATION_LANDSCAPE) {
+ 114.dp
+ } else {
+ val windowMetrics =
+ WindowMetricsCalculator.getOrCreate().computeCurrentWindowMetrics(context)
+ val density = context.resources.displayMetrics.density
+ val screenHeight = (windowMetrics.bounds.height() / density).dp
+ ((screenHeight - CardHeightFull) / 2)
+ }
+ return result
}
- val GridHeight = CardHeightFull + GridTopSpacing
+ val GridHeight: Dp
+ get() = CardHeightFull + GridTopSpacing
companion object {
val CardHeightFull
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/quickaffordance/shared/model/KeyguardPreviewConstants.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/quickaffordance/shared/model/KeyguardPreviewConstants.kt
index 08ee602..a3f40d4 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/quickaffordance/shared/model/KeyguardPreviewConstants.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/quickaffordance/shared/model/KeyguardPreviewConstants.kt
@@ -18,10 +18,17 @@
package com.android.systemui.shared.quickaffordance.shared.model
object KeyguardPreviewConstants {
+ const val MESSAGE_ID_DEFAULT_PREVIEW = 707
const val MESSAGE_ID_HIDE_SMART_SPACE = 1111
- const val KEY_HIDE_SMART_SPACE = "hide_smart_space"
+ const val MESSAGE_ID_PREVIEW_QUICK_AFFORDANCE_SELECTED = 1988
const val MESSAGE_ID_SLOT_SELECTED = 1337
- const val KEY_SLOT_ID = "slot_id"
- const val KEY_INITIALLY_SELECTED_SLOT_ID = "initially_selected_slot_id"
+ const val MESSAGE_ID_START_CUSTOMIZING_QUICK_AFFORDANCES = 214
+
+ const val KEY_HIDE_SMART_SPACE = "hide_smart_space"
const val KEY_HIGHLIGHT_QUICK_AFFORDANCES = "highlight_quick_affordances"
+ const val KEY_INITIALLY_SELECTED_SLOT_ID = "initially_selected_slot_id"
+ const val KEY_QUICK_AFFORDANCE_ID = "quick_affordance_id"
+ const val KEY_SLOT_ID = "slot_id"
+
+ const val KEYGUARD_QUICK_AFFORDANCE_ID_NONE = "none"
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerMessageViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerMessageViewModelTest.kt
index b83ab7e..c161525 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerMessageViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerMessageViewModelTest.kt
@@ -430,6 +430,22 @@
.isEqualTo("Can’t unlock with face. Too many attempts.")
}
+ @Test
+ fun startLockdownCountdown_onActivated() =
+ testScope.runTest {
+ val bouncerMessage by collectLastValue(underTest.message)
+ val lockoutSeconds = 200 * 1000 // 200 second lockout
+ kosmos.fakeAuthenticationRepository.setAuthenticationMethod(Pin)
+ kosmos.fakeAuthenticationRepository.reportLockoutStarted(lockoutSeconds)
+ runCurrent()
+
+ assertThat(bouncerMessage?.text).isEqualTo("Try again in 200 seconds.")
+ advanceTimeBy(100.seconds)
+ assertThat(bouncerMessage?.text).isEqualTo("Try again in 100 seconds.")
+ advanceTimeBy(101.seconds)
+ assertThat(bouncerMessage?.text).isEqualTo("Enter PIN")
+ }
+
private fun TestScope.verifyMessagesForAuthFlags(
vararg authFlagToMessagePair: Pair<Int, Pair<String, String?>>
) {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalSceneTransitionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalSceneTransitionInteractorTest.kt
index d6712f0..c5518b0 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalSceneTransitionInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalSceneTransitionInteractorTest.kt
@@ -53,6 +53,7 @@
import com.android.systemui.power.domain.interactor.powerInteractor
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
+import kotlin.time.Duration.Companion.seconds
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
@@ -78,6 +79,7 @@
private val underTest by lazy { kosmos.communalSceneTransitionInteractor }
private val keyguardTransitionRepository by lazy { kosmos.realKeyguardTransitionRepository }
+ private val keyguardRepository by lazy { kosmos.fakeKeyguardRepository }
private val ownerName = CommunalSceneTransitionInteractor::class.java.simpleName
private val progress = MutableSharedFlow<Float>()
@@ -789,4 +791,47 @@
)
)
}
+
+ /** Verifies that we correctly transition to GONE after keyguard goes away */
+ @Test
+ fun transition_to_blank_after_unlock_should_go_to_gone() =
+ testScope.runTest {
+ keyguardRepository.setKeyguardShowing(true)
+ sceneTransitions.value = Idle(CommunalScenes.Communal)
+
+ val currentStep by collectLastValue(keyguardTransitionRepository.transitions)
+
+ assertThat(currentStep)
+ .isEqualTo(
+ TransitionStep(
+ from = LOCKSCREEN,
+ to = GLANCEABLE_HUB,
+ transitionState = FINISHED,
+ value = 1f,
+ ownerName = ownerName,
+ )
+ )
+
+ // Keyguard starts exiting after a while, then fully exits after some time.
+ advanceTimeBy(1.seconds)
+ keyguardRepository.setKeyguardGoingAway(true)
+ advanceTimeBy(2.seconds)
+ keyguardRepository.setKeyguardGoingAway(false)
+ keyguardRepository.setKeyguardShowing(false)
+ runCurrent()
+
+ // We snap to the blank scene as a result of keyguard going away.
+ sceneTransitions.value = Idle(CommunalScenes.Blank)
+
+ assertThat(currentStep)
+ .isEqualTo(
+ TransitionStep(
+ from = GLANCEABLE_HUB,
+ to = GONE,
+ transitionState = FINISHED,
+ value = 1f,
+ ownerName = ownerName,
+ )
+ )
+ }
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepositoryTest.kt
index 8e109b4..c85cd66 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepositoryTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepositoryTest.kt
@@ -308,6 +308,15 @@
)
}
+ @Test
+ fun getConfig() =
+ testScope.runTest {
+ assertThat(underTest.getConfig(FakeCustomizationProviderClient.AFFORDANCE_1))
+ .isEqualTo(config1)
+ assertThat(underTest.getConfig(FakeCustomizationProviderClient.AFFORDANCE_2))
+ .isEqualTo(config2)
+ }
+
private fun assertSelections(
observed: Map<String, List<KeyguardQuickAffordanceConfig>>?,
expected: Map<String, List<KeyguardQuickAffordanceConfig>>,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt
index 75c0d3b..ad07c1c 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt
@@ -426,6 +426,64 @@
}
@Test
+ fun quickAffordanceAlwaysVisible_withNonNullOverrideKeyguardQuickAffordanceId() =
+ testScope.runTest {
+ quickAccessWallet.setState(
+ KeyguardQuickAffordanceConfig.LockScreenState.Visible(
+ icon = ICON,
+ activationState = ActivationState.Active,
+ )
+ )
+ homeControls.setState(
+ KeyguardQuickAffordanceConfig.LockScreenState.Visible(
+ icon = ICON,
+ activationState = ActivationState.Active,
+ )
+ )
+
+ // The default case
+ val collectedValue =
+ collectLastValue(
+ underTest.quickAffordanceAlwaysVisible(
+ KeyguardQuickAffordancePosition.BOTTOM_START,
+ )
+ )
+ assertThat(collectedValue())
+ .isInstanceOf(KeyguardQuickAffordanceModel.Visible::class.java)
+ val visibleModel = collectedValue() as KeyguardQuickAffordanceModel.Visible
+ assertThat(visibleModel.configKey)
+ .isEqualTo(
+ "${KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START}::${homeControls.key}"
+ )
+ assertThat(visibleModel.icon).isEqualTo(ICON)
+ assertThat(visibleModel.icon.contentDescription)
+ .isEqualTo(ContentDescription.Resource(res = CONTENT_DESCRIPTION_RESOURCE_ID))
+ assertThat(visibleModel.activationState).isEqualTo(ActivationState.Active)
+
+ // With override
+ val collectedValueWithOverride =
+ collectLastValue(
+ underTest.quickAffordanceAlwaysVisible(
+ position = KeyguardQuickAffordancePosition.BOTTOM_START,
+ overrideQuickAffordanceId =
+ BuiltInKeyguardQuickAffordanceKeys.QUICK_ACCESS_WALLET,
+ )
+ )
+ assertThat(collectedValueWithOverride())
+ .isInstanceOf(KeyguardQuickAffordanceModel.Visible::class.java)
+ val visibleModelWithOverride =
+ collectedValueWithOverride() as KeyguardQuickAffordanceModel.Visible
+ assertThat(visibleModelWithOverride.configKey)
+ .isEqualTo(
+ "${KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START}::${quickAccessWallet.key}"
+ )
+ assertThat(visibleModelWithOverride.icon).isEqualTo(ICON)
+ assertThat(visibleModelWithOverride.icon.contentDescription)
+ .isEqualTo(ContentDescription.Resource(res = CONTENT_DESCRIPTION_RESOURCE_ID))
+ assertThat(visibleModelWithOverride.activationState).isEqualTo(ActivationState.Active)
+ }
+
+ @Test
fun select() =
testScope.runTest {
overrideResource(
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt
index 9792c28..1bc2e24 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt
@@ -60,6 +60,7 @@
import com.android.systemui.shade.shadeTestUtil
import com.android.systemui.testKosmos
import com.android.systemui.util.mockito.whenever
+import kotlin.time.Duration.Companion.milliseconds
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.cancelChildren
import kotlinx.coroutines.flow.MutableStateFlow
@@ -2135,6 +2136,14 @@
@EnableFlags(FLAG_COMMUNAL_SCENE_KTF_REFACTOR)
fun glanceableHubToOccluded_communalKtfRefactor() =
testScope.runTest {
+ // GIVEN device is not dreaming
+ powerInteractor.setAwakeForTest()
+ keyguardRepository.setDreaming(false)
+ keyguardRepository.setDozeTransitionModel(
+ DozeTransitionModel(from = DozeStateModel.DOZE, to = DozeStateModel.FINISH)
+ )
+ advanceTimeBy(600.milliseconds)
+
// GIVEN a prior transition has run to GLANCEABLE_HUB
communalSceneInteractor.changeScene(CommunalScenes.Communal, "test")
runCurrent()
@@ -2298,6 +2307,54 @@
coroutineContext.cancelChildren()
}
+ @Test
+ @BrokenWithSceneContainer(339465026)
+ @EnableFlags(FLAG_COMMUNAL_SCENE_KTF_REFACTOR)
+ fun glanceableHubToOccludedDoesNotTriggerWhenDreamStateChanges_communalKtfRefactor() =
+ testScope.runTest {
+ // GIVEN that we are dreaming and not dozing
+ powerInteractor.setAwakeForTest()
+ keyguardRepository.setDreaming(true)
+ keyguardRepository.setKeyguardOccluded(true)
+ keyguardRepository.setDozeTransitionModel(
+ DozeTransitionModel(from = DozeStateModel.DOZE, to = DozeStateModel.FINISH)
+ )
+ advanceTimeBy(700.milliseconds)
+ clearInvocations(transitionRepository)
+
+ // GIVEN a prior transition has run to GLANCEABLE_HUB
+ communalSceneInteractor.changeScene(CommunalScenes.Communal, "test")
+ runCurrent()
+ assertThat(transitionRepository)
+ .startedTransition(
+ ownerName = CommunalSceneTransitionInteractor::class.simpleName,
+ from = KeyguardState.DREAMING,
+ to = KeyguardState.GLANCEABLE_HUB,
+ )
+ clearInvocations(transitionRepository)
+
+ // WHEN dream ends but we are still occluded
+ keyguardRepository.setDreaming(false)
+ runCurrent()
+ assertThat(transitionRepository).noTransitionsStarted()
+
+ // Simulate occlusion signal changing due to dream terminating and then occluding again
+ // due to a new activity starting a couple milliseconds later.
+ keyguardRepository.setKeyguardOccluded(false)
+ advanceTimeBy(10.milliseconds)
+ keyguardRepository.setKeyguardOccluded(true)
+ advanceTimeBy(200.milliseconds)
+
+ assertThat(transitionRepository)
+ .startedTransition(
+ ownerName = CommunalSceneTransitionInteractor::class.simpleName,
+ from = KeyguardState.GLANCEABLE_HUB,
+ to = KeyguardState.OCCLUDED,
+ )
+
+ coroutineContext.cancelChildren()
+ }
+
private suspend fun TestScope.runTransitionAndSetWakefulness(
from: KeyguardState,
to: KeyguardState
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/lifecycle/BaseActivatableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/lifecycle/BaseActivatableTest.kt
new file mode 100644
index 0000000..f6f58c9
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/lifecycle/BaseActivatableTest.kt
@@ -0,0 +1,328 @@
+/*
+ * 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.
+ */
+
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
+package com.android.systemui.lifecycle
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.testKosmos
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class BaseActivatableTest : SysuiTestCase() {
+
+ private val kosmos = testKosmos()
+ private val testScope = kosmos.testScope
+
+ private val underTest = FakeActivatable()
+
+ @Test
+ fun activate() =
+ testScope.runTest {
+ assertThat(underTest.isActive).isFalse()
+ assertThat(underTest.activationCount).isEqualTo(0)
+ assertThat(underTest.cancellationCount).isEqualTo(0)
+
+ underTest.activateIn(testScope)
+ runCurrent()
+ assertThat(underTest.isActive).isTrue()
+ assertThat(underTest.activationCount).isEqualTo(1)
+ assertThat(underTest.cancellationCount).isEqualTo(0)
+ }
+
+ @Test
+ fun activate_andCancel() =
+ testScope.runTest {
+ assertThat(underTest.isActive).isFalse()
+ assertThat(underTest.activationCount).isEqualTo(0)
+ assertThat(underTest.cancellationCount).isEqualTo(0)
+
+ val job = Job()
+ underTest.activateIn(testScope, context = job)
+ runCurrent()
+ assertThat(underTest.isActive).isTrue()
+ assertThat(underTest.activationCount).isEqualTo(1)
+ assertThat(underTest.cancellationCount).isEqualTo(0)
+
+ job.cancel()
+ runCurrent()
+ assertThat(underTest.isActive).isFalse()
+ assertThat(underTest.activationCount).isEqualTo(1)
+ assertThat(underTest.cancellationCount).isEqualTo(1)
+ }
+
+ @Test
+ fun activate_afterCancellation() =
+ testScope.runTest {
+ assertThat(underTest.isActive).isFalse()
+ assertThat(underTest.activationCount).isEqualTo(0)
+ assertThat(underTest.cancellationCount).isEqualTo(0)
+
+ val job = Job()
+ underTest.activateIn(testScope, context = job)
+ runCurrent()
+ assertThat(underTest.isActive).isTrue()
+ assertThat(underTest.activationCount).isEqualTo(1)
+ assertThat(underTest.cancellationCount).isEqualTo(0)
+
+ job.cancel()
+ runCurrent()
+ assertThat(underTest.isActive).isFalse()
+ assertThat(underTest.activationCount).isEqualTo(1)
+ assertThat(underTest.cancellationCount).isEqualTo(1)
+
+ underTest.activateIn(testScope)
+ runCurrent()
+ assertThat(underTest.isActive).isTrue()
+ assertThat(underTest.activationCount).isEqualTo(2)
+ assertThat(underTest.cancellationCount).isEqualTo(1)
+ }
+
+ @Test(expected = IllegalStateException::class)
+ fun activate_whileActive_throws() =
+ testScope.runTest {
+ assertThat(underTest.isActive).isFalse()
+ assertThat(underTest.activationCount).isEqualTo(0)
+ assertThat(underTest.cancellationCount).isEqualTo(0)
+
+ underTest.activateIn(testScope)
+ runCurrent()
+ assertThat(underTest.isActive).isTrue()
+ assertThat(underTest.activationCount).isEqualTo(1)
+ assertThat(underTest.cancellationCount).isEqualTo(0)
+
+ underTest.activateIn(testScope)
+ runCurrent()
+ }
+
+ @Test
+ fun addChild_beforeActive_activatesChildrenOnceActivated() =
+ testScope.runTest {
+ val child1 = FakeActivatable()
+ val child2 = FakeActivatable()
+ assertThat(child1.isActive).isFalse()
+ assertThat(child2.isActive).isFalse()
+
+ assertThat(underTest.isActive).isFalse()
+ underTest.addChild(child1)
+ underTest.addChild(child2)
+ assertThat(underTest.isActive).isFalse()
+ assertThat(child1.isActive).isFalse()
+ assertThat(child2.isActive).isFalse()
+
+ underTest.activateIn(this)
+ runCurrent()
+
+ assertThat(underTest.isActive).isTrue()
+ assertThat(child1.isActive).isTrue()
+ assertThat(child2.isActive).isTrue()
+ }
+
+ @Test
+ fun addChild_whileActive_activatesChildrenImmediately() =
+ testScope.runTest {
+ underTest.activateIn(this)
+ runCurrent()
+ assertThat(underTest.isActive).isTrue()
+
+ val child1 = FakeActivatable()
+ val child2 = FakeActivatable()
+ assertThat(child1.isActive).isFalse()
+ assertThat(child2.isActive).isFalse()
+
+ underTest.addChild(child1)
+ underTest.addChild(child2)
+ runCurrent()
+
+ assertThat(child1.isActive).isTrue()
+ assertThat(child2.isActive).isTrue()
+ }
+
+ @Test
+ fun addChild_afterCancellation_doesNotActivateChildren() =
+ testScope.runTest {
+ val job = Job()
+ underTest.activateIn(this, context = job)
+ runCurrent()
+ assertThat(underTest.isActive).isTrue()
+ job.cancel()
+ runCurrent()
+ assertThat(underTest.isActive).isFalse()
+
+ val child1 = FakeActivatable()
+ val child2 = FakeActivatable()
+ assertThat(child1.isActive).isFalse()
+ assertThat(child2.isActive).isFalse()
+
+ underTest.addChild(child1)
+ underTest.addChild(child2)
+ runCurrent()
+
+ assertThat(child1.isActive).isFalse()
+ assertThat(child2.isActive).isFalse()
+ }
+
+ @Test
+ fun activate_cancellation_cancelsCurrentChildren() =
+ testScope.runTest {
+ val job = Job()
+ underTest.activateIn(this, context = job)
+ runCurrent()
+ assertThat(underTest.isActive).isTrue()
+
+ val child1 = FakeActivatable()
+ val child2 = FakeActivatable()
+ assertThat(child1.isActive).isFalse()
+ assertThat(child2.isActive).isFalse()
+
+ underTest.addChild(child1)
+ underTest.addChild(child2)
+ runCurrent()
+
+ assertThat(child1.isActive).isTrue()
+ assertThat(child2.isActive).isTrue()
+
+ job.cancel()
+ runCurrent()
+ assertThat(underTest.isActive).isFalse()
+ assertThat(child1.isActive).isFalse()
+ assertThat(child2.isActive).isFalse()
+ }
+
+ @Test
+ fun activate_afterCancellation_reactivatesCurrentChildren() =
+ testScope.runTest {
+ val job = Job()
+ underTest.activateIn(this, context = job)
+ runCurrent()
+ assertThat(underTest.isActive).isTrue()
+
+ val child1 = FakeActivatable()
+ val child2 = FakeActivatable()
+ assertThat(child1.isActive).isFalse()
+ assertThat(child2.isActive).isFalse()
+
+ underTest.addChild(child1)
+ underTest.addChild(child2)
+ runCurrent()
+
+ assertThat(child1.isActive).isTrue()
+ assertThat(child2.isActive).isTrue()
+
+ job.cancel()
+ runCurrent()
+ assertThat(underTest.isActive).isFalse()
+ assertThat(child1.isActive).isFalse()
+ assertThat(child2.isActive).isFalse()
+
+ underTest.activateIn(this)
+ runCurrent()
+ assertThat(underTest.isActive).isTrue()
+ assertThat(child1.isActive).isTrue()
+ assertThat(child2.isActive).isTrue()
+ }
+
+ @Test
+ fun removeChild_beforeActive_neverActivatesChild() =
+ testScope.runTest {
+ val child1 = FakeActivatable()
+ val child2 = FakeActivatable()
+ assertThat(child1.isActive).isFalse()
+ assertThat(child2.isActive).isFalse()
+
+ assertThat(underTest.isActive).isFalse()
+ underTest.addChild(child1)
+ underTest.addChild(child2)
+ assertThat(underTest.isActive).isFalse()
+ assertThat(child1.isActive).isFalse()
+ assertThat(child2.isActive).isFalse()
+ }
+
+ @Test
+ fun removeChild_whileActive_cancelsChild() =
+ testScope.runTest {
+ val child1 = FakeActivatable()
+ val child2 = FakeActivatable()
+ assertThat(child1.isActive).isFalse()
+ assertThat(child2.isActive).isFalse()
+
+ assertThat(underTest.isActive).isFalse()
+ underTest.addChild(child1)
+ underTest.addChild(child2)
+ assertThat(underTest.isActive).isFalse()
+ assertThat(child1.isActive).isFalse()
+ assertThat(child2.isActive).isFalse()
+
+ underTest.activateIn(this)
+ runCurrent()
+ assertThat(underTest.isActive).isTrue()
+ assertThat(child1.isActive).isTrue()
+ assertThat(child2.isActive).isTrue()
+
+ underTest.removeChild(child1)
+ runCurrent()
+ assertThat(underTest.isActive).isTrue()
+ assertThat(child1.isActive).isFalse()
+ assertThat(child2.isActive).isTrue()
+ }
+
+ @Test
+ fun removeChild_afterCancellation_doesNotReactivateChildren() =
+ testScope.runTest {
+ val child1 = FakeActivatable()
+ val child2 = FakeActivatable()
+ assertThat(child1.isActive).isFalse()
+ assertThat(child2.isActive).isFalse()
+
+ assertThat(underTest.isActive).isFalse()
+ underTest.addChild(child1)
+ underTest.addChild(child2)
+ assertThat(underTest.isActive).isFalse()
+ assertThat(child1.isActive).isFalse()
+ assertThat(child2.isActive).isFalse()
+
+ val job = Job()
+ underTest.activateIn(this, context = job)
+ runCurrent()
+ assertThat(underTest.isActive).isTrue()
+ assertThat(child1.isActive).isTrue()
+ assertThat(child2.isActive).isTrue()
+
+ job.cancel()
+ runCurrent()
+ assertThat(underTest.isActive).isFalse()
+ assertThat(child1.isActive).isFalse()
+ assertThat(child2.isActive).isFalse()
+
+ underTest.removeChild(child1)
+ underTest.activateIn(this)
+ runCurrent()
+ assertThat(underTest.isActive).isTrue()
+ assertThat(child1.isActive).isFalse()
+ assertThat(child2.isActive).isTrue()
+ }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/lifecycle/SafeActivatableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/lifecycle/SafeActivatableTest.kt
deleted file mode 100644
index 9484821..0000000
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/lifecycle/SafeActivatableTest.kt
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * 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.
- */
-
-@file:OptIn(ExperimentalCoroutinesApi::class)
-
-package com.android.systemui.lifecycle
-
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SmallTest
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.kosmos.testScope
-import com.android.systemui.testKosmos
-import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.Job
-import kotlinx.coroutines.test.runCurrent
-import kotlinx.coroutines.test.runTest
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@SmallTest
-@RunWith(AndroidJUnit4::class)
-class SafeActivatableTest : SysuiTestCase() {
-
- private val kosmos = testKosmos()
- private val testScope = kosmos.testScope
-
- private val underTest = FakeActivatable()
-
- @Test
- fun activate() =
- testScope.runTest {
- assertThat(underTest.isActive).isFalse()
- assertThat(underTest.activationCount).isEqualTo(0)
- assertThat(underTest.cancellationCount).isEqualTo(0)
-
- underTest.activateIn(testScope)
- runCurrent()
- assertThat(underTest.isActive).isTrue()
- assertThat(underTest.activationCount).isEqualTo(1)
- assertThat(underTest.cancellationCount).isEqualTo(0)
- }
-
- @Test
- fun activate_andCancel() =
- testScope.runTest {
- assertThat(underTest.isActive).isFalse()
- assertThat(underTest.activationCount).isEqualTo(0)
- assertThat(underTest.cancellationCount).isEqualTo(0)
-
- val job = Job()
- underTest.activateIn(testScope, context = job)
- runCurrent()
- assertThat(underTest.isActive).isTrue()
- assertThat(underTest.activationCount).isEqualTo(1)
- assertThat(underTest.cancellationCount).isEqualTo(0)
-
- job.cancel()
- runCurrent()
- assertThat(underTest.isActive).isFalse()
- assertThat(underTest.activationCount).isEqualTo(1)
- assertThat(underTest.cancellationCount).isEqualTo(1)
- }
-
- @Test
- fun activate_afterCancellation() =
- testScope.runTest {
- assertThat(underTest.isActive).isFalse()
- assertThat(underTest.activationCount).isEqualTo(0)
- assertThat(underTest.cancellationCount).isEqualTo(0)
-
- val job = Job()
- underTest.activateIn(testScope, context = job)
- runCurrent()
- assertThat(underTest.isActive).isTrue()
- assertThat(underTest.activationCount).isEqualTo(1)
- assertThat(underTest.cancellationCount).isEqualTo(0)
-
- job.cancel()
- runCurrent()
- assertThat(underTest.isActive).isFalse()
- assertThat(underTest.activationCount).isEqualTo(1)
- assertThat(underTest.cancellationCount).isEqualTo(1)
-
- underTest.activateIn(testScope)
- runCurrent()
- assertThat(underTest.isActive).isTrue()
- assertThat(underTest.activationCount).isEqualTo(2)
- assertThat(underTest.cancellationCount).isEqualTo(1)
- }
-
- @Test(expected = IllegalStateException::class)
- fun activate_whileActive_throws() =
- testScope.runTest {
- assertThat(underTest.isActive).isFalse()
- assertThat(underTest.activationCount).isEqualTo(0)
- assertThat(underTest.cancellationCount).isEqualTo(0)
-
- underTest.activateIn(testScope)
- runCurrent()
- assertThat(underTest.isActive).isTrue()
- assertThat(underTest.activationCount).isEqualTo(1)
- assertThat(underTest.cancellationCount).isEqualTo(0)
-
- underTest.activateIn(testScope)
- runCurrent()
- }
-}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/compose/DragAndDropTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/compose/DragAndDropTest.kt
index 4d1dd1c..d9faa30 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/compose/DragAndDropTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/compose/DragAndDropTest.kt
@@ -32,6 +32,7 @@
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.onNodeWithText
import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.FlakyTest
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.common.shared.model.ContentDescription
@@ -45,6 +46,7 @@
import org.junit.Test
import org.junit.runner.RunWith
+@FlakyTest(bugId = 360351805)
@SmallTest
@RunWith(AndroidJUnit4::class)
class DragAndDropTest : SysuiTestCase() {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/custom/data/repository/CustomTileRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/custom/data/repository/CustomTileRepositoryTest.kt
index dfc004a..c9869bdb 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/custom/data/repository/CustomTileRepositoryTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/custom/data/repository/CustomTileRepositoryTest.kt
@@ -280,9 +280,12 @@
}
@Test
- fun isActiveFollowsPackageManagerAdapter() =
+ fun isActiveFollowsPackageManagerAdapter_user0() =
with(kosmos) {
testScope.runTest {
+ packageManagerAdapterFacade.setExclusiveForUser(0)
+
+ underTest.updateWithDefaults(UserHandle.of(0), TEST_DEFAULTS_1, true)
packageManagerAdapterFacade.setIsActive(false)
assertThat(underTest.isTileActive()).isFalse()
@@ -295,6 +298,7 @@
fun isToggleableFollowsPackageManagerAdapter() =
with(kosmos) {
testScope.runTest {
+ underTest.updateWithDefaults(UserHandle.of(0), TEST_DEFAULTS_1, true)
packageManagerAdapterFacade.setIsToggleable(false)
assertThat(underTest.isTileToggleable()).isFalse()
@@ -303,6 +307,66 @@
}
}
+ @Test
+ fun isActiveFollowsPackageManagerAdapter_user10_withAdapterForUser10() =
+ with(kosmos) {
+ testScope.runTest {
+ packageManagerAdapterFacade.setExclusiveForUser(10)
+
+ underTest.updateWithDefaults(UserHandle.of(10), TEST_DEFAULTS_1, true)
+ packageManagerAdapterFacade.setIsActive(false)
+ assertThat(underTest.isTileActive()).isFalse()
+
+ packageManagerAdapterFacade.setIsActive(true)
+ assertThat(underTest.isTileActive()).isTrue()
+ }
+ }
+
+ @Test
+ fun isToggleableFollowsPackageManagerAdapter_user10_withAdapterForUser10() =
+ with(kosmos) {
+ testScope.runTest {
+ packageManagerAdapterFacade.setExclusiveForUser(10)
+
+ underTest.updateWithDefaults(UserHandle.of(10), TEST_DEFAULTS_1, true)
+ packageManagerAdapterFacade.setIsToggleable(false)
+ assertThat(underTest.isTileToggleable()).isFalse()
+
+ packageManagerAdapterFacade.setIsToggleable(true)
+ assertThat(underTest.isTileToggleable()).isTrue()
+ }
+ }
+
+ @Test
+ fun isActiveDoesntFollowPackageManagerAdapter_user10() =
+ with(kosmos) {
+ testScope.runTest {
+ packageManagerAdapterFacade.setExclusiveForUser(0)
+
+ underTest.updateWithDefaults(UserHandle.of(10), TEST_DEFAULTS_1, true)
+ packageManagerAdapterFacade.setIsActive(false)
+ assertThat(underTest.isTileActive()).isFalse()
+
+ packageManagerAdapterFacade.setIsActive(true)
+ assertThat(underTest.isTileActive()).isFalse()
+ }
+ }
+
+ @Test
+ fun isToggleableDoesntFollowPackageManagerAdapter_user10() =
+ with(kosmos) {
+ testScope.runTest {
+ packageManagerAdapterFacade.setExclusiveForUser(0)
+
+ underTest.updateWithDefaults(UserHandle.of(10), TEST_DEFAULTS_1, true)
+ packageManagerAdapterFacade.setIsToggleable(false)
+ assertThat(underTest.isTileToggleable()).isFalse()
+
+ packageManagerAdapterFacade.setIsToggleable(true)
+ assertThat(underTest.isTileToggleable()).isFalse()
+ }
+ }
+
private companion object {
val TEST_COMPONENT = ComponentName("test.pkg", "test.cls")
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
index bbb467f..64a13de 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
@@ -28,9 +28,7 @@
import com.android.internal.logging.uiEventLoggerFake
import com.android.internal.policy.IKeyguardDismissCallback
import com.android.systemui.SysuiTestCase
-import com.android.systemui.authentication.data.repository.FakeAuthenticationRepository
import com.android.systemui.authentication.data.repository.fakeAuthenticationRepository
-import com.android.systemui.authentication.domain.interactor.authenticationInteractor
import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
import com.android.systemui.bouncer.data.repository.fakeKeyguardBouncerRepository
import com.android.systemui.bouncer.domain.interactor.bouncerInteractor
@@ -357,6 +355,7 @@
kosmos.fakeDeviceEntryFingerprintAuthRepository.setAuthenticationStatus(
SuccessFingerprintAuthenticationStatus(0, true)
)
+ runCurrent()
assertThat(currentSceneKey).isEqualTo(Scenes.QuickSettings)
assertThat(alternateBouncerVisible).isFalse()
@@ -507,6 +506,33 @@
}
@Test
+ fun hideAlternateBouncerAndNotifyDismissCancelledWhenDeviceSleeps() =
+ testScope.runTest {
+ val alternateBouncerVisible by
+ collectLastValue(bouncerRepository.alternateBouncerVisible)
+ val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
+ prepareState(
+ isDeviceUnlocked = false,
+ initialSceneKey = Scenes.Shade,
+ )
+ assertThat(currentSceneKey).isEqualTo(Scenes.Shade)
+ bouncerRepository.setAlternateVisible(true)
+ underTest.start()
+
+ // run all pending dismiss succeeded/cancelled calls from setup:
+ kosmos.fakeExecutor.runAllReady()
+
+ val dismissCallback: IKeyguardDismissCallback = mock()
+ kosmos.dismissCallbackRegistry.addCallback(dismissCallback)
+ powerInteractor.setAsleepForTest()
+ runCurrent()
+ kosmos.fakeExecutor.runAllReady()
+
+ assertThat(alternateBouncerVisible).isFalse()
+ verify(dismissCallback).onDismissCancelled()
+ }
+
+ @Test
fun switchToLockscreenWhenDeviceSleepsLocked() =
testScope.runTest {
val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
@@ -1644,19 +1670,27 @@
}
@Test
- fun notifyKeyguardDismissCallbacks_whenUnlocking_onDismissSucceeded() =
+ fun notifyKeyguardDismissCallbacks_whenUnlockingFromBouncer_onDismissSucceeded() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
- prepareState()
+ val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
+ prepareState(
+ authenticationMethod = AuthenticationMethodModel.Pin,
+ isDeviceUnlocked = false,
+ initialSceneKey = Scenes.Bouncer,
+ )
+ assertThat(currentSceneKey).isEqualTo(Scenes.Bouncer)
underTest.start()
+
+ // run all pending dismiss succeeded/cancelled calls from setup:
+ kosmos.fakeExecutor.runAllReady()
+
val dismissCallback: IKeyguardDismissCallback = mock()
kosmos.dismissCallbackRegistry.addCallback(dismissCallback)
- // Switch to bouncer and unlock device:
- sceneInteractor.changeScene(Scenes.Bouncer, "")
- assertThat(currentScene).isEqualTo(Scenes.Bouncer)
- kosmos.authenticationInteractor.authenticate(FakeAuthenticationRepository.DEFAULT_PIN)
- assertThat(currentScene).isEqualTo(Scenes.Gone)
+ kosmos.fakeDeviceEntryFingerprintAuthRepository.setAuthenticationStatus(
+ SuccessFingerprintAuthenticationStatus(0, true)
+ )
+ runCurrent()
kosmos.fakeExecutor.runAllReady()
verify(dismissCallback).onDismissSucceeded()
@@ -1665,19 +1699,26 @@
@Test
fun notifyKeyguardDismissCallbacks_whenLeavingBouncer_onDismissCancelled() =
testScope.runTest {
+ val isUnlocked by collectLastValue(kosmos.deviceEntryInteractor.isUnlocked)
val currentScene by collectLastValue(sceneInteractor.currentScene)
prepareState()
underTest.start()
+
+ // run all pending dismiss succeeded/cancelled calls from setup:
+ kosmos.fakeExecutor.runAllReady()
+
val dismissCallback: IKeyguardDismissCallback = mock()
kosmos.dismissCallbackRegistry.addCallback(dismissCallback)
// Switch to bouncer:
sceneInteractor.changeScene(Scenes.Bouncer, "")
assertThat(currentScene).isEqualTo(Scenes.Bouncer)
+ runCurrent()
- // Return to lockscreen:
+ // Return to lockscreen when isUnlocked=false:
sceneInteractor.changeScene(Scenes.Lockscreen, "")
assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
+ assertThat(isUnlocked).isFalse()
runCurrent()
kosmos.fakeExecutor.runAllReady()
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index f8303ea..8a2e767 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -756,6 +756,8 @@
<string name="quick_settings_bluetooth_audio_sharing_button">Share audio</string>
<!-- QuickSettings: Bluetooth dialog audio sharing button text when sharing audio [CHAR LIMIT=50]-->
<string name="quick_settings_bluetooth_audio_sharing_button_sharing">Sharing audio</string>
+ <!-- QuickSettings: Bluetooth dialog audio sharing button text accessibility label. Used as part of the string "Double tap to enter audio sharing settings". [CHAR LIMIT=50]-->
+ <string name="quick_settings_bluetooth_audio_sharing_button_accessibility">enter audio sharing settings</string>
<!-- QuickSettings: Bluetooth secondary label for the battery level of a connected device [CHAR LIMIT=20]-->
<string name="quick_settings_bluetooth_secondary_label_battery_level"><xliff:g id="battery_level_as_percentage">%s</xliff:g> battery</string>
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuController.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuController.java
index f4a1f05..e4b7b7e 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuController.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuController.java
@@ -37,6 +37,7 @@
import com.android.systemui.accessibility.AccessibilityButtonModeObserver.AccessibilityButtonMode;
import com.android.systemui.accessibility.AccessibilityButtonTargetsObserver;
import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.navigationbar.NavigationModeController;
import com.android.systemui.settings.DisplayTracker;
import com.android.systemui.util.settings.SecureSettings;
@@ -61,6 +62,7 @@
private final SecureSettings mSecureSettings;
private final DisplayTracker mDisplayTracker;
+ private final NavigationModeController mNavigationModeController;
@VisibleForTesting
IAccessibilityFloatingMenu mFloatingMenu;
private int mBtnMode;
@@ -106,7 +108,8 @@
AccessibilityButtonModeObserver accessibilityButtonModeObserver,
KeyguardUpdateMonitor keyguardUpdateMonitor,
SecureSettings secureSettings,
- DisplayTracker displayTracker) {
+ DisplayTracker displayTracker,
+ NavigationModeController navigationModeController) {
mContext = context;
mWindowManager = windowManager;
mViewCaptureAwareWindowManager = viewCaptureAwareWindowManager;
@@ -117,6 +120,7 @@
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mSecureSettings = secureSettings;
mDisplayTracker = displayTracker;
+ mNavigationModeController = navigationModeController;
mIsKeyguardVisible = false;
}
@@ -191,7 +195,8 @@
final Context windowContext = mContext.createWindowContext(defaultDisplay,
TYPE_NAVIGATION_BAR_PANEL, /* options= */ null);
mFloatingMenu = new MenuViewLayerController(windowContext, mWindowManager,
- mViewCaptureAwareWindowManager, mAccessibilityManager, mSecureSettings);
+ mViewCaptureAwareWindowManager, mAccessibilityManager, mSecureSettings,
+ mNavigationModeController);
}
mFloatingMenu.show();
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayer.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayer.java
index f4b6bfb..d62162b 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayer.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayer.java
@@ -77,6 +77,7 @@
import com.android.internal.messages.nano.SystemMessageProto;
import com.android.internal.util.Preconditions;
import com.android.systemui.Flags;
+import com.android.systemui.navigationbar.NavigationModeController;
import com.android.systemui.res.R;
import com.android.systemui.util.settings.SecureSettings;
import com.android.wm.shell.bubbles.DismissViewUtils;
@@ -142,6 +143,8 @@
private boolean mIsNotificationShown;
private Optional<MenuEduTooltipView> mEduTooltipView = Optional.empty();
private BroadcastReceiver mNotificationActionReceiver;
+ private NavigationModeController mNavigationModeController;
+ private NavigationModeController.ModeChangedListener mNavigationModeChangedListender;
@IntDef({
LayerIndex.MENU_VIEW,
@@ -220,7 +223,8 @@
MenuViewModel menuViewModel,
MenuViewAppearance menuViewAppearance, MenuView menuView,
IAccessibilityFloatingMenu floatingMenu,
- SecureSettings secureSettings) {
+ SecureSettings secureSettings,
+ NavigationModeController navigationModeController) {
super(context);
// Simplifies the translation positioning and animations
@@ -253,6 +257,8 @@
mNotificationFactory = new MenuNotificationFactory(context);
mNotificationManager = context.getSystemService(NotificationManager.class);
mStatusBarManager = context.getSystemService(StatusBarManager.class);
+ mNavigationModeController = navigationModeController;
+ mNavigationModeChangedListender = (mode -> mMenuView.onPositionChanged());
if (Flags.floatingMenuDragToEdit()) {
mDragToInteractAnimationController = new DragToInteractAnimationController(
@@ -381,6 +387,7 @@
mMigrationTooltipObserver);
mMessageView.setUndoListener(view -> undo());
getContext().registerComponentCallbacks(this);
+ mNavigationModeController.addListener(mNavigationModeChangedListender);
}
@Override
@@ -396,6 +403,7 @@
mMigrationTooltipObserver);
mHandler.removeCallbacksAndMessages(/* token= */ null);
getContext().unregisterComponentCallbacks(this);
+ mNavigationModeController.removeListener(mNavigationModeChangedListender);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerController.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerController.java
index 623536f..cb96e78 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerController.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerController.java
@@ -24,6 +24,7 @@
import android.view.accessibility.AccessibilityManager;
import com.android.app.viewcapture.ViewCaptureAwareWindowManager;
+import com.android.systemui.navigationbar.NavigationModeController;
import com.android.systemui.util.settings.SecureSettings;
/**
@@ -37,7 +38,8 @@
MenuViewLayerController(Context context, WindowManager windowManager,
ViewCaptureAwareWindowManager viewCaptureAwareWindowManager,
- AccessibilityManager accessibilityManager, SecureSettings secureSettings) {
+ AccessibilityManager accessibilityManager, SecureSettings secureSettings,
+ NavigationModeController navigationModeController) {
mWindowManager = viewCaptureAwareWindowManager;
MenuViewModel menuViewModel = new MenuViewModel(
@@ -49,7 +51,8 @@
menuViewAppearance,
new MenuView(context, menuViewModel, menuViewAppearance, secureSettings),
this,
- secureSettings);
+ secureSettings,
+ navigationModeController);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistDisclosure.java b/packages/SystemUI/src/com/android/systemui/assist/AssistDisclosure.java
index a5c5bec..f4e2b82 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistDisclosure.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistDisclosure.java
@@ -33,6 +33,7 @@
import android.view.accessibility.AccessibilityEvent;
import com.android.app.animation.Interpolators;
+import com.android.app.viewcapture.ViewCaptureAwareWindowManager;
import com.android.systemui.res.R;
/**
@@ -40,16 +41,17 @@
*/
public class AssistDisclosure {
private final Context mContext;
- private final WindowManager mWm;
+ private final ViewCaptureAwareWindowManager mWm;
private final Handler mHandler;
private AssistDisclosureView mView;
private boolean mViewAdded;
- public AssistDisclosure(Context context, Handler handler) {
+ public AssistDisclosure(Context context, Handler handler,
+ ViewCaptureAwareWindowManager viewCaptureAwareWindowManager) {
mContext = context;
mHandler = handler;
- mWm = mContext.getSystemService(WindowManager.class);
+ mWm = viewCaptureAwareWindowManager;
}
public void postShow() {
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
index a67dcdb..939d96e 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
@@ -25,6 +25,7 @@
import android.service.voice.VoiceInteractionSession;
import android.util.Log;
+import com.android.app.viewcapture.ViewCaptureAwareWindowManager;
import com.android.internal.app.AssistUtils;
import com.android.internal.app.IVisualQueryDetectionAttentionListener;
import com.android.internal.app.IVisualQueryRecognitionStatusListener;
@@ -195,12 +196,13 @@
SecureSettings secureSettings,
SelectedUserInteractor selectedUserInteractor,
ActivityManager activityManager,
- AssistInteractor interactor) {
+ AssistInteractor interactor,
+ ViewCaptureAwareWindowManager viewCaptureAwareWindowManager) {
mContext = context;
mDeviceProvisionedController = controller;
mCommandQueue = commandQueue;
mAssistUtils = assistUtils;
- mAssistDisclosure = new AssistDisclosure(context, uiHandler);
+ mAssistDisclosure = new AssistDisclosure(context, uiHandler, viewCaptureAwareWindowManager);
mOverviewProxyService = overviewProxyService;
mPhoneStateMonitor = phoneStateMonitor;
mAssistLogger = assistLogger;
diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothDeviceMetadataInteractor.kt b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothDeviceMetadataInteractor.kt
new file mode 100644
index 0000000..d69e416
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothDeviceMetadataInteractor.kt
@@ -0,0 +1,91 @@
+/*
+ * 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.bluetooth.qsdialog
+
+import android.bluetooth.BluetoothAdapter
+import android.bluetooth.BluetoothDevice
+import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow
+import java.util.concurrent.Executor
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.distinctUntilChangedBy
+import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.flowOn
+import kotlinx.coroutines.flow.merge
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SysUISingleton
+class BluetoothDeviceMetadataInteractor
+@Inject
+constructor(
+ deviceItemInteractor: DeviceItemInteractor,
+ private val bluetoothAdapter: BluetoothAdapter?,
+ private val logger: BluetoothTileDialogLogger,
+ @Background private val executor: Executor,
+ @Background private val backgroundDispatcher: CoroutineDispatcher,
+) {
+ private fun metadataUpdateForDevice(bluetoothDevice: BluetoothDevice): Flow<Unit> =
+ conflatedCallbackFlow {
+ val metadataChangedListener =
+ BluetoothAdapter.OnMetadataChangedListener { device, key, value ->
+ when (key) {
+ BluetoothDevice.METADATA_UNTETHERED_LEFT_BATTERY,
+ BluetoothDevice.METADATA_UNTETHERED_RIGHT_BATTERY,
+ BluetoothDevice.METADATA_UNTETHERED_CASE_BATTERY,
+ BluetoothDevice.METADATA_MAIN_BATTERY -> {
+ trySendWithFailureLogging(Unit, TAG, "onMetadataChanged")
+ logger.logBatteryChanged(device.address, key, value)
+ }
+ }
+ }
+ bluetoothAdapter?.addOnMetadataChangedListener(
+ bluetoothDevice,
+ executor,
+ metadataChangedListener
+ )
+ awaitClose {
+ bluetoothAdapter?.removeOnMetadataChangedListener(
+ bluetoothDevice,
+ metadataChangedListener
+ )
+ }
+ }
+
+ val metadataUpdate: Flow<Unit> =
+ deviceItemInteractor.deviceItemUpdate
+ .distinctUntilChangedBy { it.bluetoothDevices }
+ .flatMapLatest { items ->
+ items.bluetoothDevices.map { device -> metadataUpdateForDevice(device) }.merge()
+ }
+ .flowOn(backgroundDispatcher)
+
+ private companion object {
+ private const val TAG = "BluetoothDeviceMetadataInteractor"
+ private val List<DeviceItem>.bluetoothDevices: Set<BluetoothDevice>
+ get() =
+ flatMapTo(mutableSetOf()) { item ->
+ listOf(item.cachedBluetoothDevice.device) +
+ item.cachedBluetoothDevice.memberDevice.map { it.device }
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogDelegate.kt b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogDelegate.kt
index 2808dbe..7deea73 100644
--- a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogDelegate.kt
+++ b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogDelegate.kt
@@ -129,8 +129,26 @@
getPairNewDeviceButton(dialog).setOnClickListener {
bluetoothTileDialogCallback.onPairNewDeviceClicked(it)
}
- getAudioSharingButtonView(dialog).setOnClickListener {
- bluetoothTileDialogCallback.onAudioSharingButtonClicked(it)
+ getAudioSharingButtonView(dialog).apply {
+ setOnClickListener { bluetoothTileDialogCallback.onAudioSharingButtonClicked(it) }
+ accessibilityDelegate =
+ object : AccessibilityDelegate() {
+ override fun onInitializeAccessibilityNodeInfo(
+ host: View,
+ info: AccessibilityNodeInfo
+ ) {
+ super.onInitializeAccessibilityNodeInfo(host, info)
+ info.addAction(
+ AccessibilityAction(
+ AccessibilityAction.ACTION_CLICK.id,
+ context.getString(
+ R.string
+ .quick_settings_bluetooth_audio_sharing_button_accessibility
+ )
+ )
+ )
+ }
+ }
}
getScrollViewContent(dialog).apply {
minimumHeight =
@@ -445,7 +463,6 @@
internal companion object {
const val MIN_HEIGHT_CHANGE_INTERVAL_MS = 800L
- const val MAX_DEVICE_ITEM_ENTRY = 3
const val ACTION_BLUETOOTH_DEVICE_DETAILS =
"com.android.settings.BLUETOOTH_DEVICE_DETAIL_SETTINGS"
const val ACTION_PREVIOUSLY_CONNECTED_DEVICE =
diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogLogger.kt b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogLogger.kt
index 72312b8..06116f0 100644
--- a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogLogger.kt
@@ -90,6 +90,18 @@
{ "ProfileConnectionStateChanged. address=$str1 state=$str2 profileId=$int1" }
)
+ fun logBatteryChanged(address: String, key: Int, value: ByteArray?) =
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ {
+ str1 = address
+ int1 = key
+ str2 = value?.toString() ?: ""
+ },
+ { "BatteryChanged. address=$str1 key=$int1 value=$str2" }
+ )
+
fun logDeviceFetch(status: JobStatus, trigger: DeviceFetchTrigger, duration: Long) =
logBuffer.log(
TAG,
diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogRepository.kt b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogRepository.kt
index 6e51915..56b79d1 100644
--- a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogRepository.kt
@@ -24,7 +24,7 @@
/** Repository to get CachedBluetoothDevices for the Bluetooth Dialog. */
@SysUISingleton
-internal class BluetoothTileDialogRepository
+class BluetoothTileDialogRepository
@Inject
constructor(
private val localBluetoothManager: LocalBluetoothManager?,
diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogViewModel.kt b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogViewModel.kt
index 985b158..8b2449a 100644
--- a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogViewModel.kt
@@ -37,7 +37,6 @@
import com.android.systemui.bluetooth.qsdialog.BluetoothTileDialogDelegate.Companion.ACTION_BLUETOOTH_DEVICE_DETAILS
import com.android.systemui.bluetooth.qsdialog.BluetoothTileDialogDelegate.Companion.ACTION_PAIR_NEW_DEVICE
import com.android.systemui.bluetooth.qsdialog.BluetoothTileDialogDelegate.Companion.ACTION_PREVIOUSLY_CONNECTED_DEVICE
-import com.android.systemui.bluetooth.qsdialog.BluetoothTileDialogDelegate.Companion.MAX_DEVICE_ITEM_ENTRY
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Background
@@ -50,8 +49,10 @@
import kotlinx.coroutines.Job
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.channels.produce
+import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@@ -66,6 +67,7 @@
private val bluetoothStateInteractor: BluetoothStateInteractor,
private val bluetoothAutoOnInteractor: BluetoothAutoOnInteractor,
private val audioSharingInteractor: AudioSharingInteractor,
+ private val bluetoothDeviceMetadataInteractor: BluetoothDeviceMetadataInteractor,
private val dialogTransitionAnimator: DialogTransitionAnimator,
private val activityStarter: ActivityStarter,
private val uiEventLogger: UiEventLogger,
@@ -112,15 +114,17 @@
// deviceItemUpdate is emitted when device item list is done fetching, update UI and
// stop the progress bar.
- deviceItemInteractor.deviceItemUpdate
- .onEach {
+ combine(
+ deviceItemInteractor.deviceItemUpdate,
+ deviceItemInteractor.showSeeAllUpdate
+ ) { deviceItem, showSeeAll ->
updateDialogUiJob?.cancel()
updateDialogUiJob = launch {
dialogDelegate.apply {
onDeviceItemUpdated(
dialog,
- it.take(MAX_DEVICE_ITEM_ENTRY),
- showSeeAll = it.size > MAX_DEVICE_ITEM_ENTRY,
+ deviceItem,
+ showSeeAll,
showPairNewDevice =
bluetoothStateInteractor.isBluetoothEnabled()
)
@@ -131,8 +135,11 @@
.launchIn(this)
// deviceItemUpdateRequest is emitted when a bluetooth callback is called, re-fetch
- // the device item list and animiate the progress bar.
- deviceItemInteractor.deviceItemUpdateRequest
+ // the device item list and animate the progress bar.
+ merge(
+ deviceItemInteractor.deviceItemUpdateRequest,
+ bluetoothDeviceMetadataInteractor.metadataUpdate
+ )
.onEach {
dialogDelegate.animateProgressBar(dialog, true)
updateDeviceItemJob?.cancel()
diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItemFactory.kt b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItemFactory.kt
index d7893db..e846bf7 100644
--- a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItemFactory.kt
+++ b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItemFactory.kt
@@ -38,7 +38,7 @@
R.string.accessibility_quick_settings_bluetooth_device_tap_to_disconnect
/** Factories to create different types of Bluetooth device items from CachedBluetoothDevice. */
-internal abstract class DeviceItemFactory {
+abstract class DeviceItemFactory {
abstract fun isFilterMatched(
context: Context,
cachedDevice: CachedBluetoothDevice,
@@ -136,7 +136,7 @@
}
}
-internal open class AvailableMediaDeviceItemFactory : DeviceItemFactory() {
+open class AvailableMediaDeviceItemFactory : DeviceItemFactory() {
override fun isFilterMatched(
context: Context,
cachedDevice: CachedBluetoothDevice,
diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItemInteractor.kt b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItemInteractor.kt
index 1526cd9..9524496 100644
--- a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItemInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItemInteractor.kt
@@ -34,16 +34,18 @@
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.MutableSharedFlow
+import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.asSharedFlow
+import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.shareIn
import kotlinx.coroutines.isActive
import kotlinx.coroutines.withContext
/** Holds business logic for the Bluetooth Dialog after clicking on the Bluetooth QS tile. */
@SysUISingleton
-internal class DeviceItemInteractor
+class DeviceItemInteractor
@Inject
constructor(
private val bluetoothTileDialogRepository: BluetoothTileDialogRepository,
@@ -58,9 +60,13 @@
private val mutableDeviceItemUpdate: MutableSharedFlow<List<DeviceItem>> =
MutableSharedFlow(extraBufferCapacity = 1)
- internal val deviceItemUpdate
+ val deviceItemUpdate
get() = mutableDeviceItemUpdate.asSharedFlow()
+ private val mutableShowSeeAllUpdate: MutableStateFlow<Boolean> = MutableStateFlow(false)
+ internal val showSeeAllUpdate
+ get() = mutableShowSeeAllUpdate.asStateFlow()
+
internal val deviceItemUpdateRequest: SharedFlow<Unit> =
conflatedCallbackFlow {
val listener =
@@ -139,7 +145,8 @@
.sort(displayPriority, bluetoothAdapter?.mostRecentlyConnectedDevices)
// Only emit when the job is not cancelled
if (isActive) {
- mutableDeviceItemUpdate.tryEmit(deviceItems)
+ mutableDeviceItemUpdate.tryEmit(deviceItems.take(MAX_DEVICE_ITEM_ENTRY))
+ mutableShowSeeAllUpdate.tryEmit(deviceItems.size > MAX_DEVICE_ITEM_ENTRY)
logger.logDeviceFetch(
JobStatus.FINISHED,
trigger,
@@ -177,5 +184,6 @@
companion object {
private const val TAG = "DeviceItemInteractor"
+ private const val MAX_DEVICE_ITEM_ENTRY = 3
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerMessageViewModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerMessageViewModel.kt
index d746220..cfd4f50 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerMessageViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerMessageViewModel.kt
@@ -264,6 +264,9 @@
// Keeps the lockout message up-to-date.
launch { bouncerInteractor.onLockoutStarted.collect { startLockoutCountdown() } }
+ // Start already active lockdown if it exists
+ launch { startLockoutCountdown() }
+
// Listens to relevant bouncer events
launch {
bouncerInteractor.onIncorrectBouncerInput
diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java
index 04c6fa9..040af90 100644
--- a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java
+++ b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java
@@ -19,6 +19,7 @@
import static android.content.Intent.ACTION_CLOSE_SYSTEM_DIALOGS;
import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.CLIPBOARD_OVERLAY_SHOW_ACTIONS;
+import static com.android.systemui.Flags.clipboardImageTimeout;
import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_ACTION_SHOWN;
import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_ACTION_TAPPED;
import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_DISMISSED_OTHER;
@@ -32,7 +33,6 @@
import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_SWIPE_DISMISSED;
import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_TAP_OUTSIDE;
import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_TIMED_OUT;
-import static com.android.systemui.flags.Flags.CLIPBOARD_IMAGE_TIMEOUT;
import static com.android.systemui.flags.Flags.CLIPBOARD_SHARED_TRANSITIONS;
import android.animation.Animator;
@@ -288,7 +288,7 @@
boolean shouldAnimate = !model.dataMatches(mClipboardModel) || wasExiting;
mClipboardModel = model;
mClipboardLogger.setClipSource(mClipboardModel.getSource());
- if (mFeatureFlags.isEnabled(CLIPBOARD_IMAGE_TIMEOUT)) {
+ if (clipboardImageTimeout()) {
if (shouldAnimate) {
reset();
mClipboardLogger.setClipSource(mClipboardModel.getSource());
@@ -452,7 +452,7 @@
mClipboardLogger.logUnguarded(CLIPBOARD_OVERLAY_EXPANDED_FROM_MINIMIZED);
mIsMinimized = false;
}
- if (mFeatureFlags.isEnabled(CLIPBOARD_IMAGE_TIMEOUT)) {
+ if (clipboardImageTimeout()) {
setExpandedView(() -> animateIn());
} else {
setExpandedView();
@@ -522,7 +522,7 @@
mInputMonitor.getInputChannel(), Looper.getMainLooper()) {
@Override
public void onInputEvent(InputEvent event) {
- if ((!mFeatureFlags.isEnabled(CLIPBOARD_IMAGE_TIMEOUT) || mShowingUi)
+ if ((!clipboardImageTimeout() || mShowingUi)
&& event instanceof MotionEvent) {
MotionEvent motionEvent = (MotionEvent) event;
if (motionEvent.getActionMasked() == MotionEvent.ACTION_DOWN) {
diff --git a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalSceneTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalSceneTransitionInteractor.kt
index c780aac..6343752 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalSceneTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalSceneTransitionInteractor.kt
@@ -41,6 +41,8 @@
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.filterNotNull
+import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
@@ -85,25 +87,29 @@
*/
private val nextKeyguardStateInternal =
combine(
- keyguardInteractor.isAbleToDream,
- keyguardInteractor.isKeyguardOccluded,
- keyguardInteractor.isKeyguardGoingAway,
- ) { dreaming, occluded, keyguardGoingAway ->
- if (keyguardGoingAway) {
- KeyguardState.GONE
- } else if (occluded && !dreaming) {
- KeyguardState.OCCLUDED
- } else if (dreaming) {
- KeyguardState.DREAMING
- } else {
- KeyguardState.LOCKSCREEN
+ keyguardInteractor.isAbleToDream,
+ keyguardInteractor.isKeyguardOccluded,
+ keyguardInteractor.isKeyguardGoingAway,
+ keyguardInteractor.isKeyguardShowing,
+ ) { dreaming, occluded, keyguardGoingAway, keyguardShowing ->
+ if (keyguardGoingAway) {
+ KeyguardState.GONE
+ } else if (occluded && !dreaming) {
+ KeyguardState.OCCLUDED
+ } else if (dreaming) {
+ KeyguardState.DREAMING
+ } else if (keyguardShowing) {
+ KeyguardState.LOCKSCREEN
+ } else {
+ null
+ }
}
- }
+ .filterNotNull()
private val nextKeyguardState: StateFlow<KeyguardState> =
combine(
repository.nextLockscreenTargetState,
- nextKeyguardStateInternal,
+ nextKeyguardStateInternal.onStart { emit(KeyguardState.LOCKSCREEN) },
) { override, nextState ->
override ?: nextState
}
diff --git a/packages/SystemUI/src/com/android/systemui/display/domain/interactor/ConnectedDisplayInteractor.kt b/packages/SystemUI/src/com/android/systemui/display/domain/interactor/ConnectedDisplayInteractor.kt
index e4b290d..15a3cbd 100644
--- a/packages/SystemUI/src/com/android/systemui/display/domain/interactor/ConnectedDisplayInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/display/domain/interactor/ConnectedDisplayInteractor.kt
@@ -17,7 +17,6 @@
package com.android.systemui.display.domain.interactor
import android.companion.virtual.VirtualDeviceManager
-import android.companion.virtual.flags.Flags
import android.view.Display
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Background
@@ -155,8 +154,7 @@
}
private fun isVirtualDeviceOwnedMirrorDisplay(display: Display): Boolean {
- return Flags.interactiveScreenMirror() &&
- virtualDeviceManager != null &&
+ return virtualDeviceManager != null &&
virtualDeviceManager.isVirtualDeviceOwnedMirrorDisplay(display.displayId)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/data/model/TutorialSchedulerInfo.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/data/model/TutorialSchedulerInfo.kt
index 9f46846..1dbe83a 100644
--- a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/data/model/TutorialSchedulerInfo.kt
+++ b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/data/model/TutorialSchedulerInfo.kt
@@ -16,7 +16,23 @@
package com.android.systemui.inputdevice.tutorial.data.model
-data class DeviceSchedulerInfo(var isLaunched: Boolean = false, var connectTime: Long? = null) {
+import java.time.Instant
+
+data class DeviceSchedulerInfo(
+ var launchTime: Instant? = null,
+ var firstConnectionTime: Instant? = null
+) {
+ constructor(
+ launchTimeSec: Long?,
+ firstConnectionTimeSec: Long?
+ ) : this(
+ launchTimeSec?.let { Instant.ofEpochSecond(it) },
+ firstConnectionTimeSec?.let { Instant.ofEpochSecond(it) }
+ )
+
val wasEverConnected: Boolean
- get() = connectTime != null
+ get() = firstConnectionTime != null
+
+ val isLaunched: Boolean
+ get() = launchTime != null
}
diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/data/repository/TutorialSchedulerRepository.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/data/repository/TutorialSchedulerRepository.kt
index 36b9ac7..d8d4bd6 100644
--- a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/data/repository/TutorialSchedulerRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/data/repository/TutorialSchedulerRepository.kt
@@ -20,7 +20,6 @@
import androidx.annotation.VisibleForTesting
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
-import androidx.datastore.preferences.core.booleanPreferencesKey
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.longPreferencesKey
import androidx.datastore.preferences.preferencesDataStore
@@ -28,6 +27,7 @@
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.inputdevice.tutorial.data.model.DeviceSchedulerInfo
+import java.time.Instant
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.first
@@ -43,28 +43,31 @@
constructor(
@Application applicationContext: Context,
@Background backgroundScope: CoroutineScope
- ) : this(applicationContext, backgroundScope, dataStoreName = "TutorialScheduler")
+ ) : this(applicationContext, backgroundScope, dataStoreName = DATASTORE_NAME)
private val Context.dataStore: DataStore<Preferences> by
preferencesDataStore(name = dataStoreName, scope = backgroundScope)
suspend fun isLaunched(deviceType: DeviceType): Boolean = loadData()[deviceType]!!.isLaunched
+ suspend fun launchTime(deviceType: DeviceType): Instant? = loadData()[deviceType]!!.launchTime
+
suspend fun wasEverConnected(deviceType: DeviceType): Boolean =
loadData()[deviceType]!!.wasEverConnected
- suspend fun connectTime(deviceType: DeviceType): Long = loadData()[deviceType]!!.connectTime!!
+ suspend fun firstConnectionTime(deviceType: DeviceType): Instant? =
+ loadData()[deviceType]!!.firstConnectionTime
private suspend fun loadData(): Map<DeviceType, DeviceSchedulerInfo> {
return applicationContext.dataStore.data.map { pref -> getSchedulerInfo(pref) }.first()
}
- suspend fun updateConnectTime(device: DeviceType, time: Long) {
- applicationContext.dataStore.edit { pref -> pref[getConnectKey(device)] = time }
+ suspend fun updateFirstConnectionTime(device: DeviceType, time: Instant) {
+ applicationContext.dataStore.edit { pref -> pref[getConnectKey(device)] = time.epochSecond }
}
- suspend fun updateLaunch(device: DeviceType) {
- applicationContext.dataStore.edit { pref -> pref[getLaunchedKey(device)] = true }
+ suspend fun updateLaunchTime(device: DeviceType, time: Instant) {
+ applicationContext.dataStore.edit { pref -> pref[getLaunchKey(device)] = time.epochSecond }
}
private fun getSchedulerInfo(pref: Preferences): Map<DeviceType, DeviceSchedulerInfo> {
@@ -75,13 +78,13 @@
}
private fun getDeviceSchedulerInfo(pref: Preferences, device: DeviceType): DeviceSchedulerInfo {
- val isLaunched = pref[getLaunchedKey(device)] ?: false
- val connectionTime = pref[getConnectKey(device)] ?: null
- return DeviceSchedulerInfo(isLaunched, connectionTime)
+ val launchTime = pref[getLaunchKey(device)]
+ val connectionTime = pref[getConnectKey(device)]
+ return DeviceSchedulerInfo(launchTime, connectionTime)
}
- private fun getLaunchedKey(device: DeviceType) =
- booleanPreferencesKey(device.name + IS_LAUNCHED_SUFFIX)
+ private fun getLaunchKey(device: DeviceType) =
+ longPreferencesKey(device.name + LAUNCH_TIME_SUFFIX)
private fun getConnectKey(device: DeviceType) =
longPreferencesKey(device.name + CONNECT_TIME_SUFFIX)
@@ -92,8 +95,9 @@
}
companion object {
- const val IS_LAUNCHED_SUFFIX = "_IS_LAUNCHED"
- const val CONNECT_TIME_SUFFIX = "_CONNECTED_TIME"
+ const val DATASTORE_NAME = "TutorialScheduler"
+ const val LAUNCH_TIME_SUFFIX = "_LAUNCH_TIME"
+ const val CONNECT_TIME_SUFFIX = "_CONNECT_TIME"
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialSchedulerInteractor.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialSchedulerInteractor.kt
index b3b8f21..a8d7dad 100644
--- a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialSchedulerInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialSchedulerInteractor.kt
@@ -26,9 +26,11 @@
import com.android.systemui.inputdevice.tutorial.data.repository.TutorialSchedulerRepository
import com.android.systemui.keyboard.data.repository.KeyboardRepository
import com.android.systemui.touchpad.data.repository.TouchpadRepository
+import java.time.Duration
import java.time.Instant
import javax.inject.Inject
import kotlin.time.Duration.Companion.hours
+import kotlin.time.toKotlinDuration
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.filter
@@ -84,9 +86,9 @@
private suspend fun schedule(deviceType: DeviceType) {
if (!repo.wasEverConnected(deviceType)) {
waitForDeviceConnection(deviceType)
- repo.updateConnectTime(deviceType, Instant.now().toEpochMilli())
+ repo.updateFirstConnectionTime(deviceType, Instant.now())
}
- delay(remainingTimeMillis(start = repo.connectTime(deviceType)))
+ delay(remainingTime(start = repo.firstConnectionTime(deviceType)!!))
waitForDeviceConnection(deviceType)
}
@@ -95,9 +97,9 @@
private suspend fun launchTutorial(tutorialType: TutorialType) {
if (tutorialType == TutorialType.KEYBOARD || tutorialType == TutorialType.BOTH)
- repo.updateLaunch(KEYBOARD)
+ repo.updateLaunchTime(KEYBOARD, Instant.now())
if (tutorialType == TutorialType.TOUCHPAD || tutorialType == TutorialType.BOTH)
- repo.updateLaunch(TOUCHPAD)
+ repo.updateLaunchTime(TOUCHPAD, Instant.now())
// TODO: launch tutorial
Log.d(TAG, "Launch tutorial for $tutorialType")
}
@@ -113,19 +115,21 @@
return if (deviceType == KEYBOARD) TutorialType.KEYBOARD else TutorialType.TOUCHPAD
}
- private fun remainingTimeMillis(start: Long): Long {
- val elapsed = Instant.now().toEpochMilli() - start
- return LAUNCH_DELAY - elapsed
+ private fun remainingTime(start: Instant): kotlin.time.Duration {
+ val elapsed = Duration.between(start, Instant.now())
+ return LAUNCH_DELAY.minus(elapsed).toKotlinDuration()
}
companion object {
const val TAG = "TutorialSchedulerInteractor"
- private val DEFAULT_LAUNCH_DELAY = 72.hours.inWholeMilliseconds
- private val LAUNCH_DELAY: Long
+ private val DEFAULT_LAUNCH_DELAY_SEC = 72.hours.inWholeSeconds
+ private val LAUNCH_DELAY: Duration
get() =
- SystemProperties.getLong(
- "persist.peripheral_tutorial_delay_ms",
- DEFAULT_LAUNCH_DELAY
+ Duration.ofSeconds(
+ SystemProperties.getLong(
+ "persist.peripheral_tutorial_delay_sec",
+ DEFAULT_LAUNCH_DELAY_SEC
+ )
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/NewPickerUiKeyguardPreview.kt b/packages/SystemUI/src/com/android/systemui/keyguard/NewPickerUiKeyguardPreview.kt
new file mode 100644
index 0000000..7e09a10
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/NewPickerUiKeyguardPreview.kt
@@ -0,0 +1,29 @@
+/*
+ * 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.keyguard
+
+import com.android.systemui.Flags
+
+/** Helper for reading or using the new picker UI flag. */
+@Suppress("NOTHING_TO_INLINE")
+object NewPickerUiKeyguardPreview {
+
+ /** Is the new picker UI enabled */
+ @JvmStatic
+ inline val isEnabled
+ get() = Flags.newPickerUi()
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepository.kt
index 698328e..d49550e 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepository.kt
@@ -22,7 +22,6 @@
import android.os.UserHandle
import android.util.LayoutDirection
import com.android.systemui.Dumpable
-import com.android.systemui.res.R
import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
import com.android.systemui.common.coroutine.ConflatedCallbackFlow
import com.android.systemui.dagger.SysUISingleton
@@ -35,6 +34,7 @@
import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceSelectionManager
import com.android.systemui.keyguard.shared.model.KeyguardQuickAffordancePickerRepresentation
import com.android.systemui.keyguard.shared.model.KeyguardSlotPickerRepresentation
+import com.android.systemui.res.R
import com.android.systemui.settings.UserTracker
import java.io.PrintWriter
import javax.inject.Inject
@@ -61,10 +61,13 @@
private val remoteUserSelectionManager: KeyguardQuickAffordanceRemoteUserSelectionManager,
private val userTracker: UserTracker,
legacySettingSyncer: KeyguardQuickAffordanceLegacySettingSyncer,
- private val configs: Set<@JvmSuppressWildcards KeyguardQuickAffordanceConfig>,
+ configs: Set<@JvmSuppressWildcards KeyguardQuickAffordanceConfig>,
dumpManager: DumpManager,
userHandle: UserHandle,
) {
+ // Configs for all keyguard quick affordances, mapped by the quick affordance ID as key
+ private val configsByAffordanceId: Map<String, KeyguardQuickAffordanceConfig> =
+ configs.associateBy { it.key }
private val userId: Flow<Int> =
ConflatedCallbackFlow.conflatedCallbackFlow {
val callback =
@@ -126,7 +129,7 @@
*/
fun getCurrentSelections(slotId: String): List<KeyguardQuickAffordanceConfig> {
val selections = selectionManager.value.getSelections().getOrDefault(slotId, emptyList())
- return configs.filter { selections.contains(it.key) }
+ return configsByAffordanceId.values.filter { selections.contains(it.key) }
}
/**
@@ -159,7 +162,7 @@
*/
suspend fun getAffordancePickerRepresentations():
List<KeyguardQuickAffordancePickerRepresentation> {
- return configs
+ return configsByAffordanceId.values
.associateWith { config -> config.getPickerScreenState() }
.filterNot { (_, pickerState) ->
pickerState is KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice
@@ -226,6 +229,11 @@
}
}
+ /** Get the config of a quick affordance. */
+ fun getConfig(quickAffordanceId: String): KeyguardQuickAffordanceConfig? {
+ return configsByAffordanceId[quickAffordanceId]
+ }
+
private inner class Dumpster : Dumpable {
override fun dump(pw: PrintWriter, args: Array<out String>) {
val slotPickerRepresentations = getSlotPickerRepresentations()
@@ -246,7 +254,7 @@
pw.println(" $slotId$selectionText (capacity = $capacity)")
}
pw.println("Available affordances on device:")
- configs.forEach { config ->
+ configsByAffordanceId.values.forEach { config ->
pw.println(" ${config.key} (\"${config.pickerName()}\")")
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGlanceableHubTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGlanceableHubTransitionInteractor.kt
index 0aa50e0..199caa1 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGlanceableHubTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGlanceableHubTransitionInteractor.kt
@@ -37,16 +37,21 @@
import com.android.systemui.util.kotlin.BooleanFlowOperators.allOf
import com.android.systemui.util.kotlin.BooleanFlowOperators.noneOf
import com.android.systemui.util.kotlin.BooleanFlowOperators.not
+import com.android.systemui.util.kotlin.Utils.Companion.sampleFilter
import com.android.systemui.util.kotlin.sample
import javax.inject.Inject
import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.Duration.Companion.seconds
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.flow.collectLatest
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.debounce
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
+@OptIn(FlowPreview::class)
@SysUISingleton
class FromGlanceableHubTransitionInteractor
@Inject
@@ -196,19 +201,26 @@
}
} else if (communalSceneKtfRefactor()) {
scope.launch {
- allOf(
+ combine(
keyguardInteractor.isKeyguardOccluded,
- noneOf(
- // Dream is a special-case of occluded, so filter out the dreaming
- // case here.
- keyguardInteractor.isDreaming,
- // When launching activities from widgets on the hub, we have a
- // custom occlusion animation.
- communalSceneInteractor.isLaunchingWidget,
- ),
+ keyguardInteractor.isAbleToDream
+ // Debounce the dreaming signal since there is a race condition between
+ // the occluded and dreaming signals. We therefore add a small delay
+ // to give enough time for occluded to flip to false when the dream
+ // ends, to avoid transitioning to OCCLUDED erroneously when exiting
+ // the dream.
+ .debounce(100.milliseconds),
+ ::Pair
)
- .filterRelevantKeyguardStateAnd { isOccludedAndNotDreamingNorLaunchingWidget ->
- isOccludedAndNotDreamingNorLaunchingWidget
+ .sampleFilter(
+ // When launching activities from widgets on the hub, we have a
+ // custom occlusion animation.
+ communalSceneInteractor.isLaunchingWidget,
+ ) { launchingWidget ->
+ !launchingWidget
+ }
+ .filterRelevantKeyguardStateAnd { (isOccluded, isDreaming) ->
+ isOccluded && !isDreaming
}
.collect { _ ->
communalSceneInteractor.changeScene(
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractor.kt
index 1c445a7..7801c00 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractor.kt
@@ -17,15 +17,16 @@
package com.android.systemui.keyguard.domain.interactor
+import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor
import com.android.systemui.keyguard.data.repository.KeyguardRepository
import com.android.systemui.keyguard.shared.model.DismissAction
import com.android.systemui.keyguard.shared.model.KeyguardDone
-import com.android.systemui.keyguard.shared.model.KeyguardState.ALTERNATE_BOUNCER
import com.android.systemui.keyguard.shared.model.KeyguardState.GONE
import com.android.systemui.keyguard.shared.model.KeyguardState.PRIMARY_BOUNCER
+import com.android.systemui.power.domain.interactor.PowerInteractor
import com.android.systemui.scene.domain.interactor.SceneInteractor
import com.android.systemui.scene.domain.resolver.NotifShadeSceneFamilyResolver
import com.android.systemui.scene.domain.resolver.QuickSettingsSceneFamilyResolver
@@ -61,6 +62,8 @@
deviceEntryInteractor: DeviceEntryInteractor,
quickSettingsSceneFamilyResolver: QuickSettingsSceneFamilyResolver,
notifShadeSceneFamilyResolver: NotifShadeSceneFamilyResolver,
+ powerInteractor: PowerInteractor,
+ alternateBouncerInteractor: AlternateBouncerInteractor,
) {
val dismissAction: Flow<DismissAction> = repository.dismissAction
@@ -124,10 +127,12 @@
scene = Scenes.Bouncer,
stateWithoutSceneContainer = PRIMARY_BOUNCER
),
- transitionInteractor.isFinishedIn(state = ALTERNATE_BOUNCER),
+ alternateBouncerInteractor.isVisible,
isOnShadeWhileUnlocked,
- ) { isOnGone, isOnBouncer, isOnAltBouncer, isOnShadeWhileUnlocked ->
- !isOnGone && !isOnBouncer && !isOnAltBouncer && !isOnShadeWhileUnlocked
+ powerInteractor.isAsleep,
+ ) { isOnGone, isOnBouncer, isOnAltBouncer, isOnShadeWhileUnlocked, isAsleep ->
+ (!isOnGone && !isOnBouncer && !isOnAltBouncer && !isOnShadeWhileUnlocked) ||
+ isAsleep
}
.filter { it }
.sampleFilter(dismissAction) { it !is DismissAction.None }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt
index 0682d87..2af95f2 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt
@@ -53,6 +53,7 @@
import com.android.systemui.settings.UserTracker
import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.shared.customization.data.content.CustomizationProviderContract as Contract
+import com.android.systemui.shared.quickaffordance.shared.model.KeyguardPreviewConstants.KEYGUARD_QUICK_AFFORDANCE_ID_NONE
import com.android.systemui.statusbar.phone.SystemUIDialog
import com.android.systemui.statusbar.policy.KeyguardStateController
import dagger.Lazy
@@ -142,14 +143,18 @@
*
* This is useful for experiences like the lock screen preview mode, where the affordances must
* always be visible.
+ *
+ * @param overrideQuickAffordanceId If null, return the currently-set quick affordance;
+ * otherwise, override and return the correspondent [KeyguardQuickAffordanceModel].
*/
suspend fun quickAffordanceAlwaysVisible(
position: KeyguardQuickAffordancePosition,
+ overrideQuickAffordanceId: String? = null,
): Flow<KeyguardQuickAffordanceModel> {
return if (isFeatureDisabledByDevicePolicy()) {
flowOf(KeyguardQuickAffordanceModel.Hidden)
} else {
- quickAffordanceInternal(position)
+ quickAffordanceInternal(position, overrideQuickAffordanceId)
}
}
@@ -299,12 +304,24 @@
}
private fun quickAffordanceInternal(
- position: KeyguardQuickAffordancePosition
+ position: KeyguardQuickAffordancePosition,
+ overrideAffordanceId: String? = null,
): Flow<KeyguardQuickAffordanceModel> =
repository
.get()
.selections
- .map { it[position.toSlotId()] ?: emptyList() }
+ .map { selections ->
+ val overrideQuickAffordanceConfigs =
+ overrideAffordanceId?.let {
+ if (it == KEYGUARD_QUICK_AFFORDANCE_ID_NONE) {
+ emptyList()
+ } else {
+ val config = repository.get().getConfig(it)
+ listOfNotNull(config)
+ }
+ }
+ overrideQuickAffordanceConfigs ?: selections[position.toSlotId()] ?: emptyList()
+ }
.flatMapLatest { configs -> combinedConfigs(position, configs) }
private fun combinedConfigs(
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/quickaffordance/KeyguardQuickAffordancePosition.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/quickaffordance/KeyguardQuickAffordancePosition.kt
index 2581b59..1bbe843 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/shared/quickaffordance/KeyguardQuickAffordancePosition.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/quickaffordance/KeyguardQuickAffordancePosition.kt
@@ -16,7 +16,8 @@
package com.android.systemui.keyguard.shared.quickaffordance
-import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots
+import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END
+import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START
/** Enumerates all possible positions for quick affordances that can appear on the lock-screen. */
enum class KeyguardQuickAffordancePosition {
@@ -25,8 +26,19 @@
fun toSlotId(): String {
return when (this) {
- BOTTOM_START -> KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START
- BOTTOM_END -> KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END
+ BOTTOM_START -> SLOT_ID_BOTTOM_START
+ BOTTOM_END -> SLOT_ID_BOTTOM_END
}
}
+
+ companion object {
+
+ /** If the slot ID does not match any string, return null. */
+ fun parseKeyguardQuickAffordancePosition(slotId: String): KeyguardQuickAffordancePosition? =
+ when (slotId) {
+ SLOT_ID_BOTTOM_START -> BOTTOM_START
+ SLOT_ID_BOTTOM_END -> BOTTOM_END
+ else -> null
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt
index 6031ef6..51ce355 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt
@@ -275,6 +275,15 @@
}
}
+ fun onStartCustomizingQuickAffordances(
+ initiallySelectedSlotId: String?,
+ ) {
+ quickAffordancesCombinedViewModel.enablePreviewMode(
+ initiallySelectedSlotId = initiallySelectedSlotId,
+ shouldHighlightSelectedAffordance = true,
+ )
+ }
+
fun onSlotSelected(slotId: String) {
if (KeyguardBottomAreaRefactor.isEnabled) {
quickAffordancesCombinedViewModel.onPreviewSlotSelected(slotId = slotId)
@@ -283,6 +292,21 @@
}
}
+ fun onPreviewQuickAffordanceSelected(slotId: String, quickAffordanceId: String) {
+ quickAffordancesCombinedViewModel.onPreviewQuickAffordanceSelected(
+ slotId,
+ quickAffordanceId,
+ )
+ }
+
+ fun onDefaultPreview() {
+ quickAffordancesCombinedViewModel.onClearPreviewQuickAffordances()
+ quickAffordancesCombinedViewModel.enablePreviewMode(
+ initiallySelectedSlotId = null,
+ shouldHighlightSelectedAffordance = false,
+ )
+ }
+
fun destroy() {
isDestroyed = true
lockscreenSmartspaceController.disconnect()
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardRemotePreviewManager.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardRemotePreviewManager.kt
index 0532ee2..a6108c4 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardRemotePreviewManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardRemotePreviewManager.kt
@@ -31,7 +31,16 @@
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
-import com.android.systemui.shared.quickaffordance.shared.model.KeyguardPreviewConstants
+import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START
+import com.android.systemui.shared.quickaffordance.shared.model.KeyguardPreviewConstants.KEY_HIDE_SMART_SPACE
+import com.android.systemui.shared.quickaffordance.shared.model.KeyguardPreviewConstants.KEY_INITIALLY_SELECTED_SLOT_ID
+import com.android.systemui.shared.quickaffordance.shared.model.KeyguardPreviewConstants.KEY_QUICK_AFFORDANCE_ID
+import com.android.systemui.shared.quickaffordance.shared.model.KeyguardPreviewConstants.KEY_SLOT_ID
+import com.android.systemui.shared.quickaffordance.shared.model.KeyguardPreviewConstants.MESSAGE_ID_DEFAULT_PREVIEW
+import com.android.systemui.shared.quickaffordance.shared.model.KeyguardPreviewConstants.MESSAGE_ID_HIDE_SMART_SPACE
+import com.android.systemui.shared.quickaffordance.shared.model.KeyguardPreviewConstants.MESSAGE_ID_PREVIEW_QUICK_AFFORDANCE_SELECTED
+import com.android.systemui.shared.quickaffordance.shared.model.KeyguardPreviewConstants.MESSAGE_ID_SLOT_SELECTED
+import com.android.systemui.shared.quickaffordance.shared.model.KeyguardPreviewConstants.MESSAGE_ID_START_CUSTOMIZING_QUICK_AFFORDANCES
import com.android.systemui.util.kotlin.logD
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
@@ -59,7 +68,7 @@
return try {
val renderer =
if (Flags.lockscreenPreviewRendererCreateOnMainThread()) {
- runBlocking ("$TAG#previewRendererFactory.create", mainDispatcher) {
+ runBlocking("$TAG#previewRendererFactory.create", mainDispatcher) {
previewRendererFactory.create(request)
}
} else {
@@ -157,16 +166,35 @@
}
when (message.what) {
- KeyguardPreviewConstants.MESSAGE_ID_SLOT_SELECTED -> {
- message.data.getString(KeyguardPreviewConstants.KEY_SLOT_ID)?.let { slotId ->
+ MESSAGE_ID_START_CUSTOMIZING_QUICK_AFFORDANCES -> {
+ checkNotNull(renderer)
+ .onStartCustomizingQuickAffordances(
+ initiallySelectedSlotId =
+ message.data.getString(KEY_INITIALLY_SELECTED_SLOT_ID)
+ ?: SLOT_ID_BOTTOM_START
+ )
+ }
+ MESSAGE_ID_SLOT_SELECTED -> {
+ message.data.getString(KEY_SLOT_ID)?.let { slotId ->
checkNotNull(renderer).onSlotSelected(slotId = slotId)
}
}
- KeyguardPreviewConstants.MESSAGE_ID_HIDE_SMART_SPACE -> {
- checkNotNull(renderer)
- .hideSmartspace(
- message.data.getBoolean(KeyguardPreviewConstants.KEY_HIDE_SMART_SPACE)
- )
+ MESSAGE_ID_PREVIEW_QUICK_AFFORDANCE_SELECTED -> {
+ val slotId = message.data.getString(KEY_SLOT_ID)
+ val quickAffordanceId = message.data.getString(KEY_QUICK_AFFORDANCE_ID)
+ if (slotId != null && quickAffordanceId != null) {
+ checkNotNull(renderer)
+ .onPreviewQuickAffordanceSelected(
+ slotId = slotId,
+ quickAffordanceId = quickAffordanceId,
+ )
+ }
+ }
+ MESSAGE_ID_DEFAULT_PREVIEW -> {
+ checkNotNull(renderer).onDefaultPreview()
+ }
+ MESSAGE_ID_HIDE_SMART_SPACE -> {
+ checkNotNull(renderer).hideSmartspace(message.data.getBoolean(KEY_HIDE_SMART_SPACE))
}
else -> checkNotNull(onDestroy).invoke(this)
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModel.kt
index 2426f97..c885c9a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModel.kt
@@ -20,6 +20,7 @@
import androidx.annotation.VisibleForTesting
import com.android.app.tracing.FlowTracing.traceEmissionCount
import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.keyguard.NewPickerUiKeyguardPreview
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardQuickAffordanceInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
@@ -29,6 +30,7 @@
import com.android.systemui.keyguard.shared.quickaffordance.KeyguardQuickAffordancePosition
import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots
+import com.android.systemui.utils.coroutines.flow.flatMapLatestConflated
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -164,13 +166,36 @@
.map { alpha -> alpha >= AFFORDANCE_FULLY_OPAQUE_ALPHA_THRESHOLD }
.distinctUntilChanged()
+ private val previewAffordances =
+ MutableStateFlow<Map<KeyguardQuickAffordancePosition, String>>(emptyMap())
+
/** An observable for the view-model of the "start button" quick affordance. */
val startButton: Flow<KeyguardQuickAffordanceViewModel> =
- button(KeyguardQuickAffordancePosition.BOTTOM_START)
+ if (NewPickerUiKeyguardPreview.isEnabled) {
+ previewAffordances.flatMapLatestConflated {
+ button(
+ position = KeyguardQuickAffordancePosition.BOTTOM_START,
+ overrideQuickAffordanceId = it[KeyguardQuickAffordancePosition.BOTTOM_START],
+ )
+ }
+ } else {
+ button(
+ KeyguardQuickAffordancePosition.BOTTOM_START,
+ )
+ }
/** An observable for the view-model of the "end button" quick affordance. */
val endButton: Flow<KeyguardQuickAffordanceViewModel> =
- button(KeyguardQuickAffordancePosition.BOTTOM_END)
+ if (NewPickerUiKeyguardPreview.isEnabled) {
+ previewAffordances.flatMapLatestConflated {
+ button(
+ position = KeyguardQuickAffordancePosition.BOTTOM_END,
+ overrideQuickAffordanceId = it[KeyguardQuickAffordancePosition.BOTTOM_END],
+ )
+ }
+ } else {
+ button(KeyguardQuickAffordancePosition.BOTTOM_END)
+ }
/**
* Notifies that a slot with the given ID has been selected in the preview experience that is
@@ -183,6 +208,28 @@
}
/**
+ * Notifies to preview an affordance at a given slot ID. This is ignored for the real lock
+ * screen experience.
+ */
+ fun onPreviewQuickAffordanceSelected(slotId: String, affordanceId: String) {
+ val position =
+ KeyguardQuickAffordancePosition.parseKeyguardQuickAffordancePosition(slotId) ?: return
+ previewAffordances.value =
+ previewAffordances.value.toMutableMap().let {
+ it[position] = affordanceId
+ HashMap(it)
+ }
+ }
+
+ /**
+ * Notifies to clear up the preview affordances map. This is ignored for the real lock screen
+ * experience.
+ */
+ fun onClearPreviewQuickAffordances() {
+ previewAffordances.value = emptyMap()
+ }
+
+ /**
* Puts this view-model in "preview mode", which means it's being used for UI that is rendering
* the lock screen preview in wallpaper picker / settings and not the real experience on the
* lock screen.
@@ -207,14 +254,16 @@
}
private fun button(
- position: KeyguardQuickAffordancePosition
+ position: KeyguardQuickAffordancePosition,
+ overrideQuickAffordanceId: String? = null,
): Flow<KeyguardQuickAffordanceViewModel> {
return previewMode
.flatMapLatest { previewMode ->
combine(
if (previewMode.isInPreviewMode) {
quickAffordanceInteractor.quickAffordanceAlwaysVisible(
- position = position
+ position = position,
+ overrideQuickAffordanceId = overrideQuickAffordanceId,
)
} else {
quickAffordanceInteractor.quickAffordance(position = position)
diff --git a/packages/SystemUI/src/com/android/systemui/lifecycle/BaseActivatable.kt b/packages/SystemUI/src/com/android/systemui/lifecycle/BaseActivatable.kt
new file mode 100644
index 0000000..03476ec
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/lifecycle/BaseActivatable.kt
@@ -0,0 +1,115 @@
+/*
+ * 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.lifecycle
+
+import java.util.concurrent.atomic.AtomicBoolean
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.awaitCancellation
+import kotlinx.coroutines.channels.Channel
+import kotlinx.coroutines.coroutineScope
+import kotlinx.coroutines.flow.receiveAsFlow
+import kotlinx.coroutines.launch
+
+/**
+ * A base [Activatable] with the following characteristics:
+ * 1. **Can be concurrently activated by no more than one owner.** A previous call to [activate]
+ * must be canceled before a new call to [activate] can be made. Trying to call [activate] while
+ * already active will fail with an error
+ * 2. **Can manage child [Activatable]s**. See [addChild] and [removeChild]. Added children
+ * automatically track the activation state of the parent such that when the parent is active,
+ * the children are active and vice-versa. Children are also retained such that deactivating the
+ * parent and reactivating it also cancels and reactivates the children.
+ */
+abstract class BaseActivatable : Activatable {
+
+ private val _isActive = AtomicBoolean(false)
+
+ var isActive: Boolean
+ get() = _isActive.get()
+ private set(value) {
+ _isActive.set(value)
+ }
+
+ final override suspend fun activate(): Nothing {
+ val allowed = _isActive.compareAndSet(false, true)
+ check(allowed) { "Cannot activate an already active activatable!" }
+
+ coroutineScope {
+ try {
+ launch { manageChildren() }
+ onActivated()
+ } finally {
+ isActive = false
+ }
+ }
+ }
+
+ /**
+ * Notifies that the [Activatable] has been activated.
+ *
+ * Serves as an entrypoint to kick off coroutine work that the object requires in order to keep
+ * its state fresh and/or perform side-effects.
+ *
+ * The method suspends and doesn't return until all work required by the object is finished. In
+ * most cases, it's expected for the work to remain ongoing forever so this method will forever
+ * suspend its caller until the coroutine that called it is canceled.
+ *
+ * Implementations could follow this pattern:
+ * ```kotlin
+ * override suspend fun onActivated(): Nothing {
+ * coroutineScope {
+ * launch { ... }
+ * launch { ... }
+ * launch { ... }
+ * }
+ * }
+ * ```
+ *
+ * @see activate
+ */
+ protected abstract suspend fun onActivated(): Nothing
+
+ private val newChildren = Channel<Activatable>(Channel.BUFFERED)
+ private val jobByChild: MutableMap<Activatable, Job> by lazy { mutableMapOf() }
+
+ private suspend fun manageChildren(): Nothing {
+ coroutineScope {
+ // Reactivate children that were added during a previous activation:
+ jobByChild.keys.forEach { child -> jobByChild[child] = launch { child.activate() } }
+
+ // Process requests to add more children:
+ newChildren.receiveAsFlow().collect { newChild ->
+ removeChildInternal(newChild)
+ jobByChild[newChild] = launch { newChild.activate() }
+ }
+
+ awaitCancellation()
+ }
+ }
+
+ fun addChild(child: Activatable) {
+ newChildren.trySend(child)
+ }
+
+ fun removeChild(child: Activatable) {
+ removeChildInternal(child)
+ }
+
+ private fun removeChildInternal(child: Activatable) {
+ jobByChild.remove(child)?.cancel()
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/lifecycle/SafeActivatable.kt b/packages/SystemUI/src/com/android/systemui/lifecycle/SafeActivatable.kt
deleted file mode 100644
index 4dd76f8..0000000
--- a/packages/SystemUI/src/com/android/systemui/lifecycle/SafeActivatable.kt
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * 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.lifecycle
-
-import java.util.concurrent.atomic.AtomicBoolean
-
-/**
- * An [Activatable] that can be concurrently activated by no more than one owner.
- *
- * A previous call to [activate] must be canceled before a new call to [activate] can be made.
- * Trying to call [activate] while already active will fail with an error.
- */
-abstract class SafeActivatable : Activatable {
-
- private val _isActive = AtomicBoolean(false)
-
- var isActive: Boolean
- get() = _isActive.get()
- private set(value) {
- _isActive.set(value)
- }
-
- final override suspend fun activate(): Nothing {
- val allowed = _isActive.compareAndSet(false, true)
- check(allowed) { "Cannot activate an already active activatable!" }
-
- try {
- onActivated()
- } finally {
- isActive = false
- }
- }
-
- /**
- * Notifies that the [Activatable] has been activated.
- *
- * Serves as an entrypoint to kick off coroutine work that the object requires in order to keep
- * its state fresh and/or perform side-effects.
- *
- * The method suspends and doesn't return until all work required by the object is finished. In
- * most cases, it's expected for the work to remain ongoing forever so this method will forever
- * suspend its caller until the coroutine that called it is canceled.
- *
- * Implementations could follow this pattern:
- * ```kotlin
- * override suspend fun onActivated(): Nothing {
- * coroutineScope {
- * launch { ... }
- * launch { ... }
- * launch { ... }
- * }
- * }
- * ```
- *
- * @see activate
- */
- protected abstract suspend fun onActivated(): Nothing
-}
diff --git a/packages/SystemUI/src/com/android/systemui/lifecycle/SysUiViewModel.kt b/packages/SystemUI/src/com/android/systemui/lifecycle/SysUiViewModel.kt
index 2edde4a..104b076 100644
--- a/packages/SystemUI/src/com/android/systemui/lifecycle/SysUiViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/lifecycle/SysUiViewModel.kt
@@ -23,7 +23,7 @@
import kotlinx.coroutines.launch
/** Base class for all System UI view-models. */
-abstract class SysUiViewModel : SafeActivatable() {
+abstract class SysUiViewModel : BaseActivatable() {
override suspend fun onActivated(): Nothing {
awaitCancellation()
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/PackageManagerAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/external/PackageManagerAdapter.java
index 6cf4441..28e4fd0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/PackageManagerAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/PackageManagerAdapter.java
@@ -26,6 +26,8 @@
import android.content.pm.ServiceInfo;
import android.os.RemoteException;
+import androidx.annotation.Nullable;
+
import javax.inject.Inject;
// Adapter that wraps calls to PackageManager or IPackageManager for {@link TileLifecycleManager}.
@@ -45,6 +47,7 @@
mIPackageManager = AppGlobals.getPackageManager();
}
+ @Nullable
public ServiceInfo getServiceInfo(ComponentName className, int flags, int userId)
throws RemoteException {
return mIPackageManager.getServiceInfo(className, flags, userId);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
index 96df728..cbcf68c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
@@ -188,10 +188,10 @@
public boolean isActiveTile() {
try {
ServiceInfo info = mPackageManagerAdapter.getServiceInfo(mIntent.getComponent(),
- META_DATA_QUERY_FLAGS);
- return info.metaData != null
+ META_DATA_QUERY_FLAGS, mUser.getIdentifier());
+ return info != null && info.metaData != null
&& info.metaData.getBoolean(TileService.META_DATA_ACTIVE_TILE, false);
- } catch (PackageManager.NameNotFoundException e) {
+ } catch (RemoteException e) {
return false;
}
}
@@ -206,10 +206,10 @@
public boolean isToggleableTile() {
try {
ServiceInfo info = mPackageManagerAdapter.getServiceInfo(mIntent.getComponent(),
- META_DATA_QUERY_FLAGS);
- return info.metaData != null
+ META_DATA_QUERY_FLAGS, mUser.getIdentifier());
+ return info != null && info.metaData != null
&& info.metaData.getBoolean(TileService.META_DATA_TOGGLEABLE_TILE, false);
- } catch (PackageManager.NameNotFoundException e) {
+ } catch (RemoteException e) {
return false;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/data/repository/CustomTileRepository.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/data/repository/CustomTileRepository.kt
index c932cee..0aaea8f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/data/repository/CustomTileRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/data/repository/CustomTileRepository.kt
@@ -17,8 +17,8 @@
package com.android.systemui.qs.tiles.impl.custom.data.repository
import android.content.pm.PackageManager
-import android.content.pm.ServiceInfo
import android.graphics.drawable.Icon
+import android.os.RemoteException
import android.os.UserHandle
import android.service.quicksettings.Tile
import android.service.quicksettings.TileService
@@ -163,13 +163,14 @@
override suspend fun isTileActive(): Boolean =
withContext(backgroundContext) {
try {
- val info: ServiceInfo =
+ val info =
packageManagerAdapter.getServiceInfo(
tileSpec.componentName,
- META_DATA_QUERY_FLAGS
+ META_DATA_QUERY_FLAGS,
+ getCurrentTileWithUser()?.user?.identifier ?: UserHandle.USER_CURRENT,
)
- info.metaData?.getBoolean(TileService.META_DATA_ACTIVE_TILE, false) == true
- } catch (e: PackageManager.NameNotFoundException) {
+ info?.metaData?.getBoolean(TileService.META_DATA_ACTIVE_TILE, false) == true
+ } catch (e: RemoteException) {
false
}
}
@@ -177,13 +178,14 @@
override suspend fun isTileToggleable(): Boolean =
withContext(backgroundContext) {
try {
- val info: ServiceInfo =
+ val info =
packageManagerAdapter.getServiceInfo(
tileSpec.componentName,
- META_DATA_QUERY_FLAGS
+ META_DATA_QUERY_FLAGS,
+ getCurrentTileWithUser()?.user?.identifier ?: UserHandle.USER_CURRENT
)
- info.metaData?.getBoolean(TileService.META_DATA_TOGGLEABLE_TILE, false) == true
- } catch (e: PackageManager.NameNotFoundException) {
+ info?.metaData?.getBoolean(TileService.META_DATA_TOGGLEABLE_TILE, false) == true
+ } catch (e: RemoteException) {
false
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
index e73664d..cc46216 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
@@ -152,7 +152,7 @@
hydrateBackStack()
resetShadeSessions()
handleKeyguardEnabledness()
- notifyKeyguardDismissCallbacks()
+ notifyKeyguardDismissCancelledCallbacks()
refreshLockscreenEnabled()
} else {
sceneLogger.logFrameworkEnabled(
@@ -379,8 +379,10 @@
when {
isAlternateBouncerVisible -> {
// When the device becomes unlocked when the alternate bouncer is
- // showing, always hide the alternate bouncer...
+ // showing, always hide the alternate bouncer and notify dismiss
+ // succeeded
alternateBouncerInteractor.hide()
+ dismissCallbackRegistry.notifyDismissSucceeded()
// ... and go to Gone or stay on the current scene
if (
@@ -394,9 +396,11 @@
null
}
}
- isOnPrimaryBouncer ->
+ isOnPrimaryBouncer -> {
// When the device becomes unlocked in primary Bouncer,
+ // notify dismiss succeeded and
// go to previous scene or Gone.
+ dismissCallbackRegistry.notifyDismissSucceeded()
if (
previousScene.value == Scenes.Lockscreen ||
!statusBarStateController.leaveOpenOnKeyguardHide()
@@ -410,6 +414,7 @@
"device was unlocked with primary bouncer showing," +
" from sceneKey=$prevScene"
}
+ }
isOnLockscreen ->
// The lockscreen should be dismissed automatically in 2 scenarios:
// 1. When face auth bypass is enabled and authentication happens while
@@ -468,6 +473,9 @@
applicationScope.launch {
powerInteractor.isAsleep.collect { isAsleep ->
if (isAsleep) {
+ alternateBouncerInteractor.hide()
+ dismissCallbackRegistry.notifyDismissCancelled()
+
switchToScene(
targetSceneKey = Scenes.Lockscreen,
loggingReason = "device is starting to sleep",
@@ -771,15 +779,23 @@
}
}
- private fun notifyKeyguardDismissCallbacks() {
+ private fun notifyKeyguardDismissCancelledCallbacks() {
applicationScope.launch {
- sceneInteractor.currentScene.pairwise().collect { (from, to) ->
- when {
- from != Scenes.Bouncer -> Unit
- to == Scenes.Gone -> dismissCallbackRegistry.notifyDismissSucceeded()
- else -> dismissCallbackRegistry.notifyDismissCancelled()
+ combine(
+ deviceEntryInteractor.isUnlocked,
+ sceneInteractor.currentScene.pairwise(),
+ ) { isUnlocked, (from, to) ->
+ when {
+ from != Scenes.Bouncer -> false
+ to != Scenes.Gone && !isUnlocked -> true
+ else -> false
+ }
}
- }
+ .collect { notifyKeyguardDismissCancelled ->
+ if (notifyKeyguardDismissCancelled) {
+ dismissCallbackRegistry.notifyDismissCancelled()
+ }
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index 65a59f5..c023b83 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -4536,6 +4536,13 @@
private final class StatusBarStateListener implements StateListener {
@Override
public void onStateChanged(int statusBarState) {
+ onStateChanged(statusBarState, false);
+ }
+
+ private void onStateChanged(
+ int statusBarState,
+ boolean animatingUnlockedShadeToKeyguardBypass
+ ) {
boolean goingToFullShade = mStatusBarStateController.goingToFullShade();
boolean keyguardFadingAway = mKeyguardStateController.isKeyguardFadingAway();
int oldState = mBarState;
@@ -4607,15 +4614,14 @@
// - getting notified again about the current SHADE or KEYGUARD state
final boolean animatingUnlockedShadeToKeyguard = oldState == SHADE
&& statusBarState == KEYGUARD
- && mScreenOffAnimationController.isKeyguardShowDelayed();
+ && mScreenOffAnimationController.isKeyguardShowDelayed()
+ //Bypasses animatingUnlockedShadeToKeyguard for b/337742708
+ && !animatingUnlockedShadeToKeyguardBypass;
if (!animatingUnlockedShadeToKeyguard) {
// Only make the status bar visible if we're not animating the screen off, since
// we only want to be showing the clock/notifications during the animation.
- if (keyguardShowing) {
- mShadeLog.v("Updating keyguard status bar state to visible");
- } else {
- mShadeLog.v("Updating keyguard status bar state to invisible");
- }
+ mShadeLog.logKeyguardStatudBarVisibiliy(keyguardShowing, isOnAod(),
+ animatingUnlockedShadeToKeyguardBypass, oldState, statusBarState);
mKeyguardStatusBarViewController.updateViewState(
/* alpha= */ 1f,
keyguardShowing ? View.VISIBLE : View.INVISIBLE);
@@ -4692,7 +4698,8 @@
.addTagListener(QS.TAG, mQsController.getQsFragmentListener());
if (!SceneContainerFlag.isEnabled()) {
mStatusBarStateController.addCallback(mStatusBarStateListener);
- mStatusBarStateListener.onStateChanged(mStatusBarStateController.getState());
+ // Bypass animatingUnlockedShadeToKeyguard in onStateChanged for b/337742708
+ mStatusBarStateListener.onStateChanged(mStatusBarStateController.getState(), true);
}
mConfigurationController.addCallback(mConfigurationListener);
// Theme might have changed between inflating this view and attaching it to the
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt
index 66a310c..f1eaec8 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt
@@ -411,4 +411,29 @@
}
)
}
+
+ fun logKeyguardStatudBarVisibiliy(
+ visibility: Boolean,
+ isOnAod: Boolean,
+ animatingUnlockedShadeToKeyguardBypass: Boolean,
+ oldShadeState: Int,
+ newShadeState: Int,
+ ) {
+ buffer.log(
+ TAG,
+ LogLevel.VERBOSE,
+ {
+ bool1 = visibility
+ bool2 = isOnAod
+ bool3 = animatingUnlockedShadeToKeyguardBypass
+ int1 = oldShadeState
+ int2 = newShadeState
+ },
+ {
+ "Setting keyguard status bar visibility to: $bool1, isOnAod: $bool2" +
+ "oldShadeState: $int1, newShadeState: $int2," +
+ "animatingUnlockedShadeToKeyguardBypass: $bool3"
+ }
+ )
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/OWNERS b/packages/SystemUI/src/com/android/systemui/statusbar/OWNERS
index c4f539a..408fc6d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/OWNERS
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/OWNERS
@@ -13,4 +13,12 @@
per-file *Keyboard* = set noparent
per-file *Keyboard* = file:../keyguard/OWNERS
per-file *Keyguard* = set noparent
-per-file *Keyguard* = file:../keyguard/OWNERS
\ No newline at end of file
+per-file *Keyguard* = file:../keyguard/OWNERS
+per-file *Notification* = set noparent
+per-file *Notification* = file:notification/OWNERS
+per-file *Mode* = set noparent
+per-file *Mode* = file:notification/OWNERS
+per-file *RemoteInput* = set noparent
+per-file *RemoteInput* = file:notification/OWNERS
+per-file *EmptyShadeView* = set noparent
+per-file *EmptyShadeView* = file:notification/OWNERS
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/CommonNotifCollection.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/CommonNotifCollection.java
index fc7d682..0d209d8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/CommonNotifCollection.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/CommonNotifCollection.java
@@ -27,9 +27,6 @@
/**
* A notification collection that manages the list of {@link NotificationEntry}s that will be
* rendered.
- *
- * TODO: (b/145659174) Once we fully migrate to {@link NotifPipeline}, we probably won't need this,
- * but having it for now makes it easy to switch between the two.
*/
public interface CommonNotifCollection {
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index 20b1fff..e802076 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -258,7 +258,7 @@
private float mOverScrolledBottomPixels;
private final ListenerSet<Runnable> mStackHeightChangedListeners = new ListenerSet<>();
private final ListenerSet<Runnable> mHeadsUpHeightChangedListeners = new ListenerSet<>();
- private NotificationLogger.OnChildLocationsChangedListener mListener;
+ private NotificationLogger.OnChildLocationsChangedListener mLegacyLocationsChangedListener;
private OnNotificationLocationsChangedListener mLocationsChangedListener;
private OnOverscrollTopChangedListener mOverscrollTopChangedListener;
private ExpandableView.OnHeightChangedListener mOnHeightChangedListener;
@@ -1281,7 +1281,7 @@
public void setChildLocationsChangedListener(
NotificationLogger.OnChildLocationsChangedListener listener) {
NotificationsLiveDataStoreRefactor.assertInLegacyMode();
- mListener = listener;
+ mLegacyLocationsChangedListener = listener;
}
private void setMaxLayoutHeight(int maxLayoutHeight) {
@@ -4433,8 +4433,8 @@
mLocationsChangedListener.onChildLocationsChanged(collectVisibleLocationsCallable);
}
} else {
- if (mListener != null) {
- mListener.onChildLocationsChanged();
+ if (mLegacyLocationsChangedListener != null) {
+ mLegacyLocationsChangedListener.onChildLocationsChanged();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index de4d14d..0f93ff2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -545,6 +545,7 @@
@VisibleForTesting
void consumeFromAlternateBouncerTransitionSteps(TransitionStep step) {
+ SceneContainerFlag.assertInLegacyMode();
hideAlternateBouncer(false);
}
@@ -554,6 +555,7 @@
*/
@VisibleForTesting
void consumeKeyguardAuthenticatedBiometricsHandled(Unit handled) {
+ SceneContainerFlag.assertInLegacyMode();
if (mAlternateBouncerInteractor.isVisibleState()) {
hideAlternateBouncer(false);
}
@@ -981,7 +983,7 @@
} else {
showBouncerOrKeyguard(hideBouncerWhenShowing, isFalsingReset);
}
- if (hideBouncerWhenShowing) {
+ if (!SceneContainerFlag.isEnabled() && hideBouncerWhenShowing) {
hideAlternateBouncer(true);
}
mKeyguardUpdateManager.sendKeyguardReset();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogDelegate.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogDelegate.kt
index 4f7749b..e1dcc52 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogDelegate.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogDelegate.kt
@@ -21,7 +21,11 @@
import android.util.Log
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.semantics.semantics
+import androidx.compose.ui.semantics.testTagsAsResourceId
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
import com.android.compose.PlatformButton
@@ -88,7 +92,15 @@
@Composable
private fun ModesDialogContent(dialog: SystemUIDialog) {
AlertDialogContent(
- title = { Text(stringResource(R.string.zen_modes_dialog_title)) },
+ modifier = Modifier.semantics {
+ testTagsAsResourceId = true
+ },
+ title = {
+ Text(
+ modifier = Modifier.testTag("modes_title"),
+ text = stringResource(R.string.zen_modes_dialog_title)
+ )
+ },
content = { ModeTileGrid(viewModel.get()) },
neutralButton = {
PlatformOutlinedButton(onClick = { openSettings(dialog) }) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/composable/ModeTile.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/composable/ModeTile.kt
index 3b392c8..3fffd9f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/composable/ModeTile.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/composable/ModeTile.kt
@@ -32,6 +32,7 @@
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.testTag
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import com.android.systemui.common.ui.compose.Icon
@@ -70,12 +71,12 @@
Text(
viewModel.text,
fontWeight = FontWeight.W500,
- modifier = Modifier.tileMarquee()
+ modifier = Modifier.tileMarquee().testTag("name")
)
Text(
viewModel.subtext,
fontWeight = FontWeight.W400,
- modifier = Modifier.tileMarquee()
+ modifier = Modifier.tileMarquee().testTag("state")
)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/util/kotlin/FlowDumper.kt b/packages/SystemUI/src/com/android/systemui/util/kotlin/FlowDumper.kt
index ef9f8ff..ae0061b 100644
--- a/packages/SystemUI/src/com/android/systemui/util/kotlin/FlowDumper.kt
+++ b/packages/SystemUI/src/com/android/systemui/util/kotlin/FlowDumper.kt
@@ -19,7 +19,7 @@
import android.util.IndentingPrintWriter
import com.android.systemui.Dumpable
import com.android.systemui.dump.DumpManager
-import com.android.systemui.lifecycle.SafeActivatable
+import com.android.systemui.lifecycle.BaseActivatable
import com.android.systemui.lifecycle.SysUiViewModel
import com.android.systemui.util.asIndenting
import com.android.systemui.util.printCollection
@@ -189,7 +189,7 @@
) : SimpleFlowDumper(), ActivatableFlowDumper {
private val registration =
- object : SafeActivatable() {
+ object : BaseActivatable() {
override suspend fun onActivated(): Nothing {
try {
dumpManager.registerCriticalDumpable(
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/domain/interactor/AudioSlidersInteractor.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/domain/interactor/AudioSlidersInteractor.kt
index fa40059..0451ce6 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/domain/interactor/AudioSlidersInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/domain/interactor/AudioSlidersInteractor.kt
@@ -19,6 +19,7 @@
import android.media.AudioDeviceInfo
import android.media.AudioManager
import com.android.settingslib.volume.data.repository.AudioRepository
+import com.android.settingslib.volume.domain.interactor.AudioModeInteractor
import com.android.settingslib.volume.shared.model.AudioStream
import com.android.systemui.volume.panel.component.mediaoutput.domain.interactor.MediaOutputInteractor
import com.android.systemui.volume.panel.component.mediaoutput.shared.model.MediaDeviceSession
@@ -42,6 +43,7 @@
@VolumePanelScope scope: CoroutineScope,
mediaOutputInteractor: MediaOutputInteractor,
audioRepository: AudioRepository,
+ audioModeInteractor: AudioModeInteractor,
) {
val volumePanelSliders: StateFlow<List<SliderType>> =
@@ -49,9 +51,14 @@
mediaOutputInteractor.activeMediaDeviceSessions,
mediaOutputInteractor.defaultActiveMediaSession.filterData(),
audioRepository.communicationDevice,
- ) { activeSessions, defaultSession, communicationDevice ->
+ audioModeInteractor.isOngoingCall,
+ ) { activeSessions, defaultSession, communicationDevice, isOngoingCall ->
coroutineScope {
val viewModels = buildList {
+ if (isOngoingCall) {
+ addCall(communicationDevice?.type)
+ }
+
if (defaultSession?.isTheSameSession(activeSessions.remote) == true) {
addSession(activeSessions.remote)
addStream(AudioManager.STREAM_MUSIC)
@@ -60,11 +67,10 @@
addSession(activeSessions.remote)
}
- if (communicationDevice?.type == AudioDeviceInfo.TYPE_BLUETOOTH_SCO) {
- addStream(AudioManager.STREAM_BLUETOOTH_SCO)
- } else {
- addStream(AudioManager.STREAM_VOICE_CALL)
+ if (!isOngoingCall) {
+ addCall(communicationDevice?.type)
}
+
addStream(AudioManager.STREAM_RING)
addStream(AudioManager.STREAM_NOTIFICATION)
addStream(AudioManager.STREAM_ALARM)
@@ -74,6 +80,14 @@
}
.stateIn(scope, SharingStarted.Eagerly, emptyList())
+ private fun MutableList<SliderType>.addCall(communicationDeviceType: Int?) {
+ if (communicationDeviceType == AudioDeviceInfo.TYPE_BLUETOOTH_SCO) {
+ addStream(AudioManager.STREAM_BLUETOOTH_SCO)
+ } else {
+ addStream(AudioManager.STREAM_VOICE_CALL)
+ }
+ }
+
private fun MutableList<SliderType>.addSession(remoteMediaDeviceSession: MediaDeviceSession?) {
if (remoteMediaDeviceSession?.canAdjustVolume == true) {
add(SliderType.MediaDeviceCast(remoteMediaDeviceSession))
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/ui/viewmodel/AudioVolumeComponentViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/ui/viewmodel/AudioVolumeComponentViewModel.kt
index 4b4d69a..45732de 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/ui/viewmodel/AudioVolumeComponentViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/ui/viewmodel/AudioVolumeComponentViewModel.kt
@@ -16,6 +16,7 @@
package com.android.systemui.volume.panel.component.volume.ui.viewmodel
+import com.android.settingslib.volume.domain.interactor.AudioModeInteractor
import com.android.settingslib.volume.shared.model.AudioStream
import com.android.systemui.volume.panel.component.mediaoutput.domain.interactor.MediaDeviceSessionInteractor
import com.android.systemui.volume.panel.component.mediaoutput.domain.interactor.MediaOutputInteractor
@@ -35,9 +36,11 @@
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.stateIn
@@ -58,24 +61,31 @@
mediaDeviceSessionInteractor: MediaDeviceSessionInteractor,
private val streamSliderViewModelFactory: AudioStreamSliderViewModel.Factory,
private val castVolumeSliderViewModelFactory: CastVolumeSliderViewModel.Factory,
+ audioModeInteractor: AudioModeInteractor,
streamsInteractor: AudioSlidersInteractor,
) {
private val mutableIsExpanded = MutableStateFlow<Boolean?>(null)
- private val isPlaybackActive: Flow<Boolean?> =
- mediaOutputInteractor.defaultActiveMediaSession
- .filterData()
- .flatMapLatest { session ->
- if (session == null) {
- flowOf(false)
- } else {
- mediaDeviceSessionInteractor.playbackState(session).map { it?.isActive == true }
- }
+ private val isActive: Flow<Boolean?> =
+ combine(
+ audioModeInteractor.isOngoingCall,
+ mediaOutputInteractor.defaultActiveMediaSession.filterData().flatMapLatest { session
+ ->
+ if (session == null) {
+ flowOf(false)
+ } else {
+ mediaDeviceSessionInteractor.playbackState(session).map {
+ it?.isActive == true
+ }
+ }
+ },
+ ) { isOngoingCall, isPlaybackActive ->
+ isOngoingCall || isPlaybackActive
}
- .onEach { isPlaybackActive -> mutableIsExpanded.value = !isPlaybackActive }
.stateIn(scope, SharingStarted.Eagerly, null)
+
private val portraitExpandable: Flow<SlidersExpandableViewModel> =
- isPlaybackActive
+ isActive
.filterNotNull()
.flatMapLatest { isActive ->
if (isActive) {
@@ -105,6 +115,10 @@
}
.stateIn(scope, SharingStarted.Eagerly, emptyList())
+ init {
+ isActive.filterNotNull().onEach { mutableIsExpanded.value = !it }.launchIn(scope)
+ }
+
fun isExpandable(isPortrait: Boolean): Flow<SlidersExpandableViewModel> {
return if (isPortrait) {
portraitExpandable
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java b/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java
index 45799b2..7385b82 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java
@@ -115,7 +115,6 @@
private final Executor mSysuiUiBgExecutor;
private final Bubbles.SysuiProxy mSysuiProxy;
- // TODO (b/145659174): allow for multiple callbacks to support the "shadow" new notif pipeline
private final List<NotifCallback> mCallbacks = new ArrayList<>();
private final StatusBarWindowCallback mStatusBarWindowCallback;
private final Runnable mSensitiveStateChangedListener;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuControllerTest.java
index 5ff3915..113a8c0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuControllerTest.java
@@ -45,6 +45,7 @@
import com.android.systemui.SysuiTestCase;
import com.android.systemui.accessibility.AccessibilityButtonModeObserver;
import com.android.systemui.accessibility.AccessibilityButtonTargetsObserver;
+import com.android.systemui.navigationbar.NavigationModeController;
import com.android.systemui.settings.FakeDisplayTracker;
import com.android.systemui.util.settings.SecureSettings;
@@ -90,6 +91,8 @@
private SecureSettings mSecureSettings;
@Mock
private Lazy<ViewCapture> mLazyViewCapture;
+ @Mock
+ private NavigationModeController mNavigationModeController;
@Before
public void setUp() throws Exception {
@@ -163,7 +166,8 @@
enableAccessibilityFloatingMenuConfig();
mController = setUpController();
mController.mFloatingMenu = new MenuViewLayerController(mContextWrapper, mWindowManager,
- mViewCaptureAwareWindowManager, mAccessibilityManager, mSecureSettings);
+ mViewCaptureAwareWindowManager, mAccessibilityManager, mSecureSettings,
+ mNavigationModeController);
captureKeyguardUpdateMonitorCallback();
mKeyguardCallback.onUserUnlocked();
@@ -190,7 +194,8 @@
enableAccessibilityFloatingMenuConfig();
mController = setUpController();
mController.mFloatingMenu = new MenuViewLayerController(mContextWrapper, mWindowManager,
- mViewCaptureAwareWindowManager, mAccessibilityManager, mSecureSettings);
+ mViewCaptureAwareWindowManager, mAccessibilityManager, mSecureSettings,
+ mNavigationModeController);
captureKeyguardUpdateMonitorCallback();
mKeyguardCallback.onUserSwitching(fakeUserId);
@@ -204,7 +209,8 @@
enableAccessibilityFloatingMenuConfig();
mController = setUpController();
mController.mFloatingMenu = new MenuViewLayerController(mContextWrapper, mWindowManager,
- mViewCaptureAwareWindowManager, mAccessibilityManager, mSecureSettings);
+ mViewCaptureAwareWindowManager, mAccessibilityManager, mSecureSettings,
+ mNavigationModeController);
captureKeyguardUpdateMonitorCallback();
mKeyguardCallback.onUserUnlocked();
mKeyguardCallback.onKeyguardVisibilityChanged(true);
@@ -340,7 +346,7 @@
new AccessibilityFloatingMenuController(mContextWrapper, windowManager,
viewCaptureAwareWindowManager, displayManager, mAccessibilityManager,
mTargetsObserver, mModeObserver, mKeyguardUpdateMonitor, mSecureSettings,
- displayTracker);
+ displayTracker, mNavigationModeController);
controller.init();
return controller;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuItemAccessibilityDelegateTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuItemAccessibilityDelegateTest.java
index c5509ac..157cccc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuItemAccessibilityDelegateTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuItemAccessibilityDelegateTest.java
@@ -44,6 +44,7 @@
import com.android.systemui.Flags;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.accessibility.utils.TestUtils;
+import com.android.systemui.navigationbar.NavigationModeController;
import com.android.systemui.res.R;
import com.android.systemui.util.settings.SecureSettings;
@@ -94,7 +95,8 @@
mMenuViewLayer = spy(new MenuViewLayer(
mContext, stubWindowManager, mAccessibilityManager,
stubMenuViewModel, stubMenuViewAppearance, mMenuView,
- mock(IAccessibilityFloatingMenu.class), mSecureSettings));
+ mock(IAccessibilityFloatingMenu.class), mSecureSettings,
+ mock(NavigationModeController.class)));
doNothing().when(mMenuViewLayer).gotoEditScreen();
doReturn(mDraggableBounds).when(mMenuView).getMenuDraggableBounds();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerControllerTest.java
index 07ce7b9..fcdeff9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerControllerTest.java
@@ -21,6 +21,7 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -41,6 +42,7 @@
import com.android.app.viewcapture.ViewCapture;
import com.android.app.viewcapture.ViewCaptureAwareWindowManager;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.navigationbar.NavigationModeController;
import com.android.systemui.util.settings.SecureSettings;
import kotlin.Lazy;
@@ -90,7 +92,8 @@
when(mWindowMetrics.getBounds()).thenReturn(new Rect(0, 0, 1080, 2340));
when(mWindowMetrics.getWindowInsets()).thenReturn(stubDisplayInsets());
mMenuViewLayerController = new MenuViewLayerController(mContext, mWindowManager,
- viewCaptureAwareWm, mAccessibilityManager, mSecureSettings);
+ viewCaptureAwareWm, mAccessibilityManager, mSecureSettings,
+ mock(NavigationModeController.class));
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerTest.java
index e1e6139..c451c32 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerTest.java
@@ -81,6 +81,7 @@
import com.android.systemui.SysuiTestCase;
import com.android.systemui.SysuiTestableContext;
import com.android.systemui.accessibility.utils.TestUtils;
+import com.android.systemui.navigationbar.NavigationModeController;
import com.android.systemui.res.R;
import com.android.systemui.util.settings.SecureSettings;
import com.android.wm.shell.shared.magnetictarget.MagnetizedObject;
@@ -169,7 +170,7 @@
mMenuViewLayer = spy(new MenuViewLayer(mSpyContext, mStubWindowManager,
mStubAccessibilityManager, mMenuViewModel, menuViewAppearance, mMenuView,
- mFloatingMenu, mSecureSettings));
+ mFloatingMenu, mSecureSettings, mock(NavigationModeController.class)));
mMenuAnimationController = mMenuView.getMenuAnimationController();
doNothing().when(mSpyContext).startActivity(any());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothDeviceMetadataInteractorKosmos.kt b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothDeviceMetadataInteractorKosmos.kt
new file mode 100644
index 0000000..969e26a
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothDeviceMetadataInteractorKosmos.kt
@@ -0,0 +1,37 @@
+/*
+ * 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.bluetooth.qsdialog
+
+import com.android.systemui.bluetooth.bluetoothAdapter
+import com.android.systemui.concurrency.fakeExecutor
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.testDispatcher
+import org.mockito.kotlin.mock
+
+val Kosmos.deviceItemInteractor: DeviceItemInteractor by
+ Kosmos.Fixture { mock<DeviceItemInteractor>() }
+
+val Kosmos.bluetoothDeviceMetadataInteractor by
+ Kosmos.Fixture {
+ BluetoothDeviceMetadataInteractor(
+ deviceItemInteractor,
+ bluetoothAdapter,
+ bluetoothTileDialogLogger,
+ fakeExecutor,
+ testDispatcher,
+ )
+ }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothDeviceMetadataInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothDeviceMetadataInteractorTest.kt
new file mode 100644
index 0000000..f06b105
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothDeviceMetadataInteractorTest.kt
@@ -0,0 +1,226 @@
+/*
+ * 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.bluetooth.qsdialog
+
+import android.bluetooth.BluetoothAdapter
+import android.bluetooth.BluetoothDevice
+import android.testing.TestableLooper
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.settingslib.bluetooth.CachedBluetoothDevice
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.bluetooth.bluetoothAdapter
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.kosmos.testDispatcher
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.testKosmos
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.MutableSharedFlow
+import kotlinx.coroutines.test.UnconfinedTestDispatcher
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentCaptor
+import org.mockito.Captor
+import org.mockito.Mock
+import org.mockito.junit.MockitoJUnit
+import org.mockito.junit.MockitoRule
+import org.mockito.kotlin.any
+import org.mockito.kotlin.eq
+import org.mockito.kotlin.never
+import org.mockito.kotlin.times
+import org.mockito.kotlin.verify
+import org.mockito.kotlin.whenever
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
+class BluetoothDeviceMetadataInteractorTest : SysuiTestCase() {
+ @get:Rule val mockitoRule: MockitoRule = MockitoJUnit.rule()
+
+ private val kosmos = testKosmos().apply { testDispatcher = UnconfinedTestDispatcher() }
+
+ private val deviceItemUpdate: MutableSharedFlow<List<DeviceItem>> = MutableSharedFlow()
+ @Mock private lateinit var cachedDevice1: CachedBluetoothDevice
+ @Mock private lateinit var bluetoothDevice1: BluetoothDevice
+ @Mock private lateinit var cachedDevice2: CachedBluetoothDevice
+ @Mock private lateinit var bluetoothDevice2: BluetoothDevice
+ @Captor
+ private lateinit var argumentCaptor: ArgumentCaptor<BluetoothAdapter.OnMetadataChangedListener>
+ private lateinit var interactor: BluetoothDeviceMetadataInteractor
+
+ @Before
+ fun setUp() {
+ with(kosmos) {
+ whenever(deviceItemInteractor.deviceItemUpdate).thenReturn(deviceItemUpdate)
+
+ whenever(cachedDevice1.device).thenReturn(bluetoothDevice1)
+ whenever(cachedDevice1.name).thenReturn(DEVICE_NAME)
+ whenever(cachedDevice1.address).thenReturn(DEVICE_ADDRESS)
+ whenever(cachedDevice1.connectionSummary).thenReturn(CONNECTION_SUMMARY)
+ whenever(bluetoothDevice1.address).thenReturn(DEVICE_ADDRESS)
+
+ whenever(cachedDevice2.device).thenReturn(bluetoothDevice2)
+ whenever(cachedDevice2.name).thenReturn(DEVICE_NAME)
+ whenever(cachedDevice2.address).thenReturn(DEVICE_ADDRESS)
+ whenever(cachedDevice2.connectionSummary).thenReturn(CONNECTION_SUMMARY)
+ whenever(bluetoothDevice2.address).thenReturn(DEVICE_ADDRESS)
+
+ interactor = bluetoothDeviceMetadataInteractor
+ }
+ }
+
+ @Test
+ fun deviceItemUpdateEmpty_doNothing() {
+ with(kosmos) {
+ testScope.runTest {
+ val update by collectLastValue(interactor.metadataUpdate)
+ deviceItemUpdate.emit(emptyList())
+ runCurrent()
+
+ assertThat(update).isNull()
+ verify(bluetoothAdapter, never()).addOnMetadataChangedListener(any(), any(), any())
+ verify(bluetoothAdapter, never()).removeOnMetadataChangedListener(any(), any())
+ }
+ }
+ }
+
+ @Test
+ fun deviceItemUpdate_registerListener() {
+ with(kosmos) {
+ testScope.runTest {
+ val deviceItem = AvailableMediaDeviceItemFactory().create(context, cachedDevice1)
+ val update by collectLastValue(interactor.metadataUpdate)
+ deviceItemUpdate.emit(listOf(deviceItem))
+ runCurrent()
+
+ assertThat(update).isNull()
+ verify(bluetoothAdapter)
+ .addOnMetadataChangedListener(eq(bluetoothDevice1), any(), any())
+ verify(bluetoothAdapter, never()).removeOnMetadataChangedListener(any(), any())
+ }
+ }
+ }
+
+ @Test
+ fun deviceItemUpdate_sameDeviceItems_registerListenerOnce() {
+ with(kosmos) {
+ testScope.runTest {
+ val deviceItem = AvailableMediaDeviceItemFactory().create(context, cachedDevice1)
+ val update by collectLastValue(interactor.metadataUpdate)
+ deviceItemUpdate.emit(listOf(deviceItem))
+ deviceItemUpdate.emit(listOf(deviceItem))
+ runCurrent()
+
+ assertThat(update).isNull()
+ verify(bluetoothAdapter)
+ .addOnMetadataChangedListener(eq(bluetoothDevice1), any(), any())
+ verify(bluetoothAdapter, never()).removeOnMetadataChangedListener(any(), any())
+ }
+ }
+ }
+
+ @Test
+ fun deviceItemUpdate_differentDeviceItems_unregisterOldAndRegisterNew() {
+ with(kosmos) {
+ testScope.runTest {
+ val deviceItem1 = AvailableMediaDeviceItemFactory().create(context, cachedDevice1)
+ val deviceItem2 = AvailableMediaDeviceItemFactory().create(context, cachedDevice2)
+ val update by collectLastValue(interactor.metadataUpdate)
+ deviceItemUpdate.emit(listOf(deviceItem1))
+ deviceItemUpdate.emit(listOf(deviceItem1, deviceItem2))
+ runCurrent()
+
+ assertThat(update).isNull()
+ verify(bluetoothAdapter, times(2))
+ .addOnMetadataChangedListener(eq(bluetoothDevice1), any(), any())
+ verify(bluetoothAdapter)
+ .addOnMetadataChangedListener(eq(bluetoothDevice2), any(), any())
+ verify(bluetoothAdapter)
+ .removeOnMetadataChangedListener(eq(bluetoothDevice1), any())
+ }
+ }
+ }
+
+ @Test
+ fun metadataUpdate_triggerCallback_emit() {
+ with(kosmos) {
+ testScope.runTest {
+ val deviceItem = AvailableMediaDeviceItemFactory().create(context, cachedDevice1)
+ val update by collectLastValue(interactor.metadataUpdate)
+ deviceItemUpdate.emit(listOf(deviceItem))
+ runCurrent()
+
+ assertThat(update).isNull()
+ verify(bluetoothAdapter)
+ .addOnMetadataChangedListener(
+ eq(bluetoothDevice1),
+ any(),
+ argumentCaptor.capture()
+ )
+
+ val listener = argumentCaptor.value
+ listener.onMetadataChanged(
+ bluetoothDevice1,
+ BluetoothDevice.METADATA_UNTETHERED_LEFT_BATTERY,
+ ByteArray(0)
+ )
+ assertThat(update).isEqualTo(Unit)
+ }
+ }
+ }
+
+ @Test
+ fun metadataUpdate_triggerCallbackNonBatteryKey_doNothing() {
+ with(kosmos) {
+ testScope.runTest {
+ val deviceItem = AvailableMediaDeviceItemFactory().create(context, cachedDevice1)
+ val update by collectLastValue(interactor.metadataUpdate)
+ deviceItemUpdate.emit(listOf(deviceItem))
+ runCurrent()
+
+ assertThat(update).isNull()
+ verify(bluetoothAdapter)
+ .addOnMetadataChangedListener(
+ eq(bluetoothDevice1),
+ any(),
+ argumentCaptor.capture()
+ )
+
+ val listener = argumentCaptor.value
+ listener.onMetadataChanged(
+ bluetoothDevice1,
+ BluetoothDevice.METADATA_MODEL_NAME,
+ ByteArray(0)
+ )
+
+ assertThat(update).isNull()
+ }
+ }
+ }
+
+ companion object {
+ private const val DEVICE_NAME = "DeviceName"
+ private const val CONNECTION_SUMMARY = "ConnectionSummary"
+ private const val DEVICE_ADDRESS = "04:52:C7:0B:D8:3C"
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogViewModelTest.kt
index 9abb85d..d7bea66 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogViewModelTest.kt
@@ -77,6 +77,8 @@
@Mock private lateinit var audioSharingInteractor: AudioSharingInteractor
+ @Mock private lateinit var bluetoothDeviceMetadataInteractor: BluetoothDeviceMetadataInteractor
+
@Mock private lateinit var deviceItemInteractor: DeviceItemInteractor
@Mock private lateinit var deviceItemActionInteractor: DeviceItemActionInteractor
@@ -138,6 +140,7 @@
)
),
audioSharingInteractor,
+ bluetoothDeviceMetadataInteractor,
mDialogTransitionAnimator,
activityStarter,
uiEventLogger,
@@ -150,6 +153,8 @@
whenever(deviceItemInteractor.deviceItemUpdate).thenReturn(MutableSharedFlow())
whenever(deviceItemInteractor.deviceItemUpdateRequest)
.thenReturn(MutableStateFlow(Unit).asStateFlow())
+ whenever(deviceItemInteractor.showSeeAllUpdate).thenReturn(getMutableStateFlow(false))
+ whenever(bluetoothDeviceMetadataInteractor.metadataUpdate).thenReturn(MutableSharedFlow())
whenever(mBluetoothTileDialogDelegateDelegateFactory.create(any(), anyInt(), any(), any()))
.thenReturn(bluetoothTileDialogDelegate)
whenever(bluetoothTileDialogDelegate.createDialog()).thenReturn(sysuiDialog)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/DeviceItemInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/DeviceItemInteractorTest.kt
index 7f7abaf..194590c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/DeviceItemInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/DeviceItemInteractorTest.kt
@@ -113,9 +113,11 @@
)
val latest by collectLastValue(interactor.deviceItemUpdate)
+ val latestShowSeeAll by collectLastValue(interactor.showSeeAllUpdate)
interactor.updateDeviceItems(mContext, DeviceFetchTrigger.FIRST_LOAD)
assertThat(latest).isEqualTo(emptyList<DeviceItem>())
+ assertThat(latestShowSeeAll).isFalse()
}
}
@@ -128,9 +130,11 @@
)
val latest by collectLastValue(interactor.deviceItemUpdate)
+ val latestShowSeeAll by collectLastValue(interactor.showSeeAllUpdate)
interactor.updateDeviceItems(mContext, DeviceFetchTrigger.FIRST_LOAD)
assertThat(latest).isEqualTo(emptyList<DeviceItem>())
+ assertThat(latestShowSeeAll).isFalse()
}
}
@@ -143,9 +147,11 @@
)
val latest by collectLastValue(interactor.deviceItemUpdate)
+ val latestShowSeeAll by collectLastValue(interactor.showSeeAllUpdate)
interactor.updateDeviceItems(mContext, DeviceFetchTrigger.FIRST_LOAD)
assertThat(latest).isEqualTo(listOf(deviceItem1))
+ assertThat(latestShowSeeAll).isFalse()
}
}
@@ -158,9 +164,11 @@
)
val latest by collectLastValue(interactor.deviceItemUpdate)
+ val latestShowSeeAll by collectLastValue(interactor.showSeeAllUpdate)
interactor.updateDeviceItems(mContext, DeviceFetchTrigger.FIRST_LOAD)
assertThat(latest).isEqualTo(listOf(deviceItem2, deviceItem2))
+ assertThat(latestShowSeeAll).isFalse()
}
}
@@ -184,9 +192,11 @@
`when`(deviceItem2.type).thenReturn(DeviceItemType.SAVED_BLUETOOTH_DEVICE)
val latest by collectLastValue(interactor.deviceItemUpdate)
+ val latestShowSeeAll by collectLastValue(interactor.showSeeAllUpdate)
interactor.updateDeviceItems(mContext, DeviceFetchTrigger.FIRST_LOAD)
assertThat(latest).isEqualTo(listOf(deviceItem2, deviceItem1))
+ assertThat(latestShowSeeAll).isFalse()
}
}
@@ -207,9 +217,30 @@
`when`(deviceItem2.type).thenReturn(DeviceItemType.CONNECTED_BLUETOOTH_DEVICE)
val latest by collectLastValue(interactor.deviceItemUpdate)
+ val latestShowSeeAll by collectLastValue(interactor.showSeeAllUpdate)
interactor.updateDeviceItems(mContext, DeviceFetchTrigger.FIRST_LOAD)
assertThat(latest).isEqualTo(listOf(deviceItem2, deviceItem1))
+ assertThat(latestShowSeeAll).isFalse()
+ }
+ }
+
+ @Test
+ fun testUpdateDeviceItems_showMaxDeviceItems_showSeeAll() {
+ testScope.runTest {
+ `when`(bluetoothTileDialogRepository.cachedDevices)
+ .thenReturn(listOf(cachedDevice2, cachedDevice2, cachedDevice2, cachedDevice2))
+ `when`(adapter.mostRecentlyConnectedDevices).thenReturn(null)
+ interactor.setDeviceItemFactoryListForTesting(
+ listOf(createFactory({ true }, deviceItem2))
+ )
+
+ val latest by collectLastValue(interactor.deviceItemUpdate)
+ val latestShowSeeAll by collectLastValue(interactor.showSeeAllUpdate)
+ interactor.updateDeviceItems(mContext, DeviceFetchTrigger.FIRST_LOAD)
+
+ assertThat(latest).isEqualTo(listOf(deviceItem2, deviceItem2, deviceItem2))
+ assertThat(latestShowSeeAll).isTrue()
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/display/domain/interactor/ConnectedDisplayInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/display/domain/interactor/ConnectedDisplayInteractorTest.kt
index fd9964f..a2b50fd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/display/domain/interactor/ConnectedDisplayInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/display/domain/interactor/ConnectedDisplayInteractorTest.kt
@@ -17,8 +17,6 @@
package com.android.systemui.display.domain.interactor
import android.companion.virtual.VirtualDeviceManager
-import android.companion.virtual.flags.Flags.FLAG_INTERACTIVE_SCREEN_MIRROR
-import android.platform.test.annotations.EnableFlags
import android.testing.TestableLooper
import android.view.Display
import android.view.Display.TYPE_EXTERNAL
@@ -160,7 +158,6 @@
}
@Test
- @EnableFlags(FLAG_INTERACTIVE_SCREEN_MIRROR)
fun displayState_virtualDeviceOwnedMirrorVirtualDisplay_connected() =
testScope.runTest {
whenever(virtualDeviceManager.isVirtualDeviceOwnedMirrorDisplay(anyInt()))
@@ -183,7 +180,6 @@
}
@Test
- @EnableFlags(FLAG_INTERACTIVE_SCREEN_MIRROR)
fun virtualDeviceOwnedMirrorVirtualDisplay_emitsConnectedDisplayAddition() =
testScope.runTest {
whenever(virtualDeviceManager.isVirtualDeviceOwnedMirrorDisplay(anyInt()))
diff --git a/packages/SystemUI/tests/src/com/android/systemui/inputdevice/data/repository/TutorialSchedulerRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/inputdevice/data/repository/TutorialSchedulerRepositoryTest.kt
index 7583399..1d96c4d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/inputdevice/data/repository/TutorialSchedulerRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/inputdevice/data/repository/TutorialSchedulerRepositoryTest.kt
@@ -68,20 +68,23 @@
@Test
fun connectKeyboard() =
testScope.runTest {
- val now = Instant.now().toEpochMilli()
- underTest.updateConnectTime(KEYBOARD, now)
+ val now = Instant.now()
+ underTest.updateFirstConnectionTime(KEYBOARD, now)
assertThat(underTest.wasEverConnected(KEYBOARD)).isTrue()
- assertThat(underTest.connectTime(KEYBOARD)).isEqualTo(now)
+ assertThat(underTest.firstConnectionTime(KEYBOARD)!!.epochSecond)
+ .isEqualTo(now.epochSecond)
assertThat(underTest.wasEverConnected(TOUCHPAD)).isFalse()
}
@Test
fun launchKeyboard() =
testScope.runTest {
- underTest.updateLaunch(KEYBOARD)
+ val now = Instant.now()
+ underTest.updateLaunchTime(KEYBOARD, now)
assertThat(underTest.isLaunched(KEYBOARD)).isTrue()
+ assertThat(underTest.launchTime(KEYBOARD)!!.epochSecond).isEqualTo(now.epochSecond)
assertThat(underTest.isLaunched(TOUCHPAD)).isFalse()
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractorTest.kt
index 32d059b..a0fe538b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractorTest.kt
@@ -22,6 +22,7 @@
import com.android.systemui.SysuiTestCase
import com.android.systemui.authentication.data.repository.fakeAuthenticationRepository
import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
+import com.android.systemui.bouncer.domain.interactor.alternateBouncerInteractor
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor
import com.android.systemui.flags.EnableSceneContainer
@@ -29,6 +30,10 @@
import com.android.systemui.keyguard.shared.model.DismissAction
import com.android.systemui.keyguard.shared.model.KeyguardDone
import com.android.systemui.kosmos.testScope
+import com.android.systemui.power.data.repository.fakePowerRepository
+import com.android.systemui.power.domain.interactor.powerInteractor
+import com.android.systemui.power.shared.model.WakeSleepReason
+import com.android.systemui.power.shared.model.WakefulnessState
import com.android.systemui.scene.data.repository.Idle
import com.android.systemui.scene.data.repository.Transition
import com.android.systemui.scene.data.repository.setSceneTransition
@@ -82,6 +87,8 @@
deviceEntryInteractor = kosmos.deviceEntryInteractor,
quickSettingsSceneFamilyResolver = kosmos.quickSettingsSceneFamilyResolver,
notifShadeSceneFamilyResolver = kosmos.notifShadeSceneFamilyResolver,
+ powerInteractor = kosmos.powerInteractor,
+ alternateBouncerInteractor = kosmos.alternateBouncerInteractor,
)
}
@@ -234,6 +241,32 @@
}
@Test
+ fun resetDismissAction_onBouncer_OnAsleep() =
+ testScope.runTest {
+ kosmos.setSceneTransition(Idle(Scenes.Bouncer))
+ kosmos.fakeAuthenticationRepository.setAuthenticationMethod(
+ AuthenticationMethodModel.None
+ )
+ val resetDismissAction by collectLastValue(underTest.resetDismissAction)
+ keyguardRepository.setDismissAction(
+ DismissAction.RunAfterKeyguardGone(
+ dismissAction = {},
+ onCancelAction = {},
+ message = "message",
+ willAnimateOnLockscreen = true,
+ )
+ )
+ assertThat(resetDismissAction).isNull()
+ kosmos.fakePowerRepository.updateWakefulness(
+ rawState = WakefulnessState.ASLEEP,
+ lastWakeReason = WakeSleepReason.POWER_BUTTON,
+ lastSleepReason = WakeSleepReason.TIMEOUT,
+ powerButtonLaunchGestureTriggered = false,
+ )
+ assertThat(resetDismissAction).isEqualTo(Unit)
+ }
+
+ @Test
fun setDismissAction_callsCancelRunnableOnPreviousDismissAction() =
testScope.runTest {
val dismissAction by collectLastValue(underTest.dismissAction)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelTest.kt
index 24bea2c..73b9f57 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelTest.kt
@@ -20,6 +20,7 @@
import android.app.admin.DevicePolicyManager
import android.content.Intent
import android.os.UserHandle
+import android.platform.test.annotations.EnableFlags
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.internal.widget.LockPatternUtils
@@ -402,6 +403,67 @@
}
@Test
+ @EnableFlags(com.android.systemui.Flags.FLAG_NEW_PICKER_UI)
+ fun startButton_inPreviewMode_onPreviewQuickAffordanceSelected() =
+ testScope.runTest {
+ underTest.onPreviewSlotSelected(KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START)
+ underTest.enablePreviewMode(KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START, true)
+
+ repository.setKeyguardShowing(false)
+ val latest = collectLastValue(underTest.startButton)
+
+ val icon: Icon = mock()
+ val testConfig =
+ TestConfig(
+ isVisible = true,
+ isClickable = true,
+ isActivated = true,
+ icon = icon,
+ canShowWhileLocked = false,
+ intent = null,
+ slotId = KeyguardQuickAffordancePosition.BOTTOM_START.toSlotId(),
+ )
+ val defaultConfigKey =
+ setUpQuickAffordanceModel(
+ position = KeyguardQuickAffordancePosition.BOTTOM_START,
+ testConfig = testConfig,
+ )
+
+ // Set up the quick access wallet config
+ val quickAccessWalletAffordanceConfigKey =
+ quickAccessWalletAffordanceConfig
+ .apply {
+ onTriggeredResult =
+ KeyguardQuickAffordanceConfig.OnTriggeredResult.StartActivity(
+ intent = Intent("action"),
+ canShowWhileLocked = false,
+ )
+ setState(
+ KeyguardQuickAffordanceConfig.LockScreenState.Visible(
+ icon = icon,
+ activationState = ActivationState.Active,
+ )
+ )
+ }
+ .let {
+ KeyguardQuickAffordancePosition.BOTTOM_START.toSlotId() +
+ "::${quickAccessWalletAffordanceConfig.key}"
+ }
+
+ // onPreviewQuickAffordanceSelected should trigger the override with the quick access
+ // wallet quick affordance
+ underTest.onPreviewQuickAffordanceSelected(
+ KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START,
+ BuiltInKeyguardQuickAffordanceKeys.QUICK_ACCESS_WALLET,
+ )
+ Truth.assertThat(latest()?.configKey).isEqualTo(quickAccessWalletAffordanceConfigKey)
+
+ // onClearPreviewQuickAffordances should make the default quick affordance shows again
+ underTest.onClearPreviewQuickAffordances()
+ Truth.assertThat(latest()?.configKey).isEqualTo(defaultConfigKey)
+ }
+
+ @Test
fun startButton_inPreviewMode_visibleEvenWhenKeyguardNotShowing() =
testScope.runTest {
underTest.onPreviewSlotSelected(KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START)
@@ -445,7 +507,7 @@
}
@Test
- fun endButton_inHiglightedPreviewMode_dimmedWhenOtherIsSelected() =
+ fun endButton_inHighlightedPreviewMode_dimmedWhenOtherIsSelected() =
testScope.runTest {
underTest.onPreviewSlotSelected(KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START)
underTest.enablePreviewMode(KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START, true)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTest.java
index 68307b1..c1cf91d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTest.java
@@ -23,6 +23,8 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
import static com.android.systemui.Flags.FLAG_QS_CUSTOM_TILE_CLICK_GUARANTEED_BUG_FIX;
+import static com.google.common.truth.Truth.assertThat;
+
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
@@ -50,6 +52,7 @@
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo;
import android.net.Uri;
import android.os.Bundle;
@@ -183,6 +186,40 @@
.thenReturn(defaultPackageInfo);
}
+ private void setPackageInstalledForUser(
+ boolean installed,
+ boolean active,
+ boolean toggleable,
+ int user
+ ) throws Exception {
+ ServiceInfo defaultServiceInfo = null;
+ if (installed) {
+ defaultServiceInfo = new ServiceInfo();
+ defaultServiceInfo.metaData = new Bundle();
+ defaultServiceInfo.metaData.putBoolean(TileService.META_DATA_ACTIVE_TILE, active);
+ defaultServiceInfo.metaData
+ .putBoolean(TileService.META_DATA_TOGGLEABLE_TILE, toggleable);
+ when(mMockPackageManagerAdapter.getServiceInfo(any(), anyInt(), eq(user)))
+ .thenReturn(defaultServiceInfo);
+ if (user == 0) {
+ when(mMockPackageManagerAdapter.getServiceInfo(any(), anyInt()))
+ .thenReturn(defaultServiceInfo);
+ }
+ PackageInfo defaultPackageInfo = new PackageInfo();
+ when(mMockPackageManagerAdapter.getPackageInfoAsUser(anyString(), anyInt(), eq(user)))
+ .thenReturn(defaultPackageInfo);
+ } else {
+ when(mMockPackageManagerAdapter.getServiceInfo(any(), anyInt(), eq(user)))
+ .thenReturn(null);
+ if (user == 0) {
+ when(mMockPackageManagerAdapter.getServiceInfo(any(), anyInt()))
+ .thenThrow(new PackageManager.NameNotFoundException());
+ }
+ when(mMockPackageManagerAdapter.getPackageInfoAsUser(anyString(), anyInt(), eq(user)))
+ .thenThrow(new PackageManager.NameNotFoundException());
+ }
+ }
+
private void verifyBind(int times) {
assertEquals(times > 0, mContext.isBound(mTileServiceComponentName));
}
@@ -557,6 +594,100 @@
verify(mockContext).unbindService(captor.getValue());
}
+ @Test
+ public void testIsActive_user0_packageInstalled() throws Exception {
+ setPackageInstalledForUser(true, true, false, 0);
+ mUser = UserHandle.of(0);
+
+ TileLifecycleManager manager = new TileLifecycleManager(mHandler, mWrappedContext,
+ mock(IQSService.class),
+ mMockPackageManagerAdapter,
+ mMockBroadcastDispatcher,
+ mTileServiceIntent,
+ mUser,
+ mActivityManager,
+ mDeviceIdleController,
+ mExecutor);
+
+ assertThat(manager.isActiveTile()).isTrue();
+ }
+
+ @Test
+ public void testIsActive_user10_packageInstalled_notForUser0() throws Exception {
+ setPackageInstalledForUser(true, true, false, 10);
+ setPackageInstalledForUser(false, false, false, 0);
+ mUser = UserHandle.of(10);
+
+ TileLifecycleManager manager = new TileLifecycleManager(mHandler, mWrappedContext,
+ mock(IQSService.class),
+ mMockPackageManagerAdapter,
+ mMockBroadcastDispatcher,
+ mTileServiceIntent,
+ mUser,
+ mActivityManager,
+ mDeviceIdleController,
+ mExecutor);
+
+ assertThat(manager.isActiveTile()).isTrue();
+ }
+
+ @Test
+ public void testIsToggleable_user0_packageInstalled() throws Exception {
+ setPackageInstalledForUser(true, false, true, 0);
+ mUser = UserHandle.of(0);
+
+ TileLifecycleManager manager = new TileLifecycleManager(mHandler, mWrappedContext,
+ mock(IQSService.class),
+ mMockPackageManagerAdapter,
+ mMockBroadcastDispatcher,
+ mTileServiceIntent,
+ mUser,
+ mActivityManager,
+ mDeviceIdleController,
+ mExecutor);
+
+ assertThat(manager.isToggleableTile()).isTrue();
+ }
+
+ @Test
+ public void testIsToggleable_user10_packageInstalled_notForUser0() throws Exception {
+ setPackageInstalledForUser(true, false, true, 10);
+ setPackageInstalledForUser(false, false, false, 0);
+ mUser = UserHandle.of(10);
+
+ TileLifecycleManager manager = new TileLifecycleManager(mHandler, mWrappedContext,
+ mock(IQSService.class),
+ mMockPackageManagerAdapter,
+ mMockBroadcastDispatcher,
+ mTileServiceIntent,
+ mUser,
+ mActivityManager,
+ mDeviceIdleController,
+ mExecutor);
+
+ assertThat(manager.isToggleableTile()).isTrue();
+ }
+
+ @Test
+ public void testIsToggleableActive_installedForDifferentUser() throws Exception {
+ setPackageInstalledForUser(true, false, false, 10);
+ setPackageInstalledForUser(false, true, true, 0);
+ mUser = UserHandle.of(10);
+
+ TileLifecycleManager manager = new TileLifecycleManager(mHandler, mWrappedContext,
+ mock(IQSService.class),
+ mMockPackageManagerAdapter,
+ mMockBroadcastDispatcher,
+ mTileServiceIntent,
+ mUser,
+ mActivityManager,
+ mDeviceIdleController,
+ mExecutor);
+
+ assertThat(manager.isToggleableTile()).isFalse();
+ assertThat(manager.isActiveTile()).isFalse();
+ }
+
private void mockChangeEnabled(long changeId, boolean enabled) {
doReturn(enabled).when(() -> CompatChanges.isChangeEnabled(eq(changeId), anyString(),
any(UserHandle.class)));
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractorKosmos.kt
index 957f092..27eadb1 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractorKosmos.kt
@@ -16,10 +16,12 @@
package com.android.systemui.keyguard.domain.interactor
+import com.android.systemui.bouncer.domain.interactor.alternateBouncerInteractor
import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor
import com.android.systemui.keyguard.data.repository.keyguardRepository
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.testScope
+import com.android.systemui.power.domain.interactor.powerInteractor
import com.android.systemui.scene.domain.interactor.sceneInteractor
import com.android.systemui.scene.domain.resolver.notifShadeSceneFamilyResolver
import com.android.systemui.scene.domain.resolver.quickSettingsSceneFamilyResolver
@@ -37,5 +39,7 @@
deviceEntryInteractor = deviceEntryInteractor,
quickSettingsSceneFamilyResolver = quickSettingsSceneFamilyResolver,
notifShadeSceneFamilyResolver = notifShadeSceneFamilyResolver,
+ powerInteractor = powerInteractor,
+ alternateBouncerInteractor = alternateBouncerInteractor,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/lifecycle/FakeActivatable.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/lifecycle/FakeActivatable.kt
index bcc7393..4c05939 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/lifecycle/FakeActivatable.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/lifecycle/FakeActivatable.kt
@@ -21,7 +21,7 @@
class FakeActivatable(
private val onActivation: () -> Unit = {},
private val onDeactivation: () -> Unit = {},
-) : SafeActivatable() {
+) : BaseActivatable() {
var activationCount = 0
var cancellationCount = 0
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/impl/custom/data/repository/FakePackageManagerAdapterFacade.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/impl/custom/data/repository/FakePackageManagerAdapterFacade.kt
index fa8d363..5ac7c39 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/impl/custom/data/repository/FakePackageManagerAdapterFacade.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/impl/custom/data/repository/FakePackageManagerAdapterFacade.kt
@@ -18,14 +18,19 @@
import android.content.ComponentName
import android.content.pm.PackageInfo
+import android.content.pm.PackageManager
import android.content.pm.ServiceInfo
import android.os.Bundle
+import android.os.UserHandle
import com.android.systemui.qs.external.PackageManagerAdapter
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
+import org.hamcrest.BaseMatcher
+import org.hamcrest.Description
import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.hamcrest.MockitoHamcrest.intThat
/**
* Facade for [PackageManagerAdapter] to provide a fake-like behaviour. You can create this class
@@ -36,29 +41,26 @@
* [com.android.systemui.qs.external.TileServiceManager.isToggleableTile] or
* [com.android.systemui.qs.external.TileServiceManager.isActiveTile] when the real objects are
* used.
+ *
+ * The user this is set up must be a real user (`user >= 0`) or [UserHandle.USER_ALL].
*/
class FakePackageManagerAdapterFacade(
val componentName: ComponentName,
val packageManagerAdapter: PackageManagerAdapter = mock {},
+ user: Int = UserHandle.USER_ALL,
) {
private var isToggleable: Boolean = false
private var isActive: Boolean = false
init {
- whenever(packageManagerAdapter.getServiceInfo(eq(componentName), any())).thenAnswer {
- createServiceInfo()
+ if (user == UserHandle.USER_ALL) {
+ setForAllUsers()
+ } else if (user >= 0) {
+ setExclusiveForUser(user)
+ } else {
+ throw IllegalArgumentException("User must be a real user or UserHandle.USER_ALL")
}
- whenever(
- packageManagerAdapter.getPackageInfoAsUser(
- eq(componentName.packageName),
- anyInt(),
- anyInt()
- )
- )
- .thenAnswer { PackageInfo().apply { packageName = componentName.packageName } }
- whenever(packageManagerAdapter.getServiceInfo(eq(componentName), anyInt(), anyInt()))
- .thenAnswer { createServiceInfo() }
}
private fun createServiceInfo(): ServiceInfo {
@@ -84,4 +86,67 @@
fun setIsToggleable(isToggleable: Boolean) {
this.isToggleable = isToggleable
}
+
+ fun setExclusiveForUser(newUser: Int) {
+ check(newUser >= 0)
+ val notEqualMatcher = NotEqualMatcher(newUser)
+ if (newUser == 0) {
+ whenever(packageManagerAdapter.getServiceInfo(eq(componentName), any())).thenAnswer {
+ createServiceInfo()
+ }
+ }
+ whenever(
+ packageManagerAdapter.getPackageInfoAsUser(
+ eq(componentName.packageName),
+ anyInt(),
+ eq(newUser)
+ )
+ )
+ .thenAnswer { PackageInfo().apply { packageName = componentName.packageName } }
+ whenever(
+ packageManagerAdapter.getPackageInfoAsUser(
+ eq(componentName.packageName),
+ anyInt(),
+ intThat(notEqualMatcher),
+ )
+ )
+ .thenThrow(PackageManager.NameNotFoundException())
+
+ whenever(
+ packageManagerAdapter.getServiceInfo(
+ eq(componentName),
+ anyInt(),
+ intThat(notEqualMatcher)
+ )
+ )
+ .thenAnswer { null }
+ whenever(packageManagerAdapter.getServiceInfo(eq(componentName), anyInt(), eq(newUser)))
+ .thenAnswer { createServiceInfo() }
+ }
+
+ fun setForAllUsers() {
+ whenever(packageManagerAdapter.getServiceInfo(eq(componentName), any())).thenAnswer {
+ createServiceInfo()
+ }
+ whenever(
+ packageManagerAdapter.getPackageInfoAsUser(
+ eq(componentName.packageName),
+ anyInt(),
+ anyInt()
+ )
+ )
+ .thenAnswer { PackageInfo().apply { packageName = componentName.packageName } }
+ whenever(packageManagerAdapter.getServiceInfo(eq(componentName), anyInt(), anyInt()))
+ .thenAnswer { createServiceInfo() }
+ }
+}
+
+private class NotEqualMatcher(private val notEqualValue: Int) : BaseMatcher<Int>() {
+ override fun describeTo(description: Description?) {
+ description?.appendText("!= $notEqualValue")
+ }
+
+ override fun matches(item: Any?): Boolean {
+ return (item as? Int)?.equals(notEqualValue)?.not() ?: true
+ }
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/component/volume/domain/interactor/AudioSlidersInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/component/volume/domain/interactor/AudioSlidersInteractorKosmos.kt
index a0a39d1..63386d0 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/component/volume/domain/interactor/AudioSlidersInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/component/volume/domain/interactor/AudioSlidersInteractorKosmos.kt
@@ -17,15 +17,17 @@
package com.android.systemui.volume.panel.component.volume.domain.interactor
import com.android.systemui.kosmos.Kosmos
-import com.android.systemui.kosmos.testScope
+import com.android.systemui.kosmos.applicationCoroutineScope
import com.android.systemui.volume.data.repository.audioRepository
+import com.android.systemui.volume.domain.interactor.audioModeInteractor
import com.android.systemui.volume.mediaOutputInteractor
val Kosmos.audioSlidersInteractor by
Kosmos.Fixture {
AudioSlidersInteractor(
- testScope.backgroundScope,
+ applicationCoroutineScope,
mediaOutputInteractor,
audioRepository,
+ audioModeInteractor,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/component/volume/ui/viewmodel/VolumeSlidersViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/component/volume/ui/viewmodel/VolumeSlidersViewModelKosmos.kt
index 45a291e..6e848ce 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/component/volume/ui/viewmodel/VolumeSlidersViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/component/volume/ui/viewmodel/VolumeSlidersViewModelKosmos.kt
@@ -18,6 +18,7 @@
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.testScope
+import com.android.systemui.volume.domain.interactor.audioModeInteractor
import com.android.systemui.volume.mediaDeviceSessionInteractor
import com.android.systemui.volume.mediaOutputInteractor
import com.android.systemui.volume.panel.component.volume.domain.interactor.audioSlidersInteractor
@@ -32,6 +33,7 @@
mediaDeviceSessionInteractor,
audioStreamSliderViewModelFactory,
castVolumeSliderViewModelFactory,
+ audioModeInteractor,
audioSlidersInteractor,
)
}
diff --git a/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java b/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java
index 531fa45..09068d5 100644
--- a/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java
+++ b/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java
@@ -171,7 +171,7 @@
EXTENSIONS_VERSION.startsWith(LATENCY_VERSION_PREFIX) ||
EXTENSIONS_VERSION.startsWith(EFV_VERSION_PREFIX));
- private HashMap<String, Long> mMetadataVendorIdMap = new HashMap<>();
+ private static HashMap<String, Long> mMetadataVendorIdMap = new HashMap<>();
private CameraManager mCameraManager;
private static boolean checkForLatencyAPI() {
@@ -820,7 +820,7 @@
mCameraManager = getSystemService(CameraManager.class);
String [] cameraIds = mCameraManager.getCameraIdListNoLazy();
- if (cameraIds != null) {
+ if (cameraIds != null && mMetadataVendorIdMap.isEmpty()) {
for (String cameraId : cameraIds) {
CameraCharacteristics chars = mCameraManager.getCameraCharacteristics(cameraId);
Object thisClass = CameraCharacteristics.Key.class;
diff --git a/ravenwood/Android.bp b/ravenwood/Android.bp
index 6150343..58cd2e4 100644
--- a/ravenwood/Android.bp
+++ b/ravenwood/Android.bp
@@ -166,6 +166,14 @@
jarjar_rules: ":ravenwood-services-jarjar-rules",
}
+java_device_for_host {
+ name: "ravenwood-junit-impl-for-ravenizer",
+ libs: [
+ "ravenwood-junit-impl",
+ ],
+ visibility: [":__subpackages__"],
+}
+
// Separated out from ravenwood-junit-impl since it needs to compile
// against `module_current`
java_library {
diff --git a/ravenwood/minimum-test/test/com/android/ravenwood/RavenwoodMinimumTest.java b/ravenwood/minimum-test/test/com/android/ravenwoodtest/RavenwoodMinimumTest.java
similarity index 97%
rename from ravenwood/minimum-test/test/com/android/ravenwood/RavenwoodMinimumTest.java
rename to ravenwood/minimum-test/test/com/android/ravenwoodtest/RavenwoodMinimumTest.java
index b477117..30abaa2 100644
--- a/ravenwood/minimum-test/test/com/android/ravenwood/RavenwoodMinimumTest.java
+++ b/ravenwood/minimum-test/test/com/android/ravenwoodtest/RavenwoodMinimumTest.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.ravenwood;
+package com.android.ravenwoodtest;
import android.platform.test.annotations.IgnoreUnderRavenwood;
import android.platform.test.ravenwood.RavenwoodRule;
diff --git a/ravenwood/resapk_test/test/com/android/ravenwood/resapk_test/RavenwoodResApkTest.java b/ravenwood/resapk_test/test/com/android/ravenwoodtest/resapk_test/RavenwoodResApkTest.java
similarity index 96%
rename from ravenwood/resapk_test/test/com/android/ravenwood/resapk_test/RavenwoodResApkTest.java
rename to ravenwood/resapk_test/test/com/android/ravenwoodtest/resapk_test/RavenwoodResApkTest.java
index 1029ed2..e547114 100644
--- a/ravenwood/resapk_test/test/com/android/ravenwood/resapk_test/RavenwoodResApkTest.java
+++ b/ravenwood/resapk_test/test/com/android/ravenwoodtest/resapk_test/RavenwoodResApkTest.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.ravenwood.resapk_test;
+package com.android.ravenwoodtest.resapk_test;
import static junit.framework.TestCase.assertTrue;
diff --git a/ravenwood/runtime-test/test/com/android/ravenwood/runtimetest/OsConstantsTest.java b/ravenwood/runtime-test/test/com/android/ravenwoodtest/runtimetest/OsConstantsTest.java
similarity index 99%
rename from ravenwood/runtime-test/test/com/android/ravenwood/runtimetest/OsConstantsTest.java
rename to ravenwood/runtime-test/test/com/android/ravenwoodtest/runtimetest/OsConstantsTest.java
index 3332e24..633ed4e 100644
--- a/ravenwood/runtime-test/test/com/android/ravenwood/runtimetest/OsConstantsTest.java
+++ b/ravenwood/runtime-test/test/com/android/ravenwoodtest/runtimetest/OsConstantsTest.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.ravenwood.runtimetest;
+package com.android.ravenwoodtest.runtimetest;
// Copied from libcore/luni/src/test/java/libcore/android/system/OsConstantsTest.java
diff --git a/ravenwood/runtime-test/test/com/android/ravenwood/runtimetest/OsTest.java b/ravenwood/runtime-test/test/com/android/ravenwoodtest/runtimetest/OsTest.java
similarity index 99%
rename from ravenwood/runtime-test/test/com/android/ravenwood/runtimetest/OsTest.java
rename to ravenwood/runtime-test/test/com/android/ravenwoodtest/runtimetest/OsTest.java
index 05275b2..c2230c7 100644
--- a/ravenwood/runtime-test/test/com/android/ravenwood/runtimetest/OsTest.java
+++ b/ravenwood/runtime-test/test/com/android/ravenwoodtest/runtimetest/OsTest.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.ravenwood.runtimetest;
+package com.android.ravenwoodtest.runtimetest;
import static android.system.OsConstants.S_ISBLK;
import static android.system.OsConstants.S_ISCHR;
diff --git a/ravenwood/scripts/shrink-systemui-test b/ravenwood/scripts/shrink-systemui-test
new file mode 100755
index 0000000..8589c1d
--- /dev/null
+++ b/ravenwood/scripts/shrink-systemui-test
@@ -0,0 +1,131 @@
+#!/bin/bash
+# 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.
+
+set -e
+
+SCRIPT_NAME="${0##*/}"
+
+usage() {
+ cat <<"EOF"
+
+$SCRIPT_NAME: Shrink / unshrink SystemUiRavenTests.
+
+ SystemUiRavenTests has a lot of kotlin source files, so it's slow to build,
+ which is painful when you want to run it after updating ravenwood code
+ that SystemUiRavenTests depends on. (example: junit-src/)
+
+ This script basically removes the test files in SystemUI/multivalentTests
+ that don't have @EnabledOnRavenwood. But if we actaully remove them,
+ soong would re-generate the ninja file, which will take a long time,
+ so instead it'll truncate them.
+
+ This script will also tell git to ignore these files, so they won't shw up
+ in `git status`.
+ (Use `git ls-files -v | sed -ne "s/^[a-zS] //p"` to show ignored filse.)
+
+Usage:
+ $SCRIPT_NAME -s # Shrink the test files.
+
+ $SCRIPT_NAME -u # Undo it.
+
+EOF
+}
+
+TEST_PATH=${ANDROID_BUILD_TOP}/frameworks/base/packages/SystemUI/multivalentTests
+cd "$TEST_PATH"
+
+command=""
+case "$1" in
+ "-s") command=shrink ;;
+ "-u") command=unshrink ;;
+ *) usage ; exit 1 ;;
+esac
+
+
+echo "Listing test files...."
+files=( $(find . -name '*Test.kt' -o -name '*Test.java') )
+
+exemption='(BaseHeadsUpManagerTest)'
+
+shrink() {
+ local target=()
+ for file in ${files[@]}; do
+ # Check for exemption
+ if echo $file | egrep -q "$exemption"; then
+ echo " Skip exempted file"
+ continue
+ fi
+
+ echo "Checking $file"
+ if ! [[ -f $file ]] ; then
+ echo " Skip non regular file"
+ continue
+ fi
+
+ if ! [[ -s $file ]] ; then
+ echo " Skip empty file"
+ continue
+ fi
+
+ if grep -q '@EnabledOnRavenwood' $file ; then
+ echo " Skip ravenwood test file".
+ continue
+ fi
+
+ # It's a non ravenwood test file. Empty it.
+ : > $file
+
+ # Tell git to ignore the file
+
+ target+=($file)
+
+ echo " Emptied"
+
+ done
+ if (( ${#target[@]} == 0 )) ; then
+ echo "No files emptied."
+ return 0
+ fi
+
+ git update-index --skip-worktree ${target[@]}
+
+ echo "Emptied ${#target[@]} files"
+ return 0
+}
+
+unshrink() {
+ local target=()
+
+ # Collect empty files
+ for file in ${files[@]}; do
+ if [[ -s $file ]] ; then
+ continue
+ fi
+
+ target+=($file)
+ : > $file
+ done
+ if (( ${#target[@]} == 0 )) ; then
+ echo "No files to restore."
+ return 0
+ fi
+ # Un-ignore the files, and check out the original files
+ echo "Restoring ${#target[@]} files..."
+ git update-index --no-skip-worktree ${target[@]}
+ git checkout goog/main ${target[@]}
+ return 0
+}
+
+$command
diff --git a/ravenwood/tools/ravenizer/Android.bp b/ravenwood/tools/ravenizer/Android.bp
new file mode 100644
index 0000000..2892d07
--- /dev/null
+++ b/ravenwood/tools/ravenizer/Android.bp
@@ -0,0 +1,25 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
+java_binary_host {
+ name: "ravenizer",
+ main_class: "com.android.platform.test.ravenwood.ravenizer.RavenizerMain",
+ srcs: ["src/**/*.kt"],
+ static_libs: [
+ "hoststubgen-lib",
+ "ow2-asm",
+ "ow2-asm-analysis",
+ "ow2-asm-commons",
+ "ow2-asm-tree",
+ "ow2-asm-util",
+ "junit",
+ "ravenwood-junit-impl-for-ravenizer",
+ ],
+ visibility: ["//visibility:public"],
+}
diff --git a/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/Ravenizer.kt b/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/Ravenizer.kt
new file mode 100644
index 0000000..da9c7d9
--- /dev/null
+++ b/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/Ravenizer.kt
@@ -0,0 +1,212 @@
+/*
+ * 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.platform.test.ravenwood.ravenizer
+
+import com.android.hoststubgen.GeneralUserErrorException
+import com.android.hoststubgen.asm.ClassNodes
+import com.android.hoststubgen.asm.zipEntryNameToClassName
+import com.android.hoststubgen.executableName
+import com.android.hoststubgen.log
+import com.android.platform.test.ravenwood.ravenizer.adapter.TestRunnerRewritingAdapter
+import org.objectweb.asm.ClassReader
+import org.objectweb.asm.ClassVisitor
+import org.objectweb.asm.ClassWriter
+import org.objectweb.asm.util.CheckClassAdapter
+import java.io.BufferedInputStream
+import java.io.BufferedOutputStream
+import java.io.FileOutputStream
+import java.io.InputStream
+import java.io.OutputStream
+import java.util.zip.ZipEntry
+import java.util.zip.ZipFile
+import java.util.zip.ZipOutputStream
+
+/**
+ * Various stats on Ravenizer.
+ */
+data class RavenizerStats(
+ /** Total end-to-end time. */
+ var totalTime: Double = .0,
+
+ /** Time took to build [ClasNodes] */
+ var loadStructureTime: Double = .0,
+
+ /** Total real time spent for converting the jar file */
+ var totalProcessTime: Double = .0,
+
+ /** Total real time spent for converting class files (except for I/O time). */
+ var totalConversionTime: Double = .0,
+
+ /** Total real time spent for copying class files without modification. */
+ var totalCopyTime: Double = .0,
+
+ /** # of entries in the input jar file */
+ var totalEntiries: Int = 0,
+
+ /** # of *.class files in the input jar file */
+ var totalClasses: Int = 0,
+
+ /** # of *.class files that have been processed. */
+ var processedClasses: Int = 0,
+) {
+ override fun toString(): String {
+ return """
+ RavenizerStats{
+ totalTime=$totalTime,
+ loadStructureTime=$loadStructureTime,
+ totalProcessTime=$totalProcessTime,
+ totalConversionTime=$totalConversionTime,
+ totalCopyTime=$totalCopyTime,
+ totalEntiries=$totalEntiries,
+ totalClasses=$totalClasses,
+ processedClasses=$processedClasses,
+ }
+ """.trimIndent()
+ }
+}
+
+/**
+ * Main class.
+ */
+class Ravenizer(val options: RavenizerOptions) {
+ fun run() {
+ val stats = RavenizerStats()
+ stats.totalTime = log.nTime {
+ process(options.inJar.get, options.outJar.get, stats)
+ }
+ log.i(stats.toString())
+ }
+
+ private fun process(inJar: String, outJar: String, stats: RavenizerStats) {
+ var allClasses = ClassNodes.loadClassStructures(inJar) {
+ time -> stats.loadStructureTime = time
+ }
+
+ stats.totalProcessTime = log.iTime("$executableName processing $inJar") {
+ ZipFile(inJar).use { inZip ->
+ val inEntries = inZip.entries()
+
+ stats.totalEntiries = inZip.size()
+
+ ZipOutputStream(BufferedOutputStream(FileOutputStream(outJar))).use { outZip ->
+ while (inEntries.hasMoreElements()) {
+ val entry = inEntries.nextElement()
+
+ if (entry.name.endsWith(".dex")) {
+ // Seems like it's an ART jar file. We can't process it.
+ // It's a fatal error.
+ throw GeneralUserErrorException(
+ "$inJar is not a desktop jar file. It contains a *.dex file."
+ )
+ }
+
+ val className = zipEntryNameToClassName(entry.name)
+
+ if (className != null) {
+ stats.totalClasses += 1
+ }
+
+ if (className != null && shouldProcessClass(allClasses, className)) {
+ stats.processedClasses += 1
+ processSingleClass(inZip, entry, outZip, allClasses, stats)
+ } else {
+ // Too slow, let's use merge_zips to bring back the original classes.
+ copyZipEntry(inZip, entry, outZip, stats)
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Copy a single ZIP entry to the output.
+ */
+ private fun copyZipEntry(
+ inZip: ZipFile,
+ entry: ZipEntry,
+ out: ZipOutputStream,
+ stats: RavenizerStats,
+ ) {
+ stats.totalCopyTime += log.nTime {
+ inZip.getInputStream(entry).use { ins ->
+ // Copy unknown entries as is to the impl out. (but not to the stub out.)
+ val outEntry = ZipEntry(entry.name)
+ outEntry.method = 0
+ outEntry.size = entry.size
+ outEntry.crc = entry.crc
+ out.putNextEntry(outEntry)
+
+ ins.transferTo(out)
+
+ out.closeEntry()
+ }
+ }
+ }
+
+ private fun processSingleClass(
+ inZip: ZipFile,
+ entry: ZipEntry,
+ outZip: ZipOutputStream,
+ allClasses: ClassNodes,
+ stats: RavenizerStats,
+ ) {
+ val newEntry = ZipEntry(entry.name)
+ outZip.putNextEntry(newEntry)
+
+ BufferedInputStream(inZip.getInputStream(entry)).use { bis ->
+ processSingleClass(entry, bis, outZip, allClasses, stats)
+ }
+ outZip.closeEntry()
+ }
+
+ /**
+ * Whether a class needs to be processed. This must be kept in sync with [processSingleClass].
+ */
+ private fun shouldProcessClass(classes: ClassNodes, classInternalName: String): Boolean {
+ return TestRunnerRewritingAdapter.shouldProcess(classes, classInternalName)
+ }
+
+ private fun processSingleClass(
+ entry: ZipEntry,
+ input: InputStream,
+ output: OutputStream,
+ allClasses: ClassNodes,
+ stats: RavenizerStats,
+ ) {
+ val cr = ClassReader(input)
+
+ lateinit var data: ByteArray
+ stats.totalConversionTime += log.vTime("Modify ${entry.name}") {
+ val flags = ClassWriter.COMPUTE_MAXS
+ val cw = ClassWriter(flags)
+ var outVisitor: ClassVisitor = cw
+
+ val enableChecker = false
+ if (enableChecker) {
+ outVisitor = CheckClassAdapter(outVisitor)
+ }
+
+ // This must be kept in sync with shouldProcessClass.
+ outVisitor = TestRunnerRewritingAdapter(allClasses, outVisitor)
+
+ cr.accept(outVisitor, ClassReader.EXPAND_FRAMES)
+
+ data = cw.toByteArray()
+ }
+ output.write(data)
+ }
+}
diff --git a/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/RavenizerMain.kt b/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/RavenizerMain.kt
new file mode 100644
index 0000000..ff41818
--- /dev/null
+++ b/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/RavenizerMain.kt
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+@file:JvmName("RavenizerMain")
+
+package com.android.platform.test.ravenwood.ravenizer
+
+import com.android.hoststubgen.LogLevel
+import com.android.hoststubgen.executableName
+import com.android.hoststubgen.log
+import com.android.hoststubgen.runMainWithBoilerplate
+
+/**
+ * Entry point.
+ */
+fun main(args: Array<String>) {
+ executableName = "Ravenizer"
+ log.setConsoleLogLevel(LogLevel.Info)
+
+ runMainWithBoilerplate {
+ val options = RavenizerOptions.parseArgs(args)
+
+ log.i("$executableName started")
+ log.v("Options: $options")
+
+ // Run.
+ Ravenizer(options).run()
+ }
+}
diff --git a/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/RavenizerOptions.kt b/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/RavenizerOptions.kt
new file mode 100644
index 0000000..e85e3be
--- /dev/null
+++ b/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/RavenizerOptions.kt
@@ -0,0 +1,80 @@
+/*
+ * 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.platform.test.ravenwood.ravenizer
+
+import com.android.hoststubgen.ArgIterator
+import com.android.hoststubgen.ArgumentsException
+import com.android.hoststubgen.SetOnce
+import com.android.hoststubgen.ensureFileExists
+import com.android.hoststubgen.log
+
+class RavenizerOptions(
+ /** Input jar file*/
+ var inJar: SetOnce<String> = SetOnce(""),
+
+ /** Output jar file */
+ var outJar: SetOnce<String> = SetOnce(""),
+) {
+ companion object {
+ fun parseArgs(args: Array<String>): RavenizerOptions {
+ val ret = RavenizerOptions()
+ val ai = ArgIterator.withAtFiles(args)
+
+ while (true) {
+ val arg = ai.nextArgOptional()
+ if (arg == null) {
+ break
+ }
+
+ fun nextArg(): String = ai.nextArgRequired(arg)
+
+ if (log.maybeHandleCommandLineArg(arg) { nextArg() }) {
+ continue
+ }
+ try {
+ when (arg) {
+ // TODO: Write help
+ "-h", "--help" -> TODO("Help is not implemented yet")
+
+ "--in-jar" -> ret.inJar.set(nextArg()).ensureFileExists()
+ "--out-jar" -> ret.outJar.set(nextArg())
+
+ else -> throw ArgumentsException("Unknown option: $arg")
+ }
+ } catch (e: SetOnce.SetMoreThanOnceException) {
+ throw ArgumentsException("Duplicate or conflicting argument found: $arg")
+ }
+ }
+
+ if (!ret.inJar.isSet) {
+ throw ArgumentsException("Required option missing: --in-jar")
+ }
+ if (!ret.outJar.isSet) {
+ throw ArgumentsException("Required option missing: --out-jar")
+ }
+ return ret
+ }
+ }
+
+ override fun toString(): String {
+ return """
+ RavenizerOptions{
+ inJar=$inJar,
+ outJar=$outJar,
+ }
+ """.trimIndent()
+ }
+}
diff --git a/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/Utils.kt b/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/Utils.kt
new file mode 100644
index 0000000..0018648
--- /dev/null
+++ b/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/Utils.kt
@@ -0,0 +1,54 @@
+/*
+ * 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.platform.test.ravenwood.ravenizer
+
+import com.android.hoststubgen.asm.ClassNodes
+import com.android.hoststubgen.asm.findAnyAnnotation
+import org.objectweb.asm.Type
+
+val junitTestMethodType = Type.getType(org.junit.Test::class.java)
+val junitRunWithType = Type.getType(org.junit.runner.RunWith::class.java)
+
+val junitTestMethodDescriptor = junitTestMethodType.descriptor
+val junitRunWithDescriptor = junitRunWithType.descriptor
+
+val junitTestMethodDescriptors = setOf<String>(junitTestMethodDescriptor)
+val junitRunWithDescriptors = setOf<String>(junitRunWithDescriptor)
+
+/**
+ * Returns true, if a test looks like it's a test class which needs to be processed.
+ */
+fun isTestLookingClass(classes: ClassNodes, className: String): Boolean {
+ // Similar to com.android.tradefed.lite.HostUtils.testLoadClass(), except it's more lenient,
+ // and accept non-public and/or abstract classes.
+ // HostUtils also checks "Suppress" or "SuiteClasses" but this one doesn't.
+ // TODO: SuiteClasses may need to be supported.
+
+ val cn = classes.findClass(className) ?: return false
+
+ if (cn.findAnyAnnotation(junitRunWithDescriptors) != null) {
+ return true
+ }
+ cn.methods?.forEach { method ->
+ if (method.findAnyAnnotation(junitTestMethodDescriptors) != null) {
+ return true
+ }
+ }
+ if (cn.superName == null) {
+ return false
+ }
+ return isTestLookingClass(classes, cn.superName)
+}
diff --git a/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/adapter/TestRunnerRewritingAdapter.kt b/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/adapter/TestRunnerRewritingAdapter.kt
new file mode 100644
index 0000000..c539908
--- /dev/null
+++ b/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/adapter/TestRunnerRewritingAdapter.kt
@@ -0,0 +1,40 @@
+/*
+ * 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.platform.test.ravenwood.ravenizer.adapter
+
+import com.android.hoststubgen.asm.ClassNodes
+import com.android.hoststubgen.visitors.OPCODE_VERSION
+import com.android.platform.test.ravenwood.ravenizer.isTestLookingClass
+import org.objectweb.asm.ClassVisitor
+
+/**
+ * Class visitor to rewrite the test runner for Ravenwood
+ *
+ * TODO: Implement it.
+ */
+class TestRunnerRewritingAdapter(
+ protected val classes: ClassNodes,
+ nextVisitor: ClassVisitor,
+) : ClassVisitor(OPCODE_VERSION, nextVisitor) {
+ companion object {
+ /**
+ * Returns true if a target class is interesting to this adapter.
+ */
+ fun shouldProcess(classes: ClassNodes, className: String): Boolean {
+ return isTestLookingClass(classes, className)
+ }
+ }
+}
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java
index 5c6f99a..aa57e0b 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java
@@ -305,12 +305,8 @@
}
mDelegatingState = new DelegatingState();
- mDetectingState = Flags.enableMagnificationMultipleFingerMultipleTapGesture()
- ? new DetectingStateWithMultiFinger(context)
- : new DetectingState(context);
- mViewportDraggingState = Flags.enableMagnificationMultipleFingerMultipleTapGesture()
- ? new ViewportDraggingStateWithMultiFinger()
- : new ViewportDraggingState();
+ mDetectingState = new DetectingState(context);
+ mViewportDraggingState = new ViewportDraggingState();
mPanningScalingState = new PanningScalingState(context);
mSinglePanningState = new SinglePanningState(context);
mFullScreenMagnificationVibrationHelper = fullScreenMagnificationVibrationHelper;
@@ -701,62 +697,6 @@
}
}
- final class ViewportDraggingStateWithMultiFinger extends ViewportDraggingState {
- // LINT.IfChange(viewport_dragging_state_with_multi_finger)
- @Override
- public void onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags)
- throws GestureException {
- final int action = event.getActionMasked();
- switch (action) {
- case ACTION_POINTER_DOWN: {
- clearAndTransitToPanningScalingState();
- }
- break;
- case ACTION_MOVE: {
- if (event.getPointerCount() > 2) {
- throw new GestureException("Should have one pointer down.");
- }
- final float eventX = event.getX();
- final float eventY = event.getY();
- if (mFullScreenMagnificationController.magnificationRegionContains(
- mDisplayId, eventX, eventY)) {
- mFullScreenMagnificationController.setCenter(mDisplayId, eventX, eventY,
- /* animate */ mLastMoveOutsideMagnifiedRegion,
- AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
- mLastMoveOutsideMagnifiedRegion = false;
- } else {
- mLastMoveOutsideMagnifiedRegion = true;
- }
- }
- break;
-
- case ACTION_UP:
- case ACTION_CANCEL: {
- // If mScaleToRecoverAfterDraggingEnd >= 1.0, the dragging state is triggered
- // by zoom in temporary, and the magnifier needs to recover to original scale
- // after exiting dragging state.
- // Otherwise, the magnifier should be disabled.
- if (mScaleToRecoverAfterDraggingEnd >= 1.0f) {
- zoomToScale(mScaleToRecoverAfterDraggingEnd, event.getX(),
- event.getY());
- } else {
- zoomOff();
- }
- clear();
- mScaleToRecoverAfterDraggingEnd = Float.NaN;
- transitionTo(mDetectingState);
- }
- break;
-
- case ACTION_DOWN: {
- throw new GestureException(
- "Unexpected event type: " + MotionEvent.actionToString(action));
- }
- }
- }
- // LINT.ThenChange(:viewport_dragging_state)
- }
-
/**
* This class handles motion events when the event dispatcher has
* determined that the user is performing a single-finger drag of the
@@ -777,7 +717,6 @@
protected boolean mLastMoveOutsideMagnifiedRegion;
- // LINT.IfChange(viewport_dragging_state)
@Override
public void onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags)
throws GestureException {
@@ -788,7 +727,11 @@
}
break;
case ACTION_MOVE: {
- if (event.getPointerCount() != 1) {
+ if (Flags.enableMagnificationMultipleFingerMultipleTapGesture()) {
+ if (event.getPointerCount() > 2) {
+ throw new GestureException("Should have at most two pointers down.");
+ }
+ } else if (event.getPointerCount() != 1) {
throw new GestureException("Should have one pointer down.");
}
final float eventX = event.getX();
@@ -823,14 +766,20 @@
}
break;
- case ACTION_DOWN:
case ACTION_POINTER_UP: {
+ if (!Flags.enableMagnificationMultipleFingerMultipleTapGesture()) {
+ throw new GestureException(
+ "Unexpected event type: " + MotionEvent.actionToString(action));
+ }
+ }
+ break;
+
+ case ACTION_DOWN: {
throw new GestureException(
"Unexpected event type: " + MotionEvent.actionToString(action));
}
}
}
- // LINT.ThenChange(:viewport_dragging_state_with_multi_finger)
private boolean isAlwaysOnMagnificationEnabled() {
return mFullScreenMagnificationController.isAlwaysOnMagnificationEnabled();
@@ -916,270 +865,31 @@
}
}
- final class DetectingStateWithMultiFinger extends DetectingState {
- private static final int TWO_FINGER_GESTURE_MAX_TAPS = 2;
- // A flag set to true when two fingers have touched down.
- // Used to indicate what next finger action should be.
- private boolean mIsTwoFingerCountReached = false;
- // A tap counts when two fingers are down and up once.
- private int mCompletedTapCount = 0;
- DetectingStateWithMultiFinger(Context context) {
- super(context);
- }
-
- // LINT.IfChange(detecting_state_with_multi_finger)
- @Override
- public void onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
- cacheDelayedMotionEvent(event, rawEvent, policyFlags);
- switch (event.getActionMasked()) {
- case MotionEvent.ACTION_DOWN: {
- mLastDetectingDownEventTime = event.getDownTime();
- mHandler.removeMessages(MESSAGE_TRANSITION_TO_DELEGATING_STATE);
-
- mFirstPointerDownLocation.set(event.getX(), event.getY());
-
- if (!mFullScreenMagnificationController.magnificationRegionContains(
- mDisplayId, event.getX(), event.getY())) {
-
- transitionToDelegatingStateAndClear();
-
- } else if (isMultiTapTriggered(2 /* taps */)) {
-
- // 3tap and hold
- afterLongTapTimeoutTransitionToDraggingState(event);
-
- } else if (isTapOutOfDistanceSlop()) {
-
- transitionToDelegatingStateAndClear();
-
- } else if (mDetectSingleFingerTripleTap
- || mDetectTwoFingerTripleTap
- // If activated, delay an ACTION_DOWN for mMultiTapMaxDelay
- // to ensure reachability of
- // STATE_PANNING_SCALING(triggerable with ACTION_POINTER_DOWN)
- || isActivated()) {
-
- afterMultiTapTimeoutTransitionToDelegatingState();
-
- } else {
-
- // Delegate pending events without delay
- transitionToDelegatingStateAndClear();
- }
- }
- break;
- case ACTION_POINTER_DOWN: {
- mIsTwoFingerCountReached = mDetectTwoFingerTripleTap
- && event.getPointerCount() == 2;
- mHandler.removeMessages(MESSAGE_TRANSITION_TO_DELEGATING_STATE);
-
- if (event.getPointerCount() == 2) {
- if (isMultiFingerMultiTapTriggered(
- TWO_FINGER_GESTURE_MAX_TAPS - 1, event)) {
- // 3tap and hold
- afterLongTapTimeoutTransitionToDraggingState(event);
- } else {
- if (mDetectTwoFingerTripleTap) {
- // If mDetectTwoFingerTripleTap, delay transition to the delegating
- // state for mMultiTapMaxDelay to ensure reachability of
- // multi finger multi tap
- afterMultiTapTimeoutTransitionToDelegatingState();
- }
-
- if (isActivated()) {
- // If activated, delay transition to the panning scaling
- // state for tap timeout to ensure reachability of
- // multi finger multi tap
- storePointerDownLocation(mSecondPointerDownLocation, event);
- mHandler.sendEmptyMessageDelayed(
- MESSAGE_TRANSITION_TO_PANNINGSCALING_STATE,
- ViewConfiguration.getTapTimeout());
- }
- }
- } else {
- transitionToDelegatingStateAndClear();
- }
- }
- break;
- case ACTION_POINTER_UP: {
- // If it is a two-finger gesture, do not transition to the delegating state
- // to ensure the reachability of
- // the two-finger triple tap (triggerable with ACTION_MOVE and ACTION_UP)
- if (!mIsTwoFingerCountReached) {
- transitionToDelegatingStateAndClear();
- }
- }
- break;
- case ACTION_MOVE: {
- if (isFingerDown()
- && distance(mLastDown, /* move */ event) > mSwipeMinDistance) {
- // Swipe detected - transition immediately
-
- // For convenience, viewport dragging takes precedence
- // over insta-delegating on 3tap&swipe
- // (which is a rare combo to be used aside from magnification)
- if (isMultiTapTriggered(2 /* taps */) && event.getPointerCount() == 1) {
- transitionToViewportDraggingStateAndClear(event);
- } else if (isMultiFingerMultiTapTriggered(
- TWO_FINGER_GESTURE_MAX_TAPS - 1, event)
- && event.getPointerCount() == 2) {
- transitionToViewportDraggingStateAndClear(event);
- } else if (isActivated() && event.getPointerCount() == 2) {
- if (mOverscrollHandler != null
- && overscrollState(event, mFirstPointerDownLocation)
- == OVERSCROLL_VERTICAL_EDGE) {
- transitionToDelegatingStateAndClear();
- } else {
- //Primary pointer is swiping, so transit to PanningScalingState
- transitToPanningScalingStateAndClear();
- }
- } else if (mOneFingerPanningSettingsProvider.isOneFingerPanningEnabled()
- && isActivated()
- && event.getPointerCount() == 1) {
- if (mOverscrollHandler != null
- && overscrollState(event, mFirstPointerDownLocation)
- == OVERSCROLL_VERTICAL_EDGE) {
- transitionToDelegatingStateAndClear();
- } else if (overscrollState(event, mFirstPointerDownLocation)
- != OVERSCROLL_NONE) {
- transitionToDelegatingStateAndClear();
- } else {
- transitToSinglePanningStateAndClear();
- }
- } else if (!mIsTwoFingerCountReached) {
- // If it is a two-finger gesture, do not transition to the
- // delegating state to ensure the reachability of
- // the two-finger triple tap (triggerable with ACTION_UP)
- transitionToDelegatingStateAndClear();
- }
- } else if (isActivated() && pointerDownValid(mSecondPointerDownLocation)
- && distanceClosestPointerToPoint(
- mSecondPointerDownLocation, /* move */ event) > mSwipeMinDistance) {
- // Second pointer is swiping, so transit to PanningScalingState
- // Delay an ACTION_MOVE for tap timeout to ensure it is not trigger from
- // multi finger multi tap
- storePointerDownLocation(mSecondPointerDownLocation, event);
- mHandler.sendEmptyMessageDelayed(
- MESSAGE_TRANSITION_TO_PANNINGSCALING_STATE,
- ViewConfiguration.getTapTimeout());
- }
- }
- break;
- case ACTION_UP: {
-
- mHandler.removeMessages(MESSAGE_ON_TRIPLE_TAP_AND_HOLD);
- mHandler.removeMessages(MESSAGE_TRANSITION_TO_PANNINGSCALING_STATE);
-
- if (!mFullScreenMagnificationController.magnificationRegionContains(
- mDisplayId, event.getX(), event.getY())) {
- transitionToDelegatingStateAndClear();
-
- } else if (isMultiFingerMultiTapTriggered(TWO_FINGER_GESTURE_MAX_TAPS, event)) {
- // Placing multiple fingers before a single finger, because achieving a
- // multi finger multi tap also means achieving a single finger triple tap
- onTripleTap(event);
-
- } else if (isMultiTapTriggered(3 /* taps */)) {
- onTripleTap(/* up */ event);
-
- } else if (
- // Possible to be false on: 3tap&drag -> scale -> PTR_UP -> UP
- isFingerDown()
- //TODO long tap should never happen here
- && ((timeBetween(mLastDown, mLastUp) >= mLongTapMinDelay)
- || (distance(mLastDown, mLastUp) >= mSwipeMinDistance))
- // If it is a two-finger but not reach 3 tap, do not transition to the
- // delegating state to ensure the reachability of the triple tap
- && mCompletedTapCount == 0) {
- transitionToDelegatingStateAndClear();
-
- }
- }
- break;
- }
- }
- // LINT.ThenChange(:detecting_state)
-
- @Override
- public void clear() {
- mCompletedTapCount = 0;
- setShortcutTriggered(false);
- removePendingDelayedMessages();
- clearDelayedMotionEvents();
- mFirstPointerDownLocation.set(Float.NaN, Float.NaN);
- mSecondPointerDownLocation.set(Float.NaN, Float.NaN);
- }
-
- private boolean isMultiFingerMultiTapTriggered(int targetTapCount, MotionEvent event) {
- if (event.getActionMasked() == ACTION_UP && mIsTwoFingerCountReached) {
- mCompletedTapCount++;
- mIsTwoFingerCountReached = false;
- }
-
- if (mDetectTwoFingerTripleTap && mCompletedTapCount > TWO_FINGER_GESTURE_MAX_TAPS - 1) {
- final boolean enabled = !isActivated();
- mMagnificationLogger.logMagnificationTwoFingerTripleTap(enabled);
- }
- return mDetectTwoFingerTripleTap && mCompletedTapCount == targetTapCount;
- }
-
- void transitionToDelegatingStateAndClear() {
- mCompletedTapCount = 0;
- transitionTo(mDelegatingState);
- sendDelayedMotionEvents();
- removePendingDelayedMessages();
- mFirstPointerDownLocation.set(Float.NaN, Float.NaN);
- mSecondPointerDownLocation.set(Float.NaN, Float.NaN);
- }
-
- void transitionToViewportDraggingStateAndClear(MotionEvent down) {
-
- if (DEBUG_DETECTING) Slog.i(mLogTag, "onTripleTapAndHold()");
- final boolean shortcutTriggered = mShortcutTriggered;
-
- // Only log the 3tap and hold event
- if (!shortcutTriggered) {
- final boolean enabled = !isActivated();
- if (mCompletedTapCount == TWO_FINGER_GESTURE_MAX_TAPS - 1) {
- // Two finger triple tap and hold
- mMagnificationLogger.logMagnificationTwoFingerTripleTap(enabled);
- } else {
- // Triple tap and hold also belongs to triple tap event
- mMagnificationLogger.logMagnificationTripleTap(enabled);
- }
- }
- clear();
-
- mViewportDraggingState.prepareForZoomInTemporary(shortcutTriggered);
- zoomInTemporary(down.getX(), down.getY(), shortcutTriggered);
- transitionTo(mViewportDraggingState);
- }
- }
-
/**
* This class handles motion events when the event dispatch has not yet
* determined what the user is doing. It watches for various tap events.
*/
class DetectingState implements State, Handler.Callback {
- protected static final int MESSAGE_ON_TRIPLE_TAP_AND_HOLD = 1;
- protected static final int MESSAGE_TRANSITION_TO_DELEGATING_STATE = 2;
- protected static final int MESSAGE_TRANSITION_TO_PANNINGSCALING_STATE = 3;
+ private static final int MESSAGE_ON_TRIPLE_TAP_AND_HOLD = 1;
+ private static final int MESSAGE_TRANSITION_TO_DELEGATING_STATE = 2;
+ private static final int MESSAGE_TRANSITION_TO_PANNINGSCALING_STATE = 3;
final int mLongTapMinDelay;
final int mSwipeMinDistance;
final int mMultiTapMaxDelay;
final int mMultiTapMaxDistance;
+ @Nullable final TwoFingerDoubleTapHandler mTwoFingerDoubleTapHandler;
- protected MotionEventInfo mDelayedEventQueue;
- protected MotionEvent mLastDown;
- protected MotionEvent mPreLastDown;
- protected MotionEvent mLastUp;
- protected MotionEvent mPreLastUp;
+ private MotionEventInfo mDelayedEventQueue;
+ private MotionEvent mLastDown;
+ private MotionEvent mPreLastDown;
+ private MotionEvent mLastUp;
+ private MotionEvent mPreLastUp;
- protected PointF mFirstPointerDownLocation = new PointF(Float.NaN, Float.NaN);
- protected PointF mSecondPointerDownLocation = new PointF(Float.NaN, Float.NaN);
- protected long mLastDetectingDownEventTime;
+ private PointF mFirstPointerDownLocation = new PointF(Float.NaN, Float.NaN);
+ private PointF mSecondPointerDownLocation = new PointF(Float.NaN, Float.NaN);
+ private long mLastDetectingDownEventTime;
@VisibleForTesting boolean mShortcutTriggered;
@@ -1191,6 +901,9 @@
MagnificationGestureMatcher.getMagnificationMultiTapTimeout(context);
mSwipeMinDistance = ViewConfiguration.get(context).getScaledTouchSlop();
mMultiTapMaxDistance = ViewConfiguration.get(context).getScaledDoubleTapSlop();
+ mTwoFingerDoubleTapHandler =
+ Flags.enableMagnificationMultipleFingerMultipleTapGesture()
+ ? new TwoFingerDoubleTapHandler() : null;
}
@Override
@@ -1218,7 +931,6 @@
return true;
}
- // LINT.IfChange(detecting_state)
@Override
public void onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
cacheDelayedMotionEvent(event, rawEvent, policyFlags);
@@ -1244,6 +956,7 @@
transitionToDelegatingStateAndClear();
} else if (mDetectSingleFingerTripleTap
+ || (mTwoFingerDoubleTapHandler != null && mDetectTwoFingerTripleTap)
// If activated, delay an ACTION_DOWN for mMultiTapMaxDelay
// to ensure reachability of
// STATE_PANNING_SCALING(triggerable with ACTION_POINTER_DOWN)
@@ -1259,6 +972,12 @@
}
break;
case ACTION_POINTER_DOWN: {
+ if (mTwoFingerDoubleTapHandler != null) {
+ mTwoFingerDoubleTapHandler.onPointerDown(event);
+ break;
+ }
+
+ // LINT.IfChange(action_pointer_down)
if (isActivated() && event.getPointerCount() == 2) {
storePointerDownLocation(mSecondPointerDownLocation, event);
mHandler.sendEmptyMessageDelayed(MESSAGE_TRANSITION_TO_PANNINGSCALING_STATE,
@@ -1266,13 +985,26 @@
} else {
transitionToDelegatingStateAndClear();
}
+ // LINT.ThenChange(:action_pointer_down_with_multi_finger)
}
break;
case ACTION_POINTER_UP: {
+ if (mTwoFingerDoubleTapHandler != null) {
+ mTwoFingerDoubleTapHandler.onPointerUp();
+ break;
+ }
+ // LINT.IfChange(action_pointer_up)
transitionToDelegatingStateAndClear();
+ // LINT.ThenChange(:action_pointer_up_with_multi_finger)
}
break;
case ACTION_MOVE: {
+ if (mTwoFingerDoubleTapHandler != null) {
+ mTwoFingerDoubleTapHandler.onMove(event);
+ break;
+ }
+
+ // LINT.IfChange(action_move)
if (isFingerDown()
&& distance(mLastDown, /* move */ event) > mSwipeMinDistance) {
// Swipe detected - transition immediately
@@ -1313,12 +1045,20 @@
//Second pointer is swiping, so transit to PanningScalingState
transitToPanningScalingStateAndClear();
}
+ // LINT.ThenChange(:action_move_with_multi_finger)
}
break;
case ACTION_UP: {
mHandler.removeMessages(MESSAGE_ON_TRIPLE_TAP_AND_HOLD);
+ if (mTwoFingerDoubleTapHandler != null) {
+ mHandler.removeMessages(MESSAGE_TRANSITION_TO_PANNINGSCALING_STATE);
+ mTwoFingerDoubleTapHandler.onUp(event);
+ break;
+ }
+
+ // LINT.IfChange(action_up)
if (!mFullScreenMagnificationController.magnificationRegionContains(
mDisplayId, event.getX(), event.getY())) {
transitionToDelegatingStateAndClear();
@@ -1335,11 +1075,11 @@
transitionToDelegatingStateAndClear();
}
+ // LINT.ThenChange(:action_up_with_multi_finger)
}
break;
}
}
- // LINT.ThenChange(:detecting_state_with_multi_finger)
protected void storePointerDownLocation(PointF pointerDownLocation, MotionEvent event) {
final int index = event.getActionIndex();
@@ -1425,6 +1165,9 @@
@Override
public void clear() {
+ if (mTwoFingerDoubleTapHandler != null) {
+ mTwoFingerDoubleTapHandler.mCompletedTapCount = 0;
+ }
setShortcutTriggered(false);
removePendingDelayedMessages();
clearDelayedMotionEvents();
@@ -1501,9 +1244,13 @@
}
void transitionToDelegatingStateAndClear() {
+ if (mTwoFingerDoubleTapHandler != null) {
+ mTwoFingerDoubleTapHandler.mCompletedTapCount = 0;
+ }
transitionTo(mDelegatingState);
sendDelayedMotionEvents();
removePendingDelayedMessages();
+ mFirstPointerDownLocation.set(Float.NaN, Float.NaN);
mSecondPointerDownLocation.set(Float.NaN, Float.NaN);
}
@@ -1543,9 +1290,15 @@
// Only log the 3tap and hold event
if (!shortcutTriggered) {
- // Triple tap and hold also belongs to triple tap event
final boolean enabled = !isActivated();
- mMagnificationLogger.logMagnificationTripleTap(enabled);
+ if (mTwoFingerDoubleTapHandler != null
+ && mTwoFingerDoubleTapHandler.shouldLogTwoFingerDoubleTap()) {
+ // Two finger double tap and hold
+ mMagnificationLogger.logMagnificationTwoFingerTripleTap(enabled);
+ } else {
+ // Triple tap and hold also belongs to triple tap event
+ mMagnificationLogger.logMagnificationTripleTap(enabled);
+ }
}
clear();
@@ -1604,6 +1357,173 @@
}
return false;
}
+
+ final class TwoFingerDoubleTapHandler {
+ private static final int TWO_FINGER_GESTURE_MAX_TAPS = 2;
+ // A tap counts when two fingers are down and up once.
+ private int mCompletedTapCount;
+ // A flag set to true when two fingers have touched down.
+ // Used to indicate what next finger action should be.
+ private boolean mIsTwoFingerCountReached;
+
+ TwoFingerDoubleTapHandler() {
+ mCompletedTapCount = 0;
+ mIsTwoFingerCountReached = false;
+ }
+
+ private void onPointerDown(MotionEvent event) {
+ mIsTwoFingerCountReached = mDetectTwoFingerTripleTap
+ && event.getPointerCount() == 2;
+ mHandler.removeMessages(MESSAGE_TRANSITION_TO_DELEGATING_STATE);
+
+ // LINT.IfChange(action_pointer_down_with_multi_finger)
+ if (event.getPointerCount() == 2) {
+ if (isMultiFingerMultiTapTriggered(
+ TWO_FINGER_GESTURE_MAX_TAPS - 1, event)) {
+ // 3tap and hold
+ afterLongTapTimeoutTransitionToDraggingState(event);
+ } else {
+ if (mDetectTwoFingerTripleTap) {
+ // If mDetectTwoFingerTripleTap, delay transition to the delegating
+ // state for mMultiTapMaxDelay to ensure reachability of
+ // multi finger multi tap
+ afterMultiTapTimeoutTransitionToDelegatingState();
+ }
+
+ if (isActivated()) {
+ // If activated, delay transition to the panning scaling
+ // state for tap timeout to ensure reachability of
+ // multi finger multi tap
+ storePointerDownLocation(mSecondPointerDownLocation, event);
+ mHandler.sendEmptyMessageDelayed(
+ MESSAGE_TRANSITION_TO_PANNINGSCALING_STATE,
+ ViewConfiguration.getTapTimeout());
+ }
+ }
+ } else {
+ transitionToDelegatingStateAndClear();
+ }
+ // LINT.ThenChange(:action_pointer_down)
+ }
+
+ private void onMove(MotionEvent event) {
+ // LINT.IfChange(action_move_with_multi_finger)
+ if (isFingerDown()
+ && distance(mLastDown, /* move */ event) > mSwipeMinDistance) {
+ // Swipe detected - transition immediately
+
+ // For convenience, viewport dragging takes precedence
+ // over insta-delegating on 3tap&swipe
+ // (which is a rare combo to be used aside from magnification)
+ if (isMultiTapTriggered(2 /* taps */) && event.getPointerCount() == 1) {
+ transitionToViewportDraggingStateAndClear(event);
+ } else if (isMultiFingerMultiTapTriggered(
+ TWO_FINGER_GESTURE_MAX_TAPS - 1, event)
+ && event.getPointerCount() == 2) {
+ transitionToViewportDraggingStateAndClear(event);
+ } else if (isActivated() && event.getPointerCount() == 2) {
+ if (mOverscrollHandler != null
+ && overscrollState(event, mFirstPointerDownLocation)
+ == OVERSCROLL_VERTICAL_EDGE) {
+ transitionToDelegatingStateAndClear();
+ } else {
+ //Primary pointer is swiping, so transit to PanningScalingState
+ transitToPanningScalingStateAndClear();
+ }
+ } else if (mOneFingerPanningSettingsProvider.isOneFingerPanningEnabled()
+ && isActivated()
+ && event.getPointerCount() == 1) {
+ if (mOverscrollHandler != null
+ && overscrollState(event, mFirstPointerDownLocation)
+ == OVERSCROLL_VERTICAL_EDGE) {
+ transitionToDelegatingStateAndClear();
+ } else if (overscrollState(event, mFirstPointerDownLocation)
+ != OVERSCROLL_NONE) {
+ transitionToDelegatingStateAndClear();
+ } else {
+ transitToSinglePanningStateAndClear();
+ }
+ } else if (!mIsTwoFingerCountReached) {
+ // If it is a two-finger gesture, do not transition to the
+ // delegating state to ensure the reachability of
+ // the two-finger triple tap (triggerable with ACTION_UP)
+ transitionToDelegatingStateAndClear();
+ }
+ } else if (isActivated() && pointerDownValid(mSecondPointerDownLocation)
+ && distanceClosestPointerToPoint(
+ mSecondPointerDownLocation, /* move */ event) > mSwipeMinDistance) {
+ // Second pointer is swiping, so transit to PanningScalingState
+ // Delay an ACTION_MOVE for tap timeout to ensure it is not trigger from
+ // multi finger multi tap
+ storePointerDownLocation(mSecondPointerDownLocation, event);
+ mHandler.sendEmptyMessageDelayed(
+ MESSAGE_TRANSITION_TO_PANNINGSCALING_STATE,
+ ViewConfiguration.getTapTimeout());
+ }
+ // LINT.ThenChange(:action_move)
+ }
+
+ private void onPointerUp() {
+ // If it is a two-finger gesture, do not transition to the delegating state
+ // to ensure the reachability of
+ // the two-finger triple tap (triggerable with ACTION_MOVE and ACTION_UP)
+ // LINT.IfChange(action_pointer_up_with_multi_finger)
+ if (!mIsTwoFingerCountReached) {
+ transitionToDelegatingStateAndClear();
+ }
+ // LINT.ThenChange(:action_pointer_up)
+ }
+
+ private void onUp(MotionEvent event) {
+ // LINT.IfChange(action_up_with_multi_finger)
+ if (!mFullScreenMagnificationController.magnificationRegionContains(
+ mDisplayId, event.getX(), event.getY())) {
+ transitionToDelegatingStateAndClear();
+
+ } else if (isMultiFingerMultiTapTriggered(
+ TWO_FINGER_GESTURE_MAX_TAPS, event)) {
+ // Placing multiple fingers before a single finger, because achieving a
+ // multi finger multi tap also means achieving a single finger
+ // triple tap
+ onTripleTap(event);
+
+ } else if (isMultiTapTriggered(3 /* taps */)) {
+ onTripleTap(/* up */ event);
+
+ } else if (
+ // Possible to be false on: 3tap&drag -> scale -> PTR_UP -> UP
+ isFingerDown()
+ //TODO long tap should never happen here
+ && ((timeBetween(mLastDown, mLastUp) >= mLongTapMinDelay)
+ || (distance(mLastDown, mLastUp) >= mSwipeMinDistance))
+ // If it is a two-finger but not reach 3 tap, do not
+ // transition to the delegating state to ensure the
+ // reachability of the triple tap
+ && mCompletedTapCount == 0) {
+ transitionToDelegatingStateAndClear();
+ }
+ // LINT.ThenChange(:action_up)
+ }
+
+ private boolean isMultiFingerMultiTapTriggered(int targetTapCount, MotionEvent event) {
+ if (event.getActionMasked() == ACTION_UP && mIsTwoFingerCountReached) {
+ mCompletedTapCount++;
+ mIsTwoFingerCountReached = false;
+ }
+
+ if (mDetectTwoFingerTripleTap
+ && mCompletedTapCount > TWO_FINGER_GESTURE_MAX_TAPS - 1) {
+ final boolean enabled = !isActivated();
+ mMagnificationLogger.logMagnificationTwoFingerTripleTap(enabled);
+ }
+ return mDetectTwoFingerTripleTap && mCompletedTapCount == targetTapCount;
+ }
+
+ private boolean shouldLogTwoFingerDoubleTap() {
+ return mCompletedTapCount
+ == TwoFingerDoubleTapHandler.TWO_FINGER_GESTURE_MAX_TAPS - 1;
+ }
+ }
}
private void zoomInTemporary(float centerX, float centerY, boolean shortcutTriggered) {
diff --git a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
index 2db5443..1be352e 100644
--- a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
+++ b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
@@ -137,11 +137,6 @@
| DisplayManager.VIRTUAL_DISPLAY_FLAG_SUPPORTS_TOUCH
| DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_FOCUS;
- private static final int DEFAULT_VIRTUAL_DISPLAY_FLAGS_PRE_VIC =
- DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC
- | DisplayManager.VIRTUAL_DISPLAY_FLAG_ROTATES_WITH_CONTENT
- | DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY;
-
private static final String PERSISTENT_ID_PREFIX_CDM_ASSOCIATION = "companion:";
/**
@@ -373,9 +368,6 @@
}
int flags = DEFAULT_VIRTUAL_DISPLAY_FLAGS;
- if (!Flags.consistentDisplayFlags()) {
- flags |= DEFAULT_VIRTUAL_DISPLAY_FLAGS_PRE_VIC;
- }
if (mParams.getLockState() == VirtualDeviceParams.LOCK_STATE_ALWAYS_UNLOCKED) {
flags |= DisplayManager.VIRTUAL_DISPLAY_FLAG_ALWAYS_UNLOCKED;
}
@@ -1254,10 +1246,6 @@
// as the virtual display doesn't have any focused windows. Hence, call this for
// associating any input device to the source display if the input device emits any key events.
private int getTargetDisplayIdForInput(int displayId) {
- if (!Flags.interactiveScreenMirror()) {
- return displayId;
- }
-
DisplayManagerInternal displayManager = LocalServices.getService(
DisplayManagerInternal.class);
int mirroredDisplayId = displayManager.getDisplayIdToMirror(displayId);
@@ -1313,9 +1301,9 @@
int displayId;
displayId = mDisplayManagerInternal.createVirtualDisplay(virtualDisplayConfig, callback,
this, gwpc, packageName);
- gwpc.setDisplayId(displayId, /* isMirrorDisplay= */ Flags.interactiveScreenMirror()
- && mDisplayManagerInternal.getDisplayIdToMirror(displayId)
- != Display.INVALID_DISPLAY);
+ boolean isMirrorDisplay =
+ mDisplayManagerInternal.getDisplayIdToMirror(displayId) != Display.INVALID_DISPLAY;
+ gwpc.setDisplayId(displayId, isMirrorDisplay);
boolean showPointer;
synchronized (mVirtualDeviceLock) {
diff --git a/services/core/java/com/android/server/PackageWatchdog.java b/services/core/java/com/android/server/PackageWatchdog.java
index 0815384..e84250d 100644
--- a/services/core/java/com/android/server/PackageWatchdog.java
+++ b/services/core/java/com/android/server/PackageWatchdog.java
@@ -309,13 +309,14 @@
*/
public void registerHealthObserver(PackageHealthObserver observer) {
synchronized (mLock) {
- ObserverInternal internalObserver = mAllObservers.get(observer.getName());
+ ObserverInternal internalObserver = mAllObservers.get(observer.getUniqueIdentifier());
if (internalObserver != null) {
internalObserver.registeredObserver = observer;
} else {
- internalObserver = new ObserverInternal(observer.getName(), new ArrayList<>());
+ internalObserver = new ObserverInternal(observer.getUniqueIdentifier(),
+ new ArrayList<>());
internalObserver.registeredObserver = observer;
- mAllObservers.put(observer.getName(), internalObserver);
+ mAllObservers.put(observer.getUniqueIdentifier(), internalObserver);
syncState("added new observer");
}
}
@@ -342,12 +343,12 @@
public void startObservingHealth(PackageHealthObserver observer, List<String> packageNames,
long durationMs) {
if (packageNames.isEmpty()) {
- Slog.wtf(TAG, "No packages to observe, " + observer.getName());
+ Slog.wtf(TAG, "No packages to observe, " + observer.getUniqueIdentifier());
return;
}
if (durationMs < 1) {
Slog.wtf(TAG, "Invalid duration " + durationMs + "ms for observer "
- + observer.getName() + ". Not observing packages " + packageNames);
+ + observer.getUniqueIdentifier() + ". Not observing packages " + packageNames);
durationMs = DEFAULT_OBSERVING_DURATION_MS;
}
@@ -374,14 +375,14 @@
syncState("observing new packages");
synchronized (mLock) {
- ObserverInternal oldObserver = mAllObservers.get(observer.getName());
+ ObserverInternal oldObserver = mAllObservers.get(observer.getUniqueIdentifier());
if (oldObserver == null) {
- Slog.d(TAG, observer.getName() + " started monitoring health "
+ Slog.d(TAG, observer.getUniqueIdentifier() + " started monitoring health "
+ "of packages " + packageNames);
- mAllObservers.put(observer.getName(),
- new ObserverInternal(observer.getName(), packages));
+ mAllObservers.put(observer.getUniqueIdentifier(),
+ new ObserverInternal(observer.getUniqueIdentifier(), packages));
} else {
- Slog.d(TAG, observer.getName() + " added the following "
+ Slog.d(TAG, observer.getUniqueIdentifier() + " added the following "
+ "packages to monitor " + packageNames);
oldObserver.updatePackagesLocked(packages);
}
@@ -405,9 +406,9 @@
public void unregisterHealthObserver(PackageHealthObserver observer) {
mLongTaskHandler.post(() -> {
synchronized (mLock) {
- mAllObservers.remove(observer.getName());
+ mAllObservers.remove(observer.getUniqueIdentifier());
}
- syncState("unregistering observer: " + observer.getName());
+ syncState("unregistering observer: " + observer.getUniqueIdentifier());
});
}
@@ -781,7 +782,7 @@
* Identifier for the observer, should not change across device updates otherwise the
* watchdog may drop observing packages with the old name.
*/
- String getName();
+ String getUniqueIdentifier();
/**
* An observer will not be pruned if this is set, even if the observer is not explicitly
diff --git a/services/core/java/com/android/server/RescueParty.java b/services/core/java/com/android/server/RescueParty.java
index c2cb5e9..bba97fa 100644
--- a/services/core/java/com/android/server/RescueParty.java
+++ b/services/core/java/com/android/server/RescueParty.java
@@ -917,7 +917,7 @@
}
@Override
- public String getName() {
+ public String getUniqueIdentifier() {
return NAME;
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 91b549c9..68d9221 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -15312,12 +15312,17 @@
final int cookie = traceBroadcastIntentBegin(intent, resultTo, ordered, sticky,
callingUid, realCallingUid, userId);
try {
+ final BroadcastSentEventRecord broadcastSentEventRecord =
+ new BroadcastSentEventRecord();
final int res = broadcastIntentLockedTraced(callerApp, callerPackage, callerFeatureId,
intent, resolvedType, resultToApp, resultTo, resultCode, resultData,
resultExtras, requiredPermissions, excludedPermissions, excludedPackages,
appOp, BroadcastOptions.fromBundleNullable(bOptions), ordered, sticky,
callingPid, callingUid, realCallingUid, realCallingPid, userId,
- backgroundStartPrivileges, broadcastAllowList, filterExtrasForReceiver);
+ backgroundStartPrivileges, broadcastAllowList, filterExtrasForReceiver,
+ broadcastSentEventRecord);
+ broadcastSentEventRecord.setResult(res);
+ broadcastSentEventRecord.logToStatsd();
return res;
} finally {
traceBroadcastIntentEnd(cookie);
@@ -15365,7 +15370,8 @@
int callingUid, int realCallingUid, int realCallingPid, int userId,
BackgroundStartPrivileges backgroundStartPrivileges,
@Nullable int[] broadcastAllowList,
- @Nullable BiFunction<Integer, Bundle, Bundle> filterExtrasForReceiver) {
+ @Nullable BiFunction<Integer, Bundle, Bundle> filterExtrasForReceiver,
+ @NonNull BroadcastSentEventRecord broadcastSentEventRecord) {
// Ensure all internal loopers are registered for idle checks
BroadcastLoopers.addMyLooper();
@@ -15398,6 +15404,17 @@
}
intent = new Intent(intent);
+ broadcastSentEventRecord.setIntent(intent);
+ broadcastSentEventRecord.setOriginalIntentFlags(intent.getFlags());
+ broadcastSentEventRecord.setSenderUid(callingUid);
+ broadcastSentEventRecord.setRealSenderUid(realCallingUid);
+ broadcastSentEventRecord.setSticky(sticky);
+ broadcastSentEventRecord.setOrdered(ordered);
+ broadcastSentEventRecord.setResultRequested(resultTo != null);
+ final int callerAppProcessState = getRealProcessStateLocked(callerApp, realCallingPid);
+ broadcastSentEventRecord.setSenderProcState(callerAppProcessState);
+ broadcastSentEventRecord.setSenderUidState(getRealUidStateLocked(callerApp,
+ realCallingPid));
final boolean callerInstantApp = isInstantApp(callerApp, callerPackage, callingUid);
// Instant Apps cannot use FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS
@@ -15891,7 +15908,6 @@
}
}
- final int callerAppProcessState = getRealProcessStateLocked(callerApp, realCallingPid);
// Add to the sticky list if requested.
if (sticky) {
if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
@@ -16131,6 +16147,7 @@
ordered, sticky, false, userId,
backgroundStartPrivileges, timeoutExempt, filterExtrasForReceiver,
callerAppProcessState);
+ broadcastSentEventRecord.setBroadcastRecord(r);
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing ordered broadcast " + r);
queue.enqueueBroadcastLocked(r);
@@ -16187,6 +16204,22 @@
return PROCESS_STATE_NONEXISTENT;
}
+ @GuardedBy("this")
+ private int getRealUidStateLocked(ProcessRecord app, int pid) {
+ if (app == null) {
+ synchronized (mPidsSelfLocked) {
+ app = mPidsSelfLocked.get(pid);
+ }
+ }
+ if (app != null && app.getThread() != null && !app.isKilled()) {
+ final UidRecord uidRecord = app.getUidRecord();
+ if (uidRecord != null) {
+ return uidRecord.getCurProcState();
+ }
+ }
+ return PROCESS_STATE_NONEXISTENT;
+ }
+
@VisibleForTesting
ArrayList<StickyBroadcast> getStickyBroadcastsForTest(String action, int userId) {
synchronized (mStickyBroadcasts) {
diff --git a/services/core/java/com/android/server/am/BroadcastRecord.java b/services/core/java/com/android/server/am/BroadcastRecord.java
index edb04c5..f908c67 100644
--- a/services/core/java/com/android/server/am/BroadcastRecord.java
+++ b/services/core/java/com/android/server/am/BroadcastRecord.java
@@ -53,6 +53,7 @@
import android.os.SystemClock;
import android.os.UserHandle;
import android.util.ArrayMap;
+import android.util.IntArray;
import android.util.PrintWriterPrinter;
import android.util.TimeUtils;
import android.util.proto.ProtoOutputStream;
@@ -940,6 +941,46 @@
return type;
}
+ int[] calculateTypesForLogging() {
+ final IntArray types = new IntArray();
+ if (isForeground()) {
+ types.add(BROADCAST_TYPE_FOREGROUND);
+ } else {
+ types.add(BROADCAST_TYPE_BACKGROUND);
+ }
+ if (alarm) {
+ types.add(BROADCAST_TYPE_ALARM);
+ }
+ if (interactive) {
+ types.add(BROADCAST_TYPE_INTERACTIVE);
+ }
+ if (ordered) {
+ types.add(BROADCAST_TYPE_ORDERED);
+ }
+ if (prioritized) {
+ types.add(BROADCAST_TYPE_PRIORITIZED);
+ }
+ if (resultTo != null) {
+ types.add(BROADCAST_TYPE_RESULT_TO);
+ }
+ if (deferUntilActive) {
+ types.add(BROADCAST_TYPE_DEFERRABLE_UNTIL_ACTIVE);
+ }
+ if (pushMessage) {
+ types.add(BROADCAST_TYPE_PUSH_MESSAGE);
+ }
+ if (pushMessageOverQuota) {
+ types.add(BROADCAST_TYPE_PUSH_MESSAGE_OVER_QUOTA);
+ }
+ if (sticky) {
+ types.add(BROADCAST_TYPE_STICKY);
+ }
+ if (initialSticky) {
+ types.add(BROADCAST_TYPE_INITIAL_STICKY);
+ }
+ return types.toArray();
+ }
+
public BroadcastRecord maybeStripForHistory() {
if (!intent.canStripForHistory()) {
return this;
diff --git a/services/core/java/com/android/server/am/BroadcastSentEventRecord.java b/services/core/java/com/android/server/am/BroadcastSentEventRecord.java
new file mode 100644
index 0000000..f2ac6d5
--- /dev/null
+++ b/services/core/java/com/android/server/am/BroadcastSentEventRecord.java
@@ -0,0 +1,134 @@
+/*
+ * 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.server.am;
+
+import static android.app.AppProtoEnums.BROADCAST_TYPE_ORDERED;
+import static android.app.AppProtoEnums.BROADCAST_TYPE_RESULT_TO;
+import static android.app.AppProtoEnums.BROADCAST_TYPE_STICKY;
+
+import static com.android.internal.util.FrameworkStatsLog.BROADCAST_SENT;
+import static com.android.internal.util.FrameworkStatsLog.BROADCAST_SENT__RESULT__FAILED_STICKY_CANT_HAVE_PERMISSION;
+import static com.android.internal.util.FrameworkStatsLog.BROADCAST_SENT__RESULT__FAILED_USER_STOPPED;
+import static com.android.internal.util.FrameworkStatsLog.BROADCAST_SENT__RESULT__SUCCESS;
+import static com.android.internal.util.FrameworkStatsLog.BROADCAST_SENT__RESULT__UNKNOWN;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.ActivityManager;
+import android.content.Intent;
+import android.util.IntArray;
+
+import com.android.internal.util.FrameworkStatsLog;
+
+final class BroadcastSentEventRecord {
+ @NonNull private Intent mIntent;
+ private int mOriginalIntentFlags;
+ private int mSenderUid;
+ private int mRealSenderUid;
+ private boolean mSticky;
+ private boolean mOrdered;
+ private boolean mResultRequested;
+ private int mSenderProcState;
+ private int mSenderUidState;
+ @Nullable private BroadcastRecord mBroadcastRecord;
+ private int mResult;
+
+ public void setIntent(@NonNull Intent intent) {
+ mIntent = intent;
+ }
+
+ public void setSenderUid(int uid) {
+ mSenderUid = uid;
+ }
+
+ public void setRealSenderUid(int uid) {
+ mRealSenderUid = uid;
+ }
+
+ public void setOriginalIntentFlags(int flags) {
+ mOriginalIntentFlags = flags;
+ }
+
+ public void setSticky(boolean sticky) {
+ mSticky = sticky;
+ }
+
+ public void setOrdered(boolean ordered) {
+ mOrdered = ordered;
+ }
+
+ public void setResultRequested(boolean resultRequested) {
+ mResultRequested = resultRequested;
+ }
+
+ public void setSenderProcState(int procState) {
+ mSenderProcState = procState;
+ }
+
+ public void setSenderUidState(int procState) {
+ mSenderUidState = procState;
+ }
+
+ public void setBroadcastRecord(@NonNull BroadcastRecord record) {
+ mBroadcastRecord = record;
+ }
+
+ public void setResult(int result) {
+ mResult = result;
+ }
+
+ public void logToStatsd() {
+ if (Flags.logBroadcastSentEvent()) {
+ int loggingResult = switch (mResult) {
+ case ActivityManager.BROADCAST_SUCCESS ->
+ BROADCAST_SENT__RESULT__SUCCESS;
+ case ActivityManager.BROADCAST_STICKY_CANT_HAVE_PERMISSION ->
+ BROADCAST_SENT__RESULT__FAILED_STICKY_CANT_HAVE_PERMISSION;
+ case ActivityManager.BROADCAST_FAILED_USER_STOPPED ->
+ BROADCAST_SENT__RESULT__FAILED_USER_STOPPED;
+ default -> BROADCAST_SENT__RESULT__UNKNOWN;
+ };
+ int[] types = calculateTypesForLogging();
+ FrameworkStatsLog.write(BROADCAST_SENT, mIntent.getAction(), mIntent.getFlags(),
+ mOriginalIntentFlags, mSenderUid, mRealSenderUid, mIntent.getPackage() != null,
+ mIntent.getComponent() != null,
+ mBroadcastRecord != null ? mBroadcastRecord.receivers.size() : 0,
+ loggingResult,
+ mBroadcastRecord != null ? mBroadcastRecord.getDeliveryGroupPolicy() : 0,
+ ActivityManager.processStateAmToProto(mSenderProcState),
+ ActivityManager.processStateAmToProto(mSenderUidState), types);
+ }
+ }
+
+ private int[] calculateTypesForLogging() {
+ if (mBroadcastRecord != null) {
+ return mBroadcastRecord.calculateTypesForLogging();
+ } else {
+ final IntArray types = new IntArray();
+ if (mSticky) {
+ types.add(BROADCAST_TYPE_STICKY);
+ }
+ if (mOrdered) {
+ types.add(BROADCAST_TYPE_ORDERED);
+ }
+ if (mResultRequested) {
+ types.add(BROADCAST_TYPE_RESULT_TO);
+ }
+ return types.toArray();
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/am/flags.aconfig b/services/core/java/com/android/server/am/flags.aconfig
index 5315167..3334393 100644
--- a/services/core/java/com/android/server/am/flags.aconfig
+++ b/services/core/java/com/android/server/am/flags.aconfig
@@ -184,3 +184,14 @@
description: "Defer submitting binder calls to paused processes."
bug: "327038797"
}
+
+flag {
+ name: "log_broadcast_sent_event"
+ namespace: "backstage_power"
+ description: "Log the broadcast send event to Statsd"
+ bug: "355261986"
+ is_fixed_read_only: true
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
\ No newline at end of file
diff --git a/services/core/java/com/android/server/biometrics/log/BiometricFrameworkStatsLogger.java b/services/core/java/com/android/server/biometrics/log/BiometricFrameworkStatsLogger.java
index f31b2e1..2c52e3d 100644
--- a/services/core/java/com/android/server/biometrics/log/BiometricFrameworkStatsLogger.java
+++ b/services/core/java/com/android/server/biometrics/log/BiometricFrameworkStatsLogger.java
@@ -241,6 +241,14 @@
-1 /* sensorId */);
}
+ /** {@see FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED}. */
+ public void reportFingerprintsLoe(int statsModality) {
+ FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED,
+ statsModality,
+ BiometricsProtoEnums.ISSUE_FINGERPRINTS_LOE,
+ -1 /* sensorId */);
+ }
+
/** {@see FrameworkStatsLog.BIOMETRIC_FRR_NOTIFICATION}. */
public void logFrameworkNotification(int action, int modality) {
FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_FRR_NOTIFICATION,
diff --git a/services/core/java/com/android/server/biometrics/log/BiometricLogger.java b/services/core/java/com/android/server/biometrics/log/BiometricLogger.java
index ff1e5d5..9351bc0 100644
--- a/services/core/java/com/android/server/biometrics/log/BiometricLogger.java
+++ b/services/core/java/com/android/server/biometrics/log/BiometricLogger.java
@@ -296,6 +296,15 @@
mSink.reportUnknownTemplateEnrolledFramework(mStatsModality);
}
+ /** Report unknown enrollment in framework settings */
+ public void logFingerprintsLoe() {
+ if (shouldSkipLogging()) {
+ return;
+ }
+
+ mSink.reportFingerprintsLoe(mStatsModality);
+ }
+
/**
* Get a callback to start/stop ALS capture when the client runs. Do not create
* multiple callbacks since there is at most one light sensor (they will all share
diff --git a/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java b/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java
index 77e27ba..7bd905b 100644
--- a/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java
@@ -161,6 +161,11 @@
getLogger().logUnknownEnrollmentInHal();
+ if (mBiometricUtils.hasValidBiometricUserState(getContext(), getTargetUserId())
+ && Flags.notifyFingerprintsLoe()) {
+ getLogger().logFingerprintsLoe();
+ }
+
mCurrentTask.start(mRemoveCallback);
}
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 9e905ab..55a6ce7 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -64,7 +64,6 @@
import android.app.compat.CompatChanges;
import android.companion.virtual.IVirtualDevice;
import android.companion.virtual.VirtualDeviceManager;
-import android.companion.virtual.flags.Flags;
import android.compat.annotation.ChangeId;
import android.compat.annotation.EnabledSince;
import android.content.BroadcastReceiver;
@@ -1633,8 +1632,7 @@
&& (flags & VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) != 0) {
// Only a valid media projection or a virtual device can create a mirror virtual
// display.
- if (!canProjectVideo(projection)
- && !isMirroringSupportedByVirtualDevice(virtualDevice)) {
+ if (!canProjectVideo(projection) && virtualDevice == null) {
throw new SecurityException("Requires CAPTURE_VIDEO_OUTPUT or "
+ "CAPTURE_SECURE_VIDEO_OUTPUT permission, or an appropriate "
+ "MediaProjection token in order to create a screen sharing virtual "
@@ -1896,10 +1894,6 @@
return -1;
}
- private static boolean isMirroringSupportedByVirtualDevice(IVirtualDevice virtualDevice) {
- return Flags.interactiveScreenMirror() && virtualDevice != null;
- }
-
private void resizeVirtualDisplayInternal(IBinder appToken,
int width, int height, int densityDpi) {
synchronized (mSyncRoot) {
diff --git a/services/core/java/com/android/server/display/ExternalDisplayPolicy.java b/services/core/java/com/android/server/display/ExternalDisplayPolicy.java
index 44c8d1c..28a0b28 100644
--- a/services/core/java/com/android/server/display/ExternalDisplayPolicy.java
+++ b/services/core/java/com/android/server/display/ExternalDisplayPolicy.java
@@ -231,7 +231,7 @@
if (!isExternalDisplayAllowed()) {
Slog.w(TAG, "handleExternalDisplayConnectedLocked: External display can not be used"
+ " because it is currently not allowed.");
- mDisplayNotificationManager.onHighTemperatureExternalDisplayNotAllowed();
+ mHandler.post(mDisplayNotificationManager::onHighTemperatureExternalDisplayNotAllowed);
return;
}
@@ -329,7 +329,7 @@
if (!isExternalDisplayAllowed()) {
Slog.w(TAG, "External display is currently not allowed and is getting disabled.");
- mDisplayNotificationManager.onHighTemperatureExternalDisplayNotAllowed();
+ mHandler.post(mDisplayNotificationManager::onHighTemperatureExternalDisplayNotAllowed);
}
mLogicalDisplayMapper.setDisplayEnabledLocked(logicalDisplay, /*enabled=*/ false);
diff --git a/services/core/java/com/android/server/display/notifications/DisplayNotificationManager.java b/services/core/java/com/android/server/display/notifications/DisplayNotificationManager.java
index 280a7e1..8a8440b 100644
--- a/services/core/java/com/android/server/display/notifications/DisplayNotificationManager.java
+++ b/services/core/java/com/android/server/display/notifications/DisplayNotificationManager.java
@@ -26,6 +26,7 @@
import android.app.NotificationManager;
import android.content.Context;
import android.content.res.Resources;
+import android.os.UserHandle;
import android.util.Slog;
import com.android.internal.R;
@@ -197,7 +198,8 @@
return;
}
- mNotificationManager.cancel(DISPLAY_NOTIFICATION_TAG, DISPLAY_NOTIFICATION_ID);
+ mNotificationManager.cancelAsUser(DISPLAY_NOTIFICATION_TAG, DISPLAY_NOTIFICATION_ID,
+ UserHandle.CURRENT);
}
/**
@@ -210,8 +212,8 @@
return;
}
- mNotificationManager.notify(DISPLAY_NOTIFICATION_TAG, DISPLAY_NOTIFICATION_ID,
- notification);
+ mNotificationManager.notifyAsUser(DISPLAY_NOTIFICATION_TAG, DISPLAY_NOTIFICATION_ID,
+ notification, UserHandle.CURRENT);
}
/**
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index 154710f..81c30dd 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -1225,11 +1225,15 @@
boolean avrSystemAudioMode = HdmiUtils.parseCommandParamSystemAudioStatus(message);
// Set System Audio Mode according to TV's settings.
// Handle <System Audio Mode Status> here only when
- // SystemAudioAutoInitiationAction timeout
+ // SystemAudioAutoInitiationAction timeout.
+ // If AVR reports SAM on and it is in standby, the action SystemAudioActionFromTv
+ // triggers a <SAM Request> that will wake-up the AVR.
HdmiDeviceInfo avr = getAvrDeviceInfo();
if (avr == null) {
setSystemAudioMode(false);
- } else if (avrSystemAudioMode != tvSystemAudioMode) {
+ } else if (avrSystemAudioMode != tvSystemAudioMode
+ || (avrSystemAudioMode && avr.getDevicePowerStatus()
+ == HdmiControlManager.POWER_STATUS_STANDBY)) {
addAndStartAction(new SystemAudioActionFromTv(this, avr.getLogicalAddress(),
tvSystemAudioMode, null));
} else {
diff --git a/services/core/java/com/android/server/hdmi/SystemAudioAutoInitiationAction.java b/services/core/java/com/android/server/hdmi/SystemAudioAutoInitiationAction.java
index 56e538b..028637b 100644
--- a/services/core/java/com/android/server/hdmi/SystemAudioAutoInitiationAction.java
+++ b/services/core/java/com/android/server/hdmi/SystemAudioAutoInitiationAction.java
@@ -16,7 +16,9 @@
package com.android.server.hdmi;
+import android.hardware.hdmi.HdmiControlManager;
import android.hardware.tv.cec.V1_0.SendMessageResult;
+import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.hdmi.HdmiControlService.SendMessageCallback;
@@ -89,8 +91,13 @@
// If System Audio Control feature is enabled, turn on system audio mode when new AVR is
// detected. Otherwise, turn off system audio mode.
+ // If AVR reports SAM on and it is in standby, the action SystemAudioActionFromTv
+ // triggers a <SAM Request> that will wake-up the AVR.
boolean targetSystemAudioMode = tv().isSystemAudioControlFeatureEnabled();
- if (currentSystemAudioMode != targetSystemAudioMode) {
+ if (currentSystemAudioMode != targetSystemAudioMode
+ || (currentSystemAudioMode && tv().getAvrDeviceInfo() != null
+ && tv().getAvrDeviceInfo().getDevicePowerStatus()
+ == HdmiControlManager.POWER_STATUS_STANDBY)) {
// Start System Audio Control feature actions only if necessary.
addAndStartAction(
new SystemAudioActionFromTv(tv(), mAvrAddress, targetSystemAudioMode, null));
diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
index 1070f2f..e1b8e9f 100644
--- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
+++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
@@ -1364,14 +1364,14 @@
if (manager == null || manager.mLastSessionCreationRequest == null) {
Slog.w(TAG, "requestCreateSessionWithRouter2Locked: "
+ "Ignoring unknown request.");
- userHandler.notifySessionCreationFailedToRouter(routerRecord, requestId);
+ routerRecord.notifySessionCreationFailed(requestId);
return;
}
if (!TextUtils.equals(manager.mLastSessionCreationRequest.mOldSession.getId(),
oldSession.getId())) {
Slog.w(TAG, "requestCreateSessionWithRouter2Locked: "
+ "Ignoring unmatched routing session.");
- userHandler.notifySessionCreationFailedToRouter(routerRecord, requestId);
+ routerRecord.notifySessionCreationFailed(requestId);
return;
}
if (!TextUtils.equals(manager.mLastSessionCreationRequest.mRoute.getId(),
@@ -1384,7 +1384,7 @@
} else {
Slog.w(TAG, "requestCreateSessionWithRouter2Locked: "
+ "Ignoring unmatched route.");
- userHandler.notifySessionCreationFailedToRouter(routerRecord, requestId);
+ routerRecord.notifySessionCreationFailed(requestId);
return;
}
}
@@ -1396,7 +1396,7 @@
&& !TextUtils.equals(route.getId(), defaultRouteId)) {
Slog.w(TAG, "MODIFY_AUDIO_ROUTING permission is required to transfer to"
+ route);
- userHandler.notifySessionCreationFailedToRouter(routerRecord, requestId);
+ routerRecord.notifySessionCreationFailed(requestId);
return;
}
}
@@ -1484,8 +1484,7 @@
&& !TextUtils.equals(route.getId(), defaultRouteId)) {
userHandler.sendMessage(
obtainMessage(
- UserHandler::notifySessionCreationFailedToRouter,
- userHandler,
+ RouterRecord::notifySessionCreationFailed,
routerRecord,
toOriginalRequestId(DUMMY_REQUEST_ID)));
} else {
@@ -1762,12 +1761,7 @@
if (routerRecord == null) {
Slog.w(TAG, "requestCreateSessionWithManagerLocked: Ignoring session creation for "
+ "unknown router.");
- try {
- managerRecord.mManager.notifyRequestFailed(requestId, REASON_UNKNOWN_ERROR);
- } catch (RemoteException ex) {
- Slog.w(TAG, "requestCreateSessionWithManagerLocked: Failed to notify failure. "
- + "Manager probably died.");
- }
+ managerRecord.notifyRequestFailed(requestId, REASON_UNKNOWN_ERROR);
return;
}
@@ -1780,10 +1774,8 @@
"requestCreateSessionWithManagerLocked: Notifying failure for pending"
+ " session creation request - oldSession: %s, route: %s",
lastRequest.mOldSession, lastRequest.mRoute));
- managerRecord.mUserRecord.mHandler.notifyRequestFailedToManager(
- managerRecord.mManager,
- toOriginalRequestId(lastRequest.mManagerRequestId),
- REASON_UNKNOWN_ERROR);
+ managerRecord.notifyRequestFailed(
+ toOriginalRequestId(lastRequest.mManagerRequestId), REASON_UNKNOWN_ERROR);
}
managerRecord.mLastSessionCreationRequest = new SessionCreationRequest(routerRecord,
MediaRoute2ProviderService.REQUEST_ID_NONE, uniqueRequestId,
@@ -1793,15 +1785,12 @@
// As a return, media router will request to create a session.
routerRecord.mUserRecord.mHandler.sendMessage(
obtainMessage(
- UserHandler::requestRouterCreateSessionOnHandler,
- routerRecord.mUserRecord.mHandler,
- uniqueRequestId,
+ RouterRecord::requestCreateSessionByManager,
routerRecord,
managerRecord,
+ uniqueRequestId,
oldSession,
- route,
- transferInitiatorUserHandle,
- transferInitiatorPackageName));
+ route));
}
@GuardedBy("mLock")
@@ -2256,6 +2245,71 @@
}
/**
+ * Notifies the corresponding router of a request failure.
+ *
+ * @param requestId The id of the request that failed.
+ */
+ public void notifySessionCreationFailed(int requestId) {
+ try {
+ mRouter.notifySessionCreated(requestId, /* sessionInfo= */ null);
+ } catch (RemoteException ex) {
+ Slog.w(
+ TAG,
+ "Failed to notify router of the session creation failure."
+ + " Router probably died.",
+ ex);
+ }
+ }
+
+ /**
+ * Notifies the corresponding router of the release of the given {@link RoutingSessionInfo}.
+ */
+ public void notifySessionReleased(RoutingSessionInfo sessionInfo) {
+ try {
+ mRouter.notifySessionReleased(sessionInfo);
+ } catch (RemoteException ex) {
+ Slog.w(
+ TAG,
+ "Failed to notify router of the session release. Router probably died.",
+ ex);
+ }
+ }
+
+ /**
+ * Sends the corresponding router a {@link RoutingSessionInfo session} creation request,
+ * with the given {@link MediaRoute2Info} as the initial member.
+ *
+ * <p>Must be called on the thread of the corresponding {@link UserHandler}.
+ *
+ * @param managerRecord The record of the manager that made the request.
+ * @param uniqueRequestId The id of the request.
+ * @param oldSession The session from which the transfer originated.
+ * @param route The initial route member of the session to create.
+ */
+ public void requestCreateSessionByManager(
+ ManagerRecord managerRecord,
+ long uniqueRequestId,
+ RoutingSessionInfo oldSession,
+ MediaRoute2Info route) {
+ try {
+ if (route.isSystemRoute() && !hasSystemRoutingPermission()) {
+ // The router lacks permission to modify system routing, so we hide system
+ // route info from them.
+ route = mUserRecord.mHandler.mSystemProvider.getDefaultRoute();
+ }
+ mRouter.requestCreateSessionByManager(uniqueRequestId, oldSession, route);
+ } catch (RemoteException ex) {
+ Slog.w(
+ TAG,
+ "getSessionHintsForCreatingSessionOnHandler: "
+ + "Failed to request. Router probably died.",
+ ex);
+ managerRecord.notifyRequestFailed(
+ toOriginalRequestId(uniqueRequestId), REASON_UNKNOWN_ERROR);
+ }
+ }
+
+ /**
* Sends the corresponding router an update for the given session.
*
* <p>Note: These updates are not directly visible to the app.
@@ -2360,6 +2414,25 @@
}
}
+ /**
+ * Notifies the corresponding manager of a request failure.
+ *
+ * <p>Must be called on the thread of the corresponding {@link UserHandler}.
+ *
+ * @param requestId The id of the request that failed.
+ * @param reason The reason of the failure. One of
+ */
+ public void notifyRequestFailed(int requestId, int reason) {
+ try {
+ mManager.notifyRequestFailed(requestId, reason);
+ } catch (RemoteException ex) {
+ Slog.w(
+ TAG,
+ "Failed to notify manager of the request failure. Manager probably died.",
+ ex);
+ }
+ }
+
private void updateScanningState(@ScanningState int scanningState) {
if (mScanningState == scanningState) {
return;
@@ -2738,30 +2811,6 @@
return -1;
}
- private void requestRouterCreateSessionOnHandler(
- long uniqueRequestId,
- @NonNull RouterRecord routerRecord,
- @NonNull ManagerRecord managerRecord,
- @NonNull RoutingSessionInfo oldSession,
- @NonNull MediaRoute2Info route,
- @NonNull UserHandle transferInitiatorUserHandle,
- @NonNull String transferInitiatorPackageName) {
- try {
- if (route.isSystemRoute() && !routerRecord.hasSystemRoutingPermission()) {
- // The router lacks permission to modify system routing, so we hide system
- // route info from them.
- route = mSystemProvider.getDefaultRoute();
- }
- routerRecord.mRouter.requestCreateSessionByManager(
- uniqueRequestId, oldSession, route);
- } catch (RemoteException ex) {
- Slog.w(TAG, "getSessionHintsForCreatingSessionOnHandler: "
- + "Failed to request. Router probably died.", ex);
- notifyRequestFailedToManager(managerRecord.mManager,
- toOriginalRequestId(uniqueRequestId), REASON_UNKNOWN_ERROR);
- }
- }
-
private void requestCreateSessionWithRouter2OnHandler(
long uniqueRequestId,
long managerRequestId,
@@ -2774,8 +2823,7 @@
if (provider == null) {
Slog.w(TAG, "requestCreateSessionWithRouter2OnHandler: Ignoring session "
+ "creation request since no provider found for given route=" + route);
- notifySessionCreationFailedToRouter(routerRecord,
- toOriginalRequestId(uniqueRequestId));
+ routerRecord.notifySessionCreationFailed(toOriginalRequestId(uniqueRequestId));
return;
}
@@ -3054,7 +3102,7 @@
+ sessionInfo);
return;
}
- notifySessionReleasedToRouter(routerRecord, sessionInfo);
+ routerRecord.notifySessionReleased(sessionInfo);
}
private void onRequestFailedOnHandler(@NonNull MediaRoute2Provider provider,
@@ -3073,8 +3121,7 @@
final int requesterId = toRequesterId(uniqueRequestId);
ManagerRecord manager = findManagerWithId(requesterId);
if (manager != null) {
- notifyRequestFailedToManager(
- manager.mManager, toOriginalRequestId(uniqueRequestId), reason);
+ manager.notifyRequestFailed(toOriginalRequestId(uniqueRequestId), reason);
}
// Currently, only manager records can get notified of failures.
@@ -3109,40 +3156,19 @@
// Notify the requester about the failure.
// The call should be made by either MediaRouter2 or MediaRouter2Manager.
if (matchingRequest.mManagerRequestId == MediaRouter2Manager.REQUEST_ID_NONE) {
- notifySessionCreationFailedToRouter(
- matchingRequest.mRouterRecord, toOriginalRequestId(uniqueRequestId));
+ matchingRequest.mRouterRecord.notifySessionCreationFailed(
+ toOriginalRequestId(uniqueRequestId));
} else {
final int requesterId = toRequesterId(matchingRequest.mManagerRequestId);
ManagerRecord manager = findManagerWithId(requesterId);
if (manager != null) {
- notifyRequestFailedToManager(manager.mManager,
+ manager.notifyRequestFailed(
toOriginalRequestId(matchingRequest.mManagerRequestId), reason);
}
}
return true;
}
- private void notifySessionCreationFailedToRouter(@NonNull RouterRecord routerRecord,
- int requestId) {
- try {
- routerRecord.mRouter.notifySessionCreated(requestId,
- /* sessionInfo= */ null);
- } catch (RemoteException ex) {
- Slog.w(TAG, "Failed to notify router of the session creation failure."
- + " Router probably died.", ex);
- }
- }
-
- private void notifySessionReleasedToRouter(@NonNull RouterRecord routerRecord,
- @NonNull RoutingSessionInfo sessionInfo) {
- try {
- routerRecord.mRouter.notifySessionReleased(sessionInfo);
- } catch (RemoteException ex) {
- Slog.w(TAG, "Failed to notify router of the session release."
- + " Router probably died.", ex);
- }
- }
-
private List<IMediaRouter2Manager> getManagers() {
final List<IMediaRouter2Manager> managers = new ArrayList<>();
MediaRouter2ServiceImpl service = mServiceRef.get();
@@ -3379,16 +3405,6 @@
// need to update routers other than the one making the update.
}
- private void notifyRequestFailedToManager(@NonNull IMediaRouter2Manager manager,
- int requestId, int reason) {
- try {
- manager.notifyRequestFailed(requestId, reason);
- } catch (RemoteException ex) {
- Slog.w(TAG, "Failed to notify manager of the request failure."
- + " Manager probably died.", ex);
- }
- }
-
private void updateDiscoveryPreferenceOnHandler() {
MediaRouter2ServiceImpl service = mServiceRef.get();
if (service == null) {
diff --git a/services/core/java/com/android/server/notification/GroupHelper.java b/services/core/java/com/android/server/notification/GroupHelper.java
index 1cdab44..008746c 100644
--- a/services/core/java/com/android/server/notification/GroupHelper.java
+++ b/services/core/java/com/android/server/notification/GroupHelper.java
@@ -118,11 +118,32 @@
private final ArrayMap<FullyQualifiedGroupKey, ArrayMap<String, NotificationAttributes>>
mAggregatedNotifications = new ArrayMap<>();
- private static final List<NotificationSectioner> NOTIFICATION_SHADE_SECTIONS = List.of(
- new NotificationSectioner("AlertingSection", 0, (record) ->
- record.getImportance() >= NotificationManager.IMPORTANCE_DEFAULT),
- new NotificationSectioner("SilentSection", 1, (record) ->
- record.getImportance() < NotificationManager.IMPORTANCE_DEFAULT));
+ private static List<NotificationSectioner> NOTIFICATION_SHADE_SECTIONS =
+ getNotificationShadeSections();
+
+ private static List<NotificationSectioner> getNotificationShadeSections() {
+ if (android.service.notification.Flags.notificationClassification()) {
+ return List.of(
+ new NotificationSectioner("PromotionsSection", 0, (record) ->
+ NotificationChannel.PROMOTIONS_ID.equals(record.getChannel().getId())),
+ new NotificationSectioner("SocialSection", 0, (record) ->
+ NotificationChannel.SOCIAL_MEDIA_ID.equals(record.getChannel().getId())),
+ new NotificationSectioner("NewsSection", 0, (record) ->
+ NotificationChannel.NEWS_ID.equals(record.getChannel().getId())),
+ new NotificationSectioner("RecsSection", 0, (record) ->
+ NotificationChannel.RECS_ID.equals(record.getChannel().getId())),
+ new NotificationSectioner("AlertingSection", 0, (record) ->
+ record.getImportance() >= NotificationManager.IMPORTANCE_DEFAULT),
+ new NotificationSectioner("SilentSection", 1, (record) ->
+ record.getImportance() < NotificationManager.IMPORTANCE_DEFAULT));
+ } else {
+ return List.of(
+ new NotificationSectioner("AlertingSection", 0, (record) ->
+ record.getImportance() >= NotificationManager.IMPORTANCE_DEFAULT),
+ new NotificationSectioner("SilentSection", 1, (record) ->
+ record.getImportance() < NotificationManager.IMPORTANCE_DEFAULT));
+ }
+ }
public GroupHelper(Context context, PackageManager packageManager, int autoGroupAtCount,
int autoGroupSparseGroupsAtCount, Callback callback) {
@@ -131,6 +152,7 @@
mContext = context;
mPackageManager = packageManager;
mAutogroupSparseGroupsAtCount = autoGroupSparseGroupsAtCount;
+ NOTIFICATION_SHADE_SECTIONS = getNotificationShadeSections();
}
private String generatePackageKey(int userId, String pkg) {
diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
index aaa38a3..6c78b3c 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -887,7 +887,7 @@
grantPermissionsToSystemPackage(pm,
getDefaultSystemHandlerActivityPackage(pm,
SearchManager.INTENT_ACTION_GLOBAL_SEARCH, userId),
- userId, PHONE_PERMISSIONS, CALENDAR_PERMISSIONS);
+ userId, PHONE_PERMISSIONS, CALENDAR_PERMISSIONS, NEARBY_DEVICES_PERMISSIONS);
}
// Print Spooler
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 9b9d1cc..934feb3 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -3352,6 +3352,12 @@
mConsumedKeysForDevice.put(deviceId, consumedKeys);
}
+ // TODO(b/358569822) Remove below once we have nicer API for listening to shortcuts
+ if ((event.isMetaPressed() || KeyEvent.isMetaKey(keyCode))
+ && shouldInterceptShortcuts(focusedToken)) {
+ return keyNotConsumed;
+ }
+
if (interceptSystemKeysAndShortcuts(focusedToken, event)
&& event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) {
consumedKeys.add(keyCode);
@@ -3842,6 +3848,15 @@
return (metaState & KeyEvent.META_META_ON) != 0;
}
+ private boolean shouldInterceptShortcuts(IBinder focusedToken) {
+ KeyInterceptionInfo info =
+ mWindowManagerInternal.getKeyInterceptionInfoFromToken(focusedToken);
+ boolean hasInterceptWindowFlag = (info.layoutParamsPrivateFlags
+ & WindowManager.LayoutParams.PRIVATE_FLAG_ALLOW_ACTION_KEY_EVENTS) != 0;
+ return hasInterceptWindowFlag && mButtonOverridePermissionChecker.canAppOverrideSystemKey(
+ mContext, info.windowOwnerUid);
+ }
+
/**
* In this function, we check whether a system key should be sent to the application. We also
* detect the key gesture on this key, even if the key will be sent to the app. The gesture
diff --git a/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java b/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
index 4f28e02..e91097c 100644
--- a/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
+++ b/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
@@ -16,6 +16,8 @@
package com.android.server.rollback;
+import static android.content.pm.Flags.provideInfoOfApkInApex;
+
import android.annotation.AnyThread;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -23,6 +25,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.VersionedPackage;
import android.content.rollback.PackageRollbackInfo;
@@ -230,7 +233,7 @@
@Override
- public String getName() {
+ public String getUniqueIdentifier() {
return NAME;
}
@@ -486,19 +489,40 @@
*/
@AnyThread
private boolean isModule(String packageName) {
- // Check if the package is an APK inside an APEX. If it is, use the parent APEX package when
- // querying PackageManager.
- String apexPackageName = mApexManager.getActiveApexPackageNameContainingPackage(
- packageName);
- if (apexPackageName != null) {
- packageName = apexPackageName;
- }
-
PackageManager pm = mContext.getPackageManager();
- try {
- return pm.getModuleInfo(packageName, 0) != null;
- } catch (PackageManager.NameNotFoundException ignore) {
- return false;
+
+ if (Flags.refactorCrashrecovery() && provideInfoOfApkInApex()) {
+ // Check if the package is listed among the system modules.
+ boolean isApex = false;
+ try {
+ isApex = (pm.getModuleInfo(packageName, 0 /* flags */) != null);
+ } catch (PackageManager.NameNotFoundException e) {
+ //pass
+ }
+
+ // Check if the package is an APK inside an APEX.
+ boolean isApkInApex = false;
+ try {
+ final PackageInfo pkg = pm.getPackageInfo(packageName, 0 /* flags */);
+ isApkInApex = (pkg.getApexPackageName() != null);
+ } catch (PackageManager.NameNotFoundException e) {
+ // pass
+ }
+ return isApex || isApkInApex;
+ } else {
+ // Check if the package is an APK inside an APEX. If it is, use the parent APEX package
+ // when querying PackageManager.
+ String apexPackageName = mApexManager.getActiveApexPackageNameContainingPackage(
+ packageName);
+ if (apexPackageName != null) {
+ packageName = apexPackageName;
+ }
+
+ try {
+ return pm.getModuleInfo(packageName, 0) != null;
+ } catch (PackageManager.NameNotFoundException ignore) {
+ return false;
+ }
}
}
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index 6721893..c543b6d 100644
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -19,6 +19,7 @@
import static android.media.AudioManager.DEVICE_NONE;
import static android.media.tv.TvInputManager.INPUT_STATE_CONNECTED;
import static android.media.tv.TvInputManager.INPUT_STATE_CONNECTED_STANDBY;
+import static android.media.tv.flags.Flags.kidsModeTvdbSharing;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -805,6 +806,19 @@
}
}
+ private boolean isServiceSingleUser(ComponentName component) {
+ try {
+ ServiceInfo serviceInfo = getContext().getPackageManager()
+ .getServiceInfo(component, 0);
+ // Check if the single-user flag is present
+ return (serviceInfo.flags & ServiceInfo.FLAG_SINGLE_USER) != 0;
+ } catch (PackageManager.NameNotFoundException e) {
+ // Handle the case where the service is not found
+ Slog.e(TAG, "Service not found: " + component, e);
+ return false;
+ }
+ }
+
@GuardedBy("mLock")
private void abortPendingCreateSessionRequestsLocked(ServiceState serviceState,
String inputId, int userId) {
@@ -2840,6 +2854,26 @@
}
@Override
+ public int getClientUserId(String sessionId) {
+ ensureTunerResourceAccessPermission();
+ int clientUserId = TvInputManager.UNKNOWN_CLIENT_USER_ID;
+
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ try {
+ clientUserId = getClientUserIdLocked(sessionId);
+ } catch (ClientUserIdNotFoundException e) {
+ Slog.e(TAG, "error in getClientUserId", e);
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ return clientUserId;
+ }
+
+ @Override
public int getClientPriority(int useCase, String sessionId) {
ensureTunerResourceAccessPermission();
final int callingPid = Binder.getCallingPid();
@@ -2924,6 +2958,16 @@
return mSessionIdToSessionStateMap.get(sessionId).callingPid;
}
+ @GuardedBy("mLock")
+ private int getClientUserIdLocked(String sessionId) throws ClientUserIdNotFoundException {
+ SessionState sessionState = mSessionIdToSessionStateMap.get(sessionId);
+ if (sessionState == null) {
+ throw new ClientUserIdNotFoundException(
+ "Client UserId not found with sessionId " + sessionId);
+ }
+ return sessionState.userId;
+ }
+
private void ensureTunerResourceAccessPermission() {
if (mContext.checkCallingPermission(
android.Manifest.permission.TUNER_RESOURCE_ACCESS)
@@ -3495,11 +3539,15 @@
"bindServiceAsUser(service=" + serviceState.component + ", userId=" + userId
+ ")");
}
+ int bindUserId = userId;
+ if (kidsModeTvdbSharing() && isServiceSingleUser(serviceState.component)) {
+ bindUserId = UserHandle.USER_SYSTEM;
+ }
Intent i =
new Intent(TvInputService.SERVICE_INTERFACE).setComponent(serviceState.component);
serviceState.bound = mContext.bindServiceAsUser(i, serviceState.connection,
Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
- new UserHandle(userId));
+ new UserHandle(bindUserId));
if (!serviceState.bound) {
Slog.e(TAG, "failed to bind " + serviceState.component + " for userId " + userId);
mContext.unbindService(serviceState.connection);
@@ -4700,4 +4748,10 @@
super(name);
}
}
+
+ private static class ClientUserIdNotFoundException extends IllegalArgumentException {
+ ClientUserIdNotFoundException(String name) {
+ super(name);
+ }
+ }
}
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 3d58082..5e03066 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -4626,7 +4626,12 @@
return kept;
}
- /** Update default (global) configuration and notify listeners about changes. */
+ /**
+ * Updates default (global) configuration and notifies listeners about changes.
+ *
+ * @param values The new configuration. It must always be a new instance from the caller, and
+ * it won't be modified after calling this method.
+ */
int updateGlobalConfigurationLocked(@NonNull Configuration values, boolean initLocale,
boolean persistent, int userId) {
@@ -4640,24 +4645,6 @@
ProtoLog.i(WM_DEBUG_CONFIGURATION, "Updating global configuration "
+ "to: %s", values);
writeConfigurationChanged(changes);
- FrameworkStatsLog.write(FrameworkStatsLog.RESOURCE_CONFIGURATION_CHANGED,
- values.colorMode,
- values.densityDpi,
- values.fontScale,
- values.hardKeyboardHidden,
- values.keyboard,
- values.keyboardHidden,
- values.mcc,
- values.mnc,
- values.navigation,
- values.navigationHidden,
- values.orientation,
- values.screenHeightDp,
- values.screenLayout,
- values.screenWidthDp,
- values.smallestScreenWidthDp,
- values.touchscreen,
- values.uiMode);
// Note: certain tests currently run as platform_app which is not allowed
// to set debug system properties. To ensure that system properties are set
@@ -4705,13 +4692,6 @@
// resources have that config before following boot code is executed.
mSystemThread.applyConfigurationToResources(mTempConfig);
- if (persistent && Settings.System.hasInterestingConfigurationChanges(changes)) {
- final Message msg = PooledLambda.obtainMessage(
- ActivityTaskManagerService::sendPutConfigurationForUserMsg,
- this, userId, new Configuration(mTempConfig));
- mH.sendMessage(msg);
- }
-
SparseArray<WindowProcessController> pidMap = mProcessMap.getPidMap();
for (int i = pidMap.size() - 1; i >= 0; i--) {
final int pid = pidMap.keyAt(i);
@@ -4721,19 +4701,32 @@
app.onConfigurationChanged(mTempConfig);
}
- final Message msg = PooledLambda.obtainMessage(
- ActivityManagerInternal::broadcastGlobalConfigurationChanged,
- mAmInternal, changes, initLocale);
- mH.sendMessage(msg);
+ final Configuration configurationForSettings =
+ persistent && Settings.System.hasInterestingConfigurationChanges(changes)
+ ? new Configuration(mTempConfig) : null;
+ mH.post(() -> {
+ FrameworkStatsLog.write(FrameworkStatsLog.RESOURCE_CONFIGURATION_CHANGED,
+ values.colorMode, values.densityDpi, values.fontScale,
+ values.hardKeyboardHidden, values.keyboard, values.keyboardHidden,
+ values.mcc, values.mnc, values.navigation, values.navigationHidden,
+ values.orientation, values.screenHeightDp, values.screenLayout,
+ values.screenWidthDp, values.smallestScreenWidthDp, values.touchscreen,
+ values.uiMode);
+ if ((changes & ActivityInfo.CONFIG_ORIENTATION) != 0) {
+ FrameworkStatsLog.write(FrameworkStatsLog.DEVICE_ORIENTATION_CHANGED,
+ values.orientation);
+ }
+ if (configurationForSettings != null) {
+ Settings.System.putConfigurationForUser(mContext.getContentResolver(),
+ configurationForSettings, userId);
+ }
+ mAmInternal.broadcastGlobalConfigurationChanged(changes, initLocale);
+ });
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "RootConfigChange");
// Update stored global config and notify everyone about the change.
mRootWindowContainer.onConfigurationChanged(mTempConfig);
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
- if ((changes & ActivityInfo.CONFIG_ORIENTATION) != 0) {
- FrameworkStatsLog.write(FrameworkStatsLog.DEVICE_ORIENTATION_CHANGED,
- values.orientation);
- }
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
return changes;
@@ -4883,11 +4876,6 @@
mWindowManager.setEventDispatching(booted && !mShuttingDown);
}
- private void sendPutConfigurationForUserMsg(int userId, Configuration config) {
- final ContentResolver resolver = mContext.getContentResolver();
- Settings.System.putConfigurationForUser(resolver, config, userId);
- }
-
boolean isActivityStartsLoggingEnabled() {
return mAmInternal.isActivityStartsLoggingEnabled();
}
diff --git a/services/core/java/com/android/server/wm/BackNavigationController.java b/services/core/java/com/android/server/wm/BackNavigationController.java
index 767effd..87867f6 100644
--- a/services/core/java/com/android/server/wm/BackNavigationController.java
+++ b/services/core/java/com/android/server/wm/BackNavigationController.java
@@ -283,8 +283,10 @@
// keyguard locked and activities are unable to show when locked.
backType = BackNavigationInfo.TYPE_CALLBACK;
}
- } else if (currentTask.mAtmService.getLockTaskController().isTaskLocked(currentTask)) {
+ } else if (currentTask.mAtmService.getLockTaskController().isTaskLocked(currentTask)
+ || currentTask.getWindowConfiguration().tasksAreFloating()) {
// Do not predict if current task is in task locked.
+ // Also, it is unable to play cross task animation for floating task.
backType = BackNavigationInfo.TYPE_CALLBACK;
} else {
// Check back-to-home or cross-task
diff --git a/services/core/java/com/android/server/wm/DimmerAnimationHelper.java b/services/core/java/com/android/server/wm/DimmerAnimationHelper.java
index 37e4449..3dba57f 100644
--- a/services/core/java/com/android/server/wm/DimmerAnimationHelper.java
+++ b/services/core/java/com/android/server/wm/DimmerAnimationHelper.java
@@ -55,11 +55,10 @@
Change() {}
- void copyFrom(@NonNull Change other) {
+ Change(@NonNull Change other) {
mAlpha = other.mAlpha;
mBlurRadius = other.mBlurRadius;
mDimmingContainer = other.mDimmingContainer;
- mGeometryParent = other.mGeometryParent;
mRelativeLayer = other.mRelativeLayer;
}
@@ -84,8 +83,8 @@
}
}
- private final Change mCurrentProperties = new Change();
- private final Change mRequestedProperties = new Change();
+ private Change mCurrentProperties = new Change();
+ private Change mRequestedProperties = new Change();
private AnimationSpec mAlphaAnimationSpec;
private final AnimationAdapterFactory mAnimationAdapterFactory;
@@ -129,7 +128,7 @@
+ "call adjustRelativeLayer?");
return;
}
- if (mRequestedProperties.mDimmingContainer.getSurfaceControl() == null) {
+ if (mRequestedProperties.mDimmingContainer.mSurfaceControl == null) {
Log.w(TAG, "container " + mRequestedProperties.mDimmingContainer
+ "does not have a surface");
dim.remove(t);
@@ -155,35 +154,35 @@
"%s skipping animation and directly setting alpha=%f, blur=%d",
dim, mRequestedProperties.mAlpha,
mRequestedProperties.mBlurRadius);
- mCurrentProperties.copyFrom(mRequestedProperties);
- setCurrentAlphaBlur(dim.mDimSurface, t);
+ setAlphaBlur(dim.mDimSurface, mRequestedProperties.mAlpha,
+ mRequestedProperties.mBlurRadius, t);
dim.mSkipAnimation = false;
} else {
- Change startProperties = mCurrentProperties;
- mCurrentProperties.copyFrom(mRequestedProperties);
- startAnimation(t, dim, startProperties, mRequestedProperties);
+ startAnimation(t, dim);
}
+
} else if (!dim.isDimming()) {
// We are not dimming, so we tried the exit animation but the alpha is already 0,
// therefore, let's just remove this surface
dim.remove(t);
}
+ mCurrentProperties = new Change(mRequestedProperties);
}
private void startAnimation(
- @NonNull SurfaceControl.Transaction t, @NonNull Dimmer.DimState dim,
- @NonNull Change from, @NonNull Change to) {
+ @NonNull SurfaceControl.Transaction t, @NonNull Dimmer.DimState dim) {
ProtoLog.v(WM_DEBUG_DIMMER, "Starting animation on %s", dim);
- mAlphaAnimationSpec = getRequestedAnimationSpec(from, to);
+ mAlphaAnimationSpec = getRequestedAnimationSpec();
mLocalAnimationAdapter = mAnimationAdapterFactory.get(mAlphaAnimationSpec,
dim.mHostContainer.mWmService.mSurfaceAnimationRunner);
- float targetAlpha = to.mAlpha;
+ float targetAlpha = mRequestedProperties.mAlpha;
+ int targetBlur = mRequestedProperties.mBlurRadius;
mLocalAnimationAdapter.startAnimation(dim.mDimSurface, t,
ANIMATION_TYPE_DIMMER, /* finishCallback */ (type, animator) -> {
synchronized (dim.mHostContainer.mWmService.mGlobalLock) {
- setCurrentAlphaBlur(dim.mDimSurface, t);
+ setAlphaBlur(dim.mDimSurface, targetAlpha, targetBlur, t);
if (targetAlpha == 0f && !dim.isDimming()) {
dim.remove(t);
}
@@ -208,15 +207,15 @@
}
@NonNull
- private static AnimationSpec getRequestedAnimationSpec(Change from, Change to) {
- final float startAlpha = Math.max(from.mAlpha, 0f);
- final int startBlur = Math.max(from.mBlurRadius, 0);
- long duration = (long) (getDimDuration(to.mDimmingContainer)
- * Math.abs(to.mAlpha - startAlpha));
+ private AnimationSpec getRequestedAnimationSpec() {
+ final float startAlpha = Math.max(mCurrentProperties.mAlpha, 0f);
+ final int startBlur = Math.max(mCurrentProperties.mBlurRadius, 0);
+ long duration = (long) (getDimDuration(mRequestedProperties.mDimmingContainer)
+ * Math.abs(mRequestedProperties.mAlpha - startAlpha));
final AnimationSpec spec = new AnimationSpec(
- new AnimationSpec.AnimationExtremes<>(startAlpha, to.mAlpha),
- new AnimationSpec.AnimationExtremes<>(startBlur, to.mBlurRadius),
+ new AnimationSpec.AnimationExtremes<>(startAlpha, mRequestedProperties.mAlpha),
+ new AnimationSpec.AnimationExtremes<>(startBlur, mRequestedProperties.mBlurRadius),
duration
);
ProtoLog.v(WM_DEBUG_DIMMER, "Dim animation requested: %s", spec);
@@ -226,7 +225,7 @@
/**
* Change the geometry and relative parent of this dim layer
*/
- static void reparent(@NonNull SurfaceControl dimLayer,
+ void reparent(@NonNull SurfaceControl dimLayer,
@Nullable SurfaceControl newGeometryParent,
@NonNull SurfaceControl relativeParent,
int relativePosition,
@@ -241,16 +240,17 @@
}
}
- void setCurrentAlphaBlur(@NonNull SurfaceControl sc, @NonNull SurfaceControl.Transaction t) {
+ void setAlphaBlur(@NonNull SurfaceControl sc, float alpha, int blur,
+ @NonNull SurfaceControl.Transaction t) {
try {
- t.setAlpha(sc, mCurrentProperties.mAlpha);
- t.setBackgroundBlurRadius(sc, mCurrentProperties.mBlurRadius);
+ t.setAlpha(sc, alpha);
+ t.setBackgroundBlurRadius(sc, blur);
} catch (NullPointerException e) {
Log.w(TAG , "Tried to change look of dim " + sc + " after remove", e);
}
}
- private static long getDimDuration(@NonNull WindowContainer<?> container) {
+ private long getDimDuration(@NonNull WindowContainer<?> container) {
// Use the same duration as the animation on the WindowContainer
AnimationAdapter animationAdapter = container.mSurfaceAnimator.getAnimation();
final float durationScale = container.mWmService.getTransitionAnimationScaleLocked();
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 648f6bd..86285fb 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -3496,10 +3496,7 @@
*/
void collectDisplayChange(@NonNull Transition transition) {
if (!mLastHasContent) return;
- if (!transition.isCollecting()) {
- throw new IllegalArgumentException("Can only collect display change if transition"
- + " is collecting");
- }
+ if (!transition.isCollecting()) return;
if (!transition.mParticipants.contains(this)) {
transition.collect(this);
startAsyncRotationIfNeeded();
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index b528e20..4ca4730 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -1002,6 +1002,7 @@
// complete configuration.
continue;
}
+ win.updateSurfacePositionIfNeeded();
win.reportResized();
mWmService.mResizingWindows.remove(i);
}
@@ -3427,26 +3428,30 @@
boolean allResumedActivitiesIdle() {
for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
- // TODO(b/117135575): Check resumed activities on all visible root tasks.
final DisplayContent display = getChildAt(displayNdx);
if (display.isSleeping()) {
// No resumed activities while display is sleeping.
continue;
}
- // If the focused root task is not null or not empty, there should have some activities
- // resuming or resumed. Make sure these activities are idle.
- final Task rootTask = display.getFocusedRootTask();
- if (rootTask == null || !rootTask.hasActivity()) {
- continue;
- }
- final ActivityRecord resumedActivity = rootTask.getTopResumedActivity();
- if (resumedActivity == null || !resumedActivity.idle) {
- ProtoLog.d(WM_DEBUG_STATES, "allResumedActivitiesIdle: rootTask=%d %s "
- + "not idle", rootTask.getRootTaskId(), resumedActivity);
+ final boolean foundNotIdle = display.forAllLeafTaskFragments(tf -> {
+ if (!tf.isVisibleRequested()) {
+ return false;
+ }
+ // Note that only activities that will be resumed can report idle.
+ final ActivityRecord r = tf.topRunningActivity();
+ if (r != null && !r.idle && (r.isState(RESUMED)
+ // Its process is not attached yet and it may resume later.
+ || (r.app == null && r.isFocusable()))) {
+ ProtoLog.d(WM_DEBUG_STATES, "allResumedActivitiesIdle: %s not idle", r);
+ return true;
+ }
+ return false;
+ });
+ if (foundNotIdle) {
return false;
}
- if (mTransitionController.isTransientLaunch(resumedActivity)) {
+ if (mTransitionController.hasTransientLaunch(display)) {
// Not idle if the transient transition animation is running.
return false;
}
diff --git a/services/core/java/com/android/server/wm/TransitionController.java b/services/core/java/com/android/server/wm/TransitionController.java
index ef25eda..1d2b693 100644
--- a/services/core/java/com/android/server/wm/TransitionController.java
+++ b/services/core/java/com/android/server/wm/TransitionController.java
@@ -408,6 +408,10 @@
*/
@Nullable
Transition getCollectingTransition() {
+ if (mCollectingTransition != null && !mCollectingTransition.isCollecting()) {
+ Slog.wtfStack(TAG, "Collecting Transition (#" + mCollectingTransition.getSyncId()
+ + ") is not collecting. state=" + mCollectingTransition.getState());
+ }
return mCollectingTransition;
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index bdb1d43..87c0084 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -32,6 +32,7 @@
import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
import static android.app.StatusBarManager.DISABLE_MASK;
import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED;
import static android.content.pm.PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT;
import static android.content.pm.PackageManager.FEATURE_PC;
@@ -9024,14 +9025,7 @@
}
clearPointerDownOutsideFocusRunnable();
- // For embedded activity that is showing side-by-side with another activity, delay
- // handling the touch-outside event to prevent focus rapid changes back-n-forth.
- // Otherwise, handle the touch-outside event directly.
- final WindowState w = t.getWindowState();
- final ActivityRecord activity = w != null ? w.getActivityRecord() : null;
- if (mFocusedInputTarget != t && mFocusedInputTarget != null
- && activity != null && activity.isEmbedded()
- && activity.getTaskFragment().getAdjacentTaskFragment() != null) {
+ if (shouldDelayTouchOutside(t)) {
mPointerDownOutsideFocusRunnable = () -> handlePointerDownOutsideFocus(t);
mH.postDelayed(mPointerDownOutsideFocusRunnable, POINTER_DOWN_OUTSIDE_FOCUS_TIMEOUT_MS);
} else if (!fromHandler) {
@@ -9044,6 +9038,33 @@
}
}
+ private boolean shouldDelayTouchOutside(InputTarget t) {
+ final WindowState w = t.getWindowState();
+ final ActivityRecord activity = w != null ? w.getActivityRecord() : null;
+ final Task task = w != null ? w.getRootTask() : null;
+
+ final boolean isInputTargetNotFocused =
+ mFocusedInputTarget != t && mFocusedInputTarget != null;
+ if (!isInputTargetNotFocused) {
+ return false;
+ }
+
+ // For embedded activity that is showing side-by-side with another activity, delay
+ // handling the touch-outside event to prevent focus rapid changes back-n-forth.
+ final boolean shouldDelayTouchForEmbeddedActivity = activity != null
+ && activity.isEmbedded()
+ && activity.getTaskFragment().getAdjacentTaskFragment() != null;
+
+ // For cases when there are multiple freeform windows where non-top windows are blocking
+ // the gesture zones, delay handling the touch-outside event to prevent refocusing the
+ // the non-top windows during the gesture.
+ final boolean shouldDelayTouchForFreeform =
+ task != null && task.getWindowingMode() == WINDOWING_MODE_FREEFORM;
+
+ // If non of the above cases are true, handle the touch-outside event directly.
+ return shouldDelayTouchForEmbeddedActivity || shouldDelayTouchForFreeform;
+ }
+
private void handlePointerDownOutsideFocus(InputTarget t) {
synchronized (mGlobalLock) {
if (mPointerDownOutsideFocusRunnable != null
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 923ad4b..4568f2e 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -5333,6 +5333,14 @@
super.prepareSurfaces();
}
+ void updateSurfacePositionIfNeeded() {
+ if (mWindowFrames.mRelFrame.top == mWindowFrames.mLastRelFrame.top
+ && mWindowFrames.mRelFrame.left == mWindowFrames.mLastRelFrame.left) {
+ return;
+ }
+ updateSurfacePosition(getSyncTransaction());
+ }
+
@Override
@VisibleForTesting
void updateSurfacePosition(Transaction t) {
diff --git a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
index dab3978..8332b8b 100644
--- a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
+++ b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
@@ -46,12 +46,12 @@
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.art.ArtManagerLocal;
+import com.android.server.profcollect.Utils;
import com.android.server.wm.ActivityMetricsLaunchObserver;
import com.android.server.wm.ActivityMetricsLaunchObserverRegistry;
import com.android.server.wm.ActivityTaskManagerInternal;
import java.util.Arrays;
-import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
/**
@@ -280,11 +280,7 @@
return;
}
- // Sample for a fraction of app launches.
- int traceFrequency = DeviceConfig.getInt(DeviceConfig.NAMESPACE_PROFCOLLECT_NATIVE_BOOT,
- "applaunch_trace_freq", 2);
- int randomNum = ThreadLocalRandom.current().nextInt(100);
- if (randomNum < traceFrequency) {
+ if (Utils.withFrequency("applaunch_trace_freq", 2)) {
BackgroundThread.get().getThreadHandler().post(() -> {
try {
mIProfcollect.trace_system("applaunch");
@@ -318,12 +314,7 @@
if (mIProfcollect == null) {
return;
}
- // Sample for a fraction of dex2oat runs.
- final int traceFrequency =
- DeviceConfig.getInt(DeviceConfig.NAMESPACE_PROFCOLLECT_NATIVE_BOOT,
- "dex2oat_trace_freq", 25);
- int randomNum = ThreadLocalRandom.current().nextInt(100);
- if (randomNum < traceFrequency) {
+ if (Utils.withFrequency("dex2oat_trace_freq", 25)) {
// Dex2oat could take a while before it starts. Add a short delay before start tracing.
BackgroundThread.get().getThreadHandler().postDelayed(() -> {
try {
@@ -393,27 +384,22 @@
if (Arrays.asList(cameraSkipPackages).contains(packageId)) {
return;
}
- // Sample for a fraction of camera events.
- final int traceFrequency =
- DeviceConfig.getInt(DeviceConfig.NAMESPACE_PROFCOLLECT_NATIVE_BOOT,
- "camera_trace_freq", 10);
- int randomNum = ThreadLocalRandom.current().nextInt(100);
- if (randomNum >= traceFrequency) {
- return;
- }
- final int traceDuration = 5000;
- final String traceTag = "camera";
- BackgroundThread.get().getThreadHandler().post(() -> {
- if (mIProfcollect == null) {
- return;
- }
- try {
- mIProfcollect.trace_process(traceTag, "android.hardware.camera.provider",
+ if (Utils.withFrequency("camera_trace_freq", 10)) {
+ final int traceDuration = 5000;
+ final String traceTag = "camera";
+ BackgroundThread.get().getThreadHandler().post(() -> {
+ if (mIProfcollect == null) {
+ return;
+ }
+ try {
+ mIProfcollect.trace_process(traceTag,
+ "android.hardware.camera.provider",
traceDuration);
- } catch (RemoteException e) {
- Log.e(LOG_TAG, "Failed to initiate trace: " + e.getMessage());
- }
- });
+ } catch (RemoteException e) {
+ Log.e(LOG_TAG, "Failed to initiate trace: " + e.getMessage());
+ }
+ });
+ }
}
}, null);
}
diff --git a/services/profcollect/src/com/android/server/profcollect/Utils.java b/services/profcollect/src/com/android/server/profcollect/Utils.java
new file mode 100644
index 0000000..d5ef14c
--- /dev/null
+++ b/services/profcollect/src/com/android/server/profcollect/Utils.java
@@ -0,0 +1,32 @@
+/**
+ * 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.server.profcollect;
+
+import android.provider.DeviceConfig;
+
+import java.util.concurrent.ThreadLocalRandom;
+
+public final class Utils {
+
+ public static boolean withFrequency(String configName, int defaultFrequency) {
+ int threshold = DeviceConfig.getInt(
+ DeviceConfig.NAMESPACE_PROFCOLLECT_NATIVE_BOOT, configName, defaultFrequency);
+ int randomNum = ThreadLocalRandom.current().nextInt(100);
+ return randomNum < threshold;
+ }
+
+}
\ No newline at end of file
diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java
index 2b03dc4..bbf2ecb 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java
@@ -69,7 +69,6 @@
import android.companion.virtual.IVirtualDevice;
import android.companion.virtual.IVirtualDeviceManager;
import android.companion.virtual.VirtualDeviceManager;
-import android.companion.virtual.flags.Flags;
import android.compat.testing.PlatformCompatChangeRule;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -374,7 +373,6 @@
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
when(mMockFlags.isConnectedDisplayManagementEnabled()).thenReturn(false);
- mSetFlagsRule.disableFlags(Flags.FLAG_INTERACTIVE_SCREEN_MIRROR);
mLocalServiceKeeperRule.overrideLocalService(
InputManagerInternal.class, mMockInputManagerInternal);
@@ -1298,44 +1296,11 @@
}
/**
- * Tests that it's not allowed to create an auto-mirror virtual display when display mirroring
- * is not supported in a virtual device.
- */
- @Test
- public void createAutoMirrorDisplay_virtualDeviceDoesntSupportMirroring_throwsException()
- throws Exception {
- mSetFlagsRule.disableFlags(Flags.FLAG_INTERACTIVE_SCREEN_MIRROR);
- DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
- DisplayManagerInternal localService = displayManager.new LocalService();
- registerDefaultDisplays(displayManager);
- when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
- when(mContext.checkCallingPermission(CAPTURE_VIDEO_OUTPUT)).thenReturn(
- PackageManager.PERMISSION_DENIED);
- IVirtualDevice virtualDevice = mock(IVirtualDevice.class);
- when(virtualDevice.getDeviceId()).thenReturn(1);
- when(mIVirtualDeviceManager.isValidVirtualDeviceId(1)).thenReturn(true);
-
- final VirtualDisplayConfig.Builder builder =
- new VirtualDisplayConfig.Builder(VIRTUAL_DISPLAY_NAME, 600, 800, 320)
- .setFlags(VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR)
- .setUniqueId("uniqueId --- mirror display");
- assertThrows(SecurityException.class, () -> {
- localService.createVirtualDisplay(
- builder.build(),
- mMockAppToken /* callback */,
- virtualDevice /* virtualDeviceToken */,
- mock(DisplayWindowPolicyController.class),
- PACKAGE_NAME);
- });
- }
-
- /**
* Tests that the virtual display is added to the default display group when created with
* VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR using a virtual device.
*/
@Test
public void createAutoMirrorVirtualDisplay_addsDisplayToDefaultDisplayGroup() throws Exception {
- mSetFlagsRule.enableFlags(Flags.FLAG_INTERACTIVE_SCREEN_MIRROR);
DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
DisplayManagerInternal localService = displayManager.new LocalService();
registerDefaultDisplays(displayManager);
@@ -1368,7 +1333,6 @@
*/
@Test
public void createAutoMirrorVirtualDisplay_mirrorsDefaultDisplay() throws Exception {
- mSetFlagsRule.enableFlags(Flags.FLAG_INTERACTIVE_SCREEN_MIRROR);
DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
DisplayManagerInternal localService = displayManager.new LocalService();
registerDefaultDisplays(displayManager);
@@ -1400,7 +1364,6 @@
*/
@Test
public void createOwnContentOnlyVirtualDisplay_doesNotMirrorAnyDisplay() throws Exception {
- mSetFlagsRule.enableFlags(Flags.FLAG_INTERACTIVE_SCREEN_MIRROR);
DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
DisplayManagerInternal localService = displayManager.new LocalService();
registerDefaultDisplays(displayManager);
@@ -1436,7 +1399,6 @@
*/
@Test
public void createAutoMirrorVirtualDisplay_flagAlwaysUnlockedNotSet() throws Exception {
- mSetFlagsRule.enableFlags(Flags.FLAG_INTERACTIVE_SCREEN_MIRROR);
DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
DisplayManagerInternal localService = displayManager.new LocalService();
registerDefaultDisplays(displayManager);
@@ -1472,7 +1434,6 @@
*/
@Test
public void createAutoMirrorVirtualDisplay_flagPresentationNotSet() throws Exception {
- mSetFlagsRule.enableFlags(Flags.FLAG_INTERACTIVE_SCREEN_MIRROR);
DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
DisplayManagerInternal localService = displayManager.new LocalService();
registerDefaultDisplays(displayManager);
diff --git a/services/tests/displayservicetests/src/com/android/server/display/ExternalDisplayPolicyTest.java b/services/tests/displayservicetests/src/com/android/server/display/ExternalDisplayPolicyTest.java
index 82acaf8..f728168 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/ExternalDisplayPolicyTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/ExternalDisplayPolicyTest.java
@@ -258,6 +258,7 @@
when(mMockedLogicalDisplay.isEnabledLocked()).thenReturn(false);
mExternalDisplayPolicy.handleExternalDisplayConnectedLocked(mMockedLogicalDisplay);
+ mHandler.flush();
verify(mMockedInjector, never()).sendExternalDisplayEventLocked(any(), anyInt());
verify(mMockedDisplayNotificationManager, times(2))
.onHighTemperatureExternalDisplayNotAllowed();
diff --git a/services/tests/displayservicetests/src/com/android/server/display/notifications/DisplayNotificationManagerTest.java b/services/tests/displayservicetests/src/com/android/server/display/notifications/DisplayNotificationManagerTest.java
index d6c8ceb..97c12bb 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/notifications/DisplayNotificationManagerTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/notifications/DisplayNotificationManagerTest.java
@@ -30,6 +30,7 @@
import android.app.Notification;
import android.app.NotificationManager;
+import android.os.UserHandle;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.filters.SmallTest;
@@ -70,6 +71,8 @@
private ArgumentCaptor<Integer> mNotifyNoteIdCaptor;
@Captor
private ArgumentCaptor<Notification> mNotifyAsUserNotificationCaptor;
+ @Captor
+ private ArgumentCaptor<UserHandle> mNotifyAsUserCaptor;
/** Setup tests. */
@Before
@@ -127,7 +130,8 @@
dnm.onDisplayPortLinkTrainingFailure();
dnm.onCableNotCapableDisplayPort();
dnm.onHighTemperatureExternalDisplayNotAllowed();
- verify(mMockedNotificationManager, never()).notify(anyString(), anyInt(), any());
+ verify(mMockedNotificationManager, never()).notifyAsUser(anyString(), anyInt(), any(),
+ any());
}
@Test
@@ -175,10 +179,11 @@
}
private void assertExpectedNotification() {
- verify(mMockedNotificationManager).notify(
+ verify(mMockedNotificationManager).notifyAsUser(
mNotifyTagCaptor.capture(),
mNotifyNoteIdCaptor.capture(),
- mNotifyAsUserNotificationCaptor.capture());
+ mNotifyAsUserNotificationCaptor.capture(),
+ mNotifyAsUserCaptor.capture());
assertThat(mNotifyTagCaptor.getValue()).isEqualTo("DisplayNotificationManager");
assertThat((int) mNotifyNoteIdCaptor.getValue()).isEqualTo(1);
final var notification = mNotifyAsUserNotificationCaptor.getValue();
@@ -188,5 +193,7 @@
assertThat(notification.flags & FLAG_ONGOING_EVENT).isEqualTo(0);
assertThat(notification.when).isEqualTo(0);
assertThat(notification.getTimeoutAfter()).isEqualTo(30000L);
+ final var user = mNotifyAsUserCaptor.getValue();
+ assertThat(user).isEqualTo(UserHandle.CURRENT);
}
}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricLoggerTest.java b/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricLoggerTest.java
index 238a928..8f23ab9 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricLoggerTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricLoggerTest.java
@@ -236,6 +236,13 @@
}
@Test
+ public void testFingerprintsLoe() {
+ mLogger = createLogger();
+ mLogger.logFingerprintsLoe();
+ verify(mSink).reportFingerprintsLoe(eq(DEFAULT_MODALITY));
+ }
+
+ @Test
public void testALSCallback() {
mLogger = createLogger();
final CallbackWithProbe<Probe> callback =
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInternalCleanupClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInternalCleanupClientTest.java
index 242880c..7dcf841 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInternalCleanupClientTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInternalCleanupClientTest.java
@@ -182,13 +182,22 @@
public void invalidBiometricUserState() throws Exception {
mClient = createClient();
+ final List<Fingerprint> templates = List.of(
+ new Fingerprint("one", 1, 1),
+ new Fingerprint("two", 2, 1),
+ new Fingerprint("three", 3, 1)
+ );
+
final List<Fingerprint> list = new ArrayList<>();
doReturn(true).when(mFingerprintUtils)
.hasValidBiometricUserState(mContext, 2);
doReturn(list).when(mFingerprintUtils).getBiometricsForUser(mContext, 2);
mClient.start(mCallback);
- mClient.onEnumerationResult(null, 0);
+ for (int i = templates.size() - 1; i >= 0; i--) {
+ mClient.getCurrentEnumerateClient().onEnumerationResult(templates.get(i), i);
+ }
+ verify(mLogger).logFingerprintsLoe();
verify(mFingerprintUtils).deleteStateForUser(2);
}
diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java
index c288212..4d067f6 100644
--- a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java
@@ -62,7 +62,6 @@
import android.companion.virtual.VirtualDeviceParams;
import android.companion.virtual.audio.IAudioConfigChangedCallback;
import android.companion.virtual.audio.IAudioRoutingCallback;
-import android.companion.virtual.flags.Flags;
import android.companion.virtual.sensor.VirtualSensor;
import android.companion.virtual.sensor.VirtualSensorCallback;
import android.companion.virtual.sensor.VirtualSensorConfig;
@@ -1686,7 +1685,6 @@
@Test
public void openNonBlockedAppOnMirrorDisplay_flagEnabled_cannotBeLaunched() {
- mSetFlagsRule.enableFlags(Flags.FLAG_INTERACTIVE_SCREEN_MIRROR);
when(mDisplayManagerInternalMock.getDisplayIdToMirror(anyInt()))
.thenReturn(Display.DEFAULT_DISPLAY);
addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
@@ -1711,31 +1709,6 @@
}
@Test
- public void openNonBlockedAppOnMirrorDisplay_flagDisabled_launchesActivity() {
- mSetFlagsRule.disableFlags(Flags.FLAG_INTERACTIVE_SCREEN_MIRROR);
- when(mDisplayManagerInternalMock.getDisplayIdToMirror(anyInt()))
- .thenReturn(Display.DEFAULT_DISPLAY);
- addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
- GenericWindowPolicyController gwpc = mDeviceImpl.getDisplayWindowPolicyControllerForTest(
- DISPLAY_ID_1);
- doNothing().when(mContext).startActivityAsUser(any(), any(), any());
-
- ActivityInfo activityInfo = getActivityInfo(
- NONBLOCKED_APP_PACKAGE_NAME,
- NONBLOCKED_APP_PACKAGE_NAME,
- /* displayOnRemoteDevices */ true,
- /* targetDisplayCategory */ null);
- assertThat(gwpc.canActivityBeLaunched(activityInfo, null,
- WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /* isNewTask= */ false,
- /* isResultExpected = */ false, /* intentSender= */ null))
- .isTrue();
- Intent blockedAppIntent = BlockedAppStreamingActivity.createIntent(
- activityInfo, mAssociationInfo.getDisplayName());
- verify(mContext, never()).startActivityAsUser(argThat(intent ->
- intent.filterEquals(blockedAppIntent)), any(), any());
- }
-
- @Test
public void registerRunningAppsChangedListener_onRunningAppsChanged_listenersNotified() {
ArraySet<Integer> uids = new ArraySet<>(Arrays.asList(UID_1, UID_2));
addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java
index 2b93ccb..a7e8a00 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java
@@ -2148,6 +2148,40 @@
.hasSize(1);
}
+
+ @Test
+ public void handleReportAudioStatus_SamOnAvrStandby_startSystemAudioActionFromTv() {
+ mHdmiControlService.getHdmiCecConfig().setIntValue(
+ HdmiControlManager.CEC_SETTING_NAME_SYSTEM_AUDIO_CONTROL,
+ HdmiControlManager.SYSTEM_AUDIO_CONTROL_ENABLED);
+ // Emulate Audio device on port 0x1000 (does not support ARC)
+ mNativeWrapper.setPortConnectionStatus(1, true);
+ HdmiCecMessage reportPhysicalAddress =
+ HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
+ ADDR_AUDIO_SYSTEM, 0x1000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM);
+ HdmiCecMessage reportPowerStatus =
+ HdmiCecMessageBuilder.buildReportPowerStatus(ADDR_AUDIO_SYSTEM, ADDR_TV,
+ HdmiControlManager.POWER_STATUS_STANDBY);
+ mNativeWrapper.onCecMessage(reportPhysicalAddress);
+ mNativeWrapper.onCecMessage(reportPowerStatus);
+ mTestLooper.dispatchAll();
+ assertThat(mHdmiCecLocalDeviceTv.getActions(SystemAudioActionFromTv.class)).hasSize(0);
+
+ HdmiCecFeatureAction systemAudioAutoInitiationAction =
+ new SystemAudioAutoInitiationAction(mHdmiCecLocalDeviceTv, ADDR_AUDIO_SYSTEM);
+ mHdmiCecLocalDeviceTv.addAndStartAction(systemAudioAutoInitiationAction);
+ HdmiCecMessage reportSystemAudioMode =
+ HdmiCecMessageBuilder.buildReportSystemAudioMode(
+ ADDR_AUDIO_SYSTEM,
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+ true);
+ mHdmiControlService.handleCecCommand(reportSystemAudioMode);
+ mTestLooper.dispatchAll();
+
+ // SAM must be on; ARC must be off
+ assertThat(mHdmiCecLocalDeviceTv.getActions(SystemAudioActionFromTv.class)).hasSize(1);
+ }
+
protected static class MockTvDevice extends HdmiCecLocalDeviceTv {
MockTvDevice(HdmiControlService service) {
super(service);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/GroupHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/GroupHelperTest.java
index 225c1dc..51f64ba 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/GroupHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/GroupHelperTest.java
@@ -31,10 +31,11 @@
import static android.app.Notification.VISIBILITY_SECRET;
import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
import static android.app.NotificationManager.IMPORTANCE_LOW;
+import static android.service.notification.Flags.FLAG_NOTIFICATION_CLASSIFICATION;
import static android.service.notification.Flags.FLAG_NOTIFICATION_FORCE_GROUPING;
+import static android.service.notification.NotificationListenerService.REASON_APP_CANCEL;
import static android.platform.test.flag.junit.SetFlagsRule.DefaultInitValueType.DEVICE_DEFAULT;
-import static android.service.notification.NotificationListenerService.REASON_APP_CANCEL;
import static com.android.server.notification.GroupHelper.AGGREGATE_GROUP_KEY;
import static com.android.server.notification.GroupHelper.AUTOGROUP_KEY;
import static com.android.server.notification.GroupHelper.BASE_FLAGS;
@@ -2518,17 +2519,7 @@
assertThat(cachedSummary).isNull();
}
- @Test
- @EnableFlags(FLAG_NOTIFICATION_FORCE_GROUPING)
- public void testGroupSectioners() {
- final NotificationRecord notification_alerting = getNotificationRecord(mPkg, 0, "", mUser,
- "", false, IMPORTANCE_DEFAULT);
- assertThat(GroupHelper.getSection(notification_alerting).mName).isEqualTo("AlertingSection");
-
- final NotificationRecord notification_silent = getNotificationRecord(mPkg, 0, "", mUser,
- "", false, IMPORTANCE_LOW);
- assertThat(GroupHelper.getSection(notification_silent).mName).isEqualTo("SilentSection");
-
+ private void checkNonGroupableNotifications() {
NotificationRecord notification_conversation = mock(NotificationRecord.class);
when(notification_conversation.isConversation()).thenReturn(true);
assertThat(GroupHelper.getSection(notification_conversation)).isNull();
@@ -2545,7 +2536,7 @@
assertThat(GroupHelper.getSection(notification_call)).isNull();
NotificationRecord notification_colorFg = spy(getNotificationRecord(mPkg, 0, "", mUser,
- "", false, IMPORTANCE_LOW));
+ "", false, IMPORTANCE_LOW));
sbn = spy(getSbn("package", 0, "0", UserHandle.SYSTEM));
n = mock(Notification.class);
when(notification_colorFg.isConversation()).thenReturn(false);
@@ -2558,4 +2549,97 @@
assertThat(GroupHelper.getSection(notification_colorFg)).isNull();
}
+ @Test
+ @EnableFlags(FLAG_NOTIFICATION_FORCE_GROUPING)
+ @DisableFlags(FLAG_NOTIFICATION_CLASSIFICATION)
+ public void testGroupSectioners() {
+ final NotificationRecord notification_alerting = getNotificationRecord(mPkg, 0, "", mUser,
+ "", false, IMPORTANCE_DEFAULT);
+ assertThat(GroupHelper.getSection(notification_alerting).mName).isEqualTo(
+ "AlertingSection");
+
+ final NotificationRecord notification_silent = getNotificationRecord(mPkg, 0, "", mUser,
+ "", false, IMPORTANCE_LOW);
+ assertThat(GroupHelper.getSection(notification_silent).mName).isEqualTo("SilentSection");
+
+ // Check that special categories are grouped by their importance
+ final NotificationChannel promoChannel = new NotificationChannel(
+ NotificationChannel.PROMOTIONS_ID, NotificationChannel.PROMOTIONS_ID,
+ IMPORTANCE_DEFAULT);
+ final NotificationRecord notification_promotion = getNotificationRecord(mPkg, 0, "", mUser,
+ "", false, promoChannel);
+ assertThat(GroupHelper.getSection(notification_promotion).mName).isEqualTo(
+ "AlertingSection");
+
+ final NotificationChannel newsChannel = new NotificationChannel(NotificationChannel.NEWS_ID,
+ NotificationChannel.NEWS_ID, IMPORTANCE_DEFAULT);
+ final NotificationRecord notification_news = getNotificationRecord(mPkg, 0, "", mUser,
+ "", false, newsChannel);
+ assertThat(GroupHelper.getSection(notification_news).mName).isEqualTo(
+ "AlertingSection");
+
+ final NotificationChannel socialChannel = new NotificationChannel(
+ NotificationChannel.SOCIAL_MEDIA_ID, NotificationChannel.SOCIAL_MEDIA_ID,
+ IMPORTANCE_DEFAULT);
+ final NotificationRecord notification_social = getNotificationRecord(mPkg, 0, "", mUser,
+ "", false, socialChannel);
+ assertThat(GroupHelper.getSection(notification_social).mName).isEqualTo(
+ "AlertingSection");
+
+ final NotificationChannel recsChannel = new NotificationChannel(NotificationChannel.RECS_ID,
+ NotificationChannel.RECS_ID, IMPORTANCE_DEFAULT);
+ final NotificationRecord notification_recs = getNotificationRecord(mPkg, 0, "", mUser,
+ "", false, recsChannel);
+ assertThat(GroupHelper.getSection(notification_recs).mName).isEqualTo(
+ "AlertingSection");
+
+ checkNonGroupableNotifications();
+ }
+
+ @Test
+ @EnableFlags({FLAG_NOTIFICATION_FORCE_GROUPING, FLAG_NOTIFICATION_CLASSIFICATION})
+ public void testGroupSectioners_withClassificationSections() {
+ final NotificationRecord notification_alerting = getNotificationRecord(mPkg, 0, "", mUser,
+ "", false, IMPORTANCE_DEFAULT);
+ assertThat(GroupHelper.getSection(notification_alerting).mName).isEqualTo(
+ "AlertingSection");
+
+ final NotificationRecord notification_silent = getNotificationRecord(mPkg, 0, "", mUser,
+ "", false, IMPORTANCE_LOW);
+ assertThat(GroupHelper.getSection(notification_silent).mName).isEqualTo("SilentSection");
+
+ // Check that special categories are grouped in their own sections
+ final NotificationChannel promoChannel = new NotificationChannel(
+ NotificationChannel.PROMOTIONS_ID, NotificationChannel.PROMOTIONS_ID,
+ IMPORTANCE_DEFAULT);
+ final NotificationRecord notification_promotion = getNotificationRecord(mPkg, 0, "", mUser,
+ "", false, promoChannel);
+ assertThat(GroupHelper.getSection(notification_promotion).mName).isEqualTo(
+ "PromotionsSection");
+
+ final NotificationChannel newsChannel = new NotificationChannel(NotificationChannel.NEWS_ID,
+ NotificationChannel.NEWS_ID, IMPORTANCE_DEFAULT);
+ final NotificationRecord notification_news = getNotificationRecord(mPkg, 0, "", mUser,
+ "", false, newsChannel);
+ assertThat(GroupHelper.getSection(notification_news).mName).isEqualTo(
+ "NewsSection");
+
+ final NotificationChannel socialChannel = new NotificationChannel(
+ NotificationChannel.SOCIAL_MEDIA_ID, NotificationChannel.SOCIAL_MEDIA_ID,
+ IMPORTANCE_DEFAULT);
+ final NotificationRecord notification_social = getNotificationRecord(mPkg, 0, "", mUser,
+ "", false, socialChannel);
+ assertThat(GroupHelper.getSection(notification_social).mName).isEqualTo(
+ "SocialSection");
+
+ final NotificationChannel recsChannel = new NotificationChannel(NotificationChannel.RECS_ID,
+ NotificationChannel.RECS_ID, IMPORTANCE_DEFAULT);
+ final NotificationRecord notification_recs = getNotificationRecord(mPkg, 0, "", mUser,
+ "", false, recsChannel);
+ assertThat(GroupHelper.getSection(notification_recs).mName).isEqualTo(
+ "RecsSection");
+
+ checkNonGroupableNotifications();
+ }
+
}
diff --git a/services/tests/wmtests/src/com/android/server/policy/MetaKeyEventsInterceptionTests.java b/services/tests/wmtests/src/com/android/server/policy/MetaKeyEventsInterceptionTests.java
new file mode 100644
index 0000000..b979335
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/policy/MetaKeyEventsInterceptionTests.java
@@ -0,0 +1,96 @@
+/*
+ * 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.server.policy;
+
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_ALLOW_ACTION_KEY_EVENTS;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.view.KeyEvent;
+import android.view.WindowManager;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.policy.KeyInterceptionInfo;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Testing {@link PhoneWindowManager} functionality of letting app intercepting key events
+ * containing META.
+ */
+@SmallTest
+public class MetaKeyEventsInterceptionTests extends ShortcutKeyTestBase {
+
+ private static final List<KeyEvent> META_KEY_EVENTS = Arrays.asList(
+ new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_META_LEFT),
+ new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_META_RIGHT),
+ new KeyEvent(/* downTime= */ 0, /* eventTime= */
+ 0, /* action= */ 0, /* code= */ 0, /* repeat= */ 0,
+ /* metaState= */ KeyEvent.META_META_ON));
+
+ @Before
+ public void setUp() {
+ setUpPhoneWindowManager();
+ }
+
+ @Test
+ public void doesntInterceptMetaKeyEvents_whenWindowAskedForIt() {
+ mPhoneWindowManager.overrideFocusedWindowButtonOverridePermission(/* granted= */ true);
+ setWindowKeyInterceptionWithPrivateFlags(PRIVATE_FLAG_ALLOW_ACTION_KEY_EVENTS);
+
+ META_KEY_EVENTS.forEach(keyEvent -> {
+ assertKeyInterceptionResult(keyEvent, /* intercepted= */ false);
+ });
+ }
+
+ @Test
+ public void interceptsMetaKeyEvents_whenWindowDoesntHaveFlagSet() {
+ mPhoneWindowManager.overrideFocusedWindowButtonOverridePermission(/* granted= */ true);
+ setWindowKeyInterceptionWithPrivateFlags(0);
+
+ META_KEY_EVENTS.forEach(keyEvent -> {
+ assertKeyInterceptionResult(keyEvent, /* intercepted= */ true);
+ });
+ }
+
+ @Test
+ public void interceptsMetaKeyEvents_whenWindowDoesntHavePermission() {
+ mPhoneWindowManager.overrideFocusedWindowButtonOverridePermission(/* granted= */ false);
+ setWindowKeyInterceptionWithPrivateFlags(PRIVATE_FLAG_ALLOW_ACTION_KEY_EVENTS);
+
+ META_KEY_EVENTS.forEach(keyEvent -> {
+ assertKeyInterceptionResult(keyEvent, /* intercepted= */ true);
+ });
+ }
+
+ private void setWindowKeyInterceptionWithPrivateFlags(int privateFlags) {
+ KeyInterceptionInfo info = new KeyInterceptionInfo(
+ WindowManager.LayoutParams.TYPE_APPLICATION, privateFlags, "title", 0);
+ mPhoneWindowManager.overrideWindowKeyInterceptionInfo(info);
+ }
+
+ private void assertKeyInterceptionResult(KeyEvent keyEvent, boolean intercepted) {
+ long result = mPhoneWindowManager.interceptKeyBeforeDispatching(keyEvent);
+ int expected = intercepted ? -1 : 0;
+ assertThat(result).isEqualTo(expected);
+ }
+}
diff --git a/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java b/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
index 43b065d..79c7ac1 100644
--- a/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
+++ b/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
@@ -52,6 +52,7 @@
import static org.mockito.Mockito.description;
import static org.mockito.Mockito.mockingDetails;
import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.when;
import static org.mockito.Mockito.withSettings;
import android.app.ActivityManagerInternal;
@@ -613,6 +614,10 @@
.when(mButtonOverridePermissionChecker).canAppOverrideSystemKey(any(), anyInt());
}
+ void overrideWindowKeyInterceptionInfo(KeyInterceptionInfo info) {
+ when(mWindowManagerInternal.getKeyInterceptionInfoFromToken(any())).thenReturn(info);
+ }
+
void overrideKeyEventPolicyFlags(int flags) {
mKeyEventPolicyFlags = flags;
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
index 84c2c32..4ab2fcf 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
@@ -205,6 +205,28 @@
}
@Test
+ public void testAllResumedActivitiesIdle() {
+ final ActivityRecord activity1 = new ActivityBuilder(mAtm).setCreateTask(true).build();
+ final ActivityRecord activity2 = new ActivityBuilder(mAtm).setCreateTask(true).build();
+ final WindowProcessController proc2 = activity2.app;
+ activity1.setState(RESUMED, "test");
+ activity2.detachFromProcess();
+ assertThat(mWm.mRoot.allResumedActivitiesIdle()).isFalse();
+
+ activity1.idle = true;
+ assertThat(mWm.mRoot.allResumedActivitiesIdle()).isFalse();
+
+ activity2.setProcess(proc2);
+ activity2.setState(RESUMED, "test");
+ activity2.idle = true;
+ assertThat(mWm.mRoot.allResumedActivitiesIdle()).isTrue();
+
+ activity1.idle = false;
+ activity1.setVisibleRequested(false);
+ assertThat(mWm.mRoot.allResumedActivitiesIdle()).isTrue();
+ }
+
+ @Test
public void testTaskLayerRank() {
final Task rootTask = new TaskBuilder(mSupervisor).build();
final Task task1 = new TaskBuilder(mSupervisor).setParentTask(rootTask).build();
diff --git a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
index 49e349c..56fca31 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
@@ -1550,10 +1550,6 @@
// An active transient launch overrides idle state to avoid clearing power mode before the
// transition is finished.
- spyOn(mRootWindowContainer.mTransitionController);
- doAnswer(invocation -> controller.isTransientLaunch(invocation.getArgument(0))).when(
- mRootWindowContainer.mTransitionController).isTransientLaunch(any());
- activity2.getTask().setResumedActivity(activity2, "test");
activity2.idle = true;
assertFalse(mRootWindowContainer.allResumedActivitiesIdle());
diff --git a/telephony/java/android/telephony/satellite/SatelliteModemEnableRequestAttributes.java b/telephony/java/android/telephony/satellite/SatelliteModemEnableRequestAttributes.java
new file mode 100644
index 0000000..5e56f84
--- /dev/null
+++ b/telephony/java/android/telephony/satellite/SatelliteModemEnableRequestAttributes.java
@@ -0,0 +1,132 @@
+/*
+ * 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 android.telephony.satellite;
+
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * SatelliteModemEnableRequestAttributes is used to pack info needed by modem to allow carrier to
+ * roam to satellite.
+ *
+ * @hide
+ */
+public final class SatelliteModemEnableRequestAttributes implements Parcelable {
+
+ /** {@code true} to enable satellite and {@code false} to disable satellite */
+ private final boolean mIsEnabled;
+ /**
+ * {@code true} to enable demo mode and {@code false} to disable. When disabling satellite,
+ * {@code mIsDemoMode} is always considered as {@code false} by Telephony.
+ */
+ private final boolean mIsDemoMode;
+ /**
+ * {@code true} means satellite is enabled for emergency mode, {@code false} otherwise. When
+ * disabling satellite, {@code isEmergencyMode} is always considered as {@code false} by
+ * Telephony.
+ */
+ private final boolean mIsEmergencyMode;
+
+ /** The subscription related info */
+ @NonNull private final SatelliteSubscriptionInfo mSatelliteSubscriptionInfo;
+
+ public SatelliteModemEnableRequestAttributes(boolean isEnabled, boolean isDemoMode,
+ boolean isEmergencyMode, @NonNull SatelliteSubscriptionInfo satelliteSubscriptionInfo) {
+ mIsEnabled = isEnabled;
+ mIsDemoMode = isDemoMode;
+ mIsEmergencyMode = isEmergencyMode;
+ mSatelliteSubscriptionInfo = satelliteSubscriptionInfo;
+ }
+
+ private SatelliteModemEnableRequestAttributes(Parcel in) {
+ mIsEnabled = in.readBoolean();
+ mIsDemoMode = in.readBoolean();
+ mIsEmergencyMode = in.readBoolean();
+ mSatelliteSubscriptionInfo = in.readParcelable(
+ SatelliteSubscriptionInfo.class.getClassLoader(), SatelliteSubscriptionInfo.class);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeBoolean(mIsEnabled);
+ dest.writeBoolean(mIsDemoMode);
+ dest.writeBoolean(mIsEmergencyMode);
+ mSatelliteSubscriptionInfo.writeToParcel(dest, flags);
+ }
+
+ public static final Creator<SatelliteModemEnableRequestAttributes> CREATOR = new Creator<>() {
+ @Override
+ public SatelliteModemEnableRequestAttributes createFromParcel(Parcel in) {
+ return new SatelliteModemEnableRequestAttributes(in);
+ }
+
+ @Override
+ public SatelliteModemEnableRequestAttributes[] newArray(int size) {
+ return new SatelliteModemEnableRequestAttributes[size];
+ }
+ };
+
+ @Override
+ public String toString() {
+ return (new StringBuilder()).append("SatelliteModemEnableRequestAttributes{")
+ .append(", mIsEnabled=").append(mIsEnabled)
+ .append(", mIsDemoMode=").append(mIsDemoMode)
+ .append(", mIsDemoMode=").append(mIsDemoMode)
+ .append("mSatelliteSubscriptionInfo=").append(mSatelliteSubscriptionInfo)
+ .append("}")
+ .toString();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ SatelliteModemEnableRequestAttributes that = (SatelliteModemEnableRequestAttributes) o;
+ return mIsEnabled == that.mIsEnabled && mIsDemoMode == that.mIsDemoMode
+ && mIsEmergencyMode == that.mIsEmergencyMode && mSatelliteSubscriptionInfo.equals(
+ that.mSatelliteSubscriptionInfo);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mIsEnabled, mIsDemoMode, mIsEmergencyMode, mSatelliteSubscriptionInfo);
+ }
+
+ public boolean isEnabled() {
+ return mIsEnabled;
+ }
+
+ public boolean isDemoMode() {
+ return mIsDemoMode;
+ }
+
+ public boolean isEmergencyMode() {
+ return mIsEmergencyMode;
+ }
+
+ @NonNull public SatelliteSubscriptionInfo getSatelliteSubscriptionInfo() {
+ return mSatelliteSubscriptionInfo;
+ }
+}
diff --git a/telephony/java/android/telephony/satellite/SatelliteSubscriberInfo.java b/telephony/java/android/telephony/satellite/SatelliteSubscriberInfo.java
index 50ed627..dbe5ddd 100644
--- a/telephony/java/android/telephony/satellite/SatelliteSubscriberInfo.java
+++ b/telephony/java/android/telephony/satellite/SatelliteSubscriberInfo.java
@@ -268,7 +268,7 @@
@Override
public boolean equals(Object o) {
if (this == o) return true;
- if (!(o instanceof SatelliteSubscriberProvisionStatus)) return false;
+ if (!(o instanceof SatelliteSubscriberInfo)) return false;
SatelliteSubscriberInfo that = (SatelliteSubscriberInfo) o;
return Objects.equals(mSubscriberId, that.mSubscriberId) && mCarrierId == that.mCarrierId
&& Objects.equals(mNiddApn, that.mNiddApn) && mSubId == that.mSubId
diff --git a/telephony/java/android/telephony/satellite/SatelliteSubscriberProvisionStatus.java b/telephony/java/android/telephony/satellite/SatelliteSubscriberProvisionStatus.java
index e3d619e..08ef3f2 100644
--- a/telephony/java/android/telephony/satellite/SatelliteSubscriberProvisionStatus.java
+++ b/telephony/java/android/telephony/satellite/SatelliteSubscriberProvisionStatus.java
@@ -90,7 +90,7 @@
@Override
@FlaggedApi(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN)
public void writeToParcel(@NonNull Parcel out, int flags) {
- mSubscriberInfo.writeToParcel(out, flags);
+ out.writeParcelable(mSubscriberInfo, flags);
out.writeBoolean(mProvisionStatus);
}
diff --git a/telephony/java/android/telephony/satellite/SatelliteSubscriptionInfo.java b/telephony/java/android/telephony/satellite/SatelliteSubscriptionInfo.java
new file mode 100644
index 0000000..2ef19f8
--- /dev/null
+++ b/telephony/java/android/telephony/satellite/SatelliteSubscriptionInfo.java
@@ -0,0 +1,106 @@
+/*
+ * 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 android.telephony.satellite;
+
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * SatelliteSubscriptionInfo is used to pack subscription related info needed by modem to allow
+ * carrier to roam to satellite.
+ *
+ * @hide
+ */
+public final class SatelliteSubscriptionInfo implements Parcelable {
+ /**
+ * The ICC ID used for satellite attachment.
+ */
+ @NonNull private final String mIccId;
+
+ /**
+ * The NIDD(Non IP Data) APN to be used for carrier roaming to satellite attachment.
+ */
+ @NonNull private final String mNiddApn;
+
+ public SatelliteSubscriptionInfo(@NonNull String iccId, @NonNull String niddApn) {
+ mIccId = iccId;
+ mNiddApn = niddApn;
+ }
+
+ private SatelliteSubscriptionInfo(Parcel in) {
+ mIccId = in.readString8();
+ mNiddApn = in.readString8();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeString8(mIccId);
+ dest.writeString8(mNiddApn);
+ }
+
+ @NonNull public static final Creator<SatelliteSubscriptionInfo> CREATOR = new Creator<>() {
+ @Override
+ public SatelliteSubscriptionInfo createFromParcel(Parcel in) {
+ return new SatelliteSubscriptionInfo(in);
+ }
+
+ @Override
+ public SatelliteSubscriptionInfo[] newArray(int size) {
+ return new SatelliteSubscriptionInfo[size];
+ }
+ };
+
+ @Override
+ @NonNull public String toString() {
+ return (new StringBuilder()).append("SatelliteSubscriptionInfo{")
+ .append("IccId=").append(mIccId)
+ .append(", NiddApn=").append(mNiddApn)
+ .append("}")
+ .toString();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ SatelliteSubscriptionInfo that = (SatelliteSubscriptionInfo) o;
+ return mIccId.equals(that.getIccId()) && mNiddApn.equals(that.getNiddApn());
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(getIccId(), getNiddApn());
+ }
+
+ @NonNull
+ public String getIccId() {
+ return mIccId;
+ }
+
+ @NonNull
+ public String getNiddApn() {
+ return mNiddApn;
+ }
+}
diff --git a/telephony/java/android/telephony/satellite/stub/SatelliteModemEnableRequestAttributes.aidl b/telephony/java/android/telephony/satellite/stub/SatelliteModemEnableRequestAttributes.aidl
new file mode 100644
index 0000000..0a40e15
--- /dev/null
+++ b/telephony/java/android/telephony/satellite/stub/SatelliteModemEnableRequestAttributes.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2023 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 android.telephony.satellite.stub;
+
+import android.telephony.satellite.stub.SatelliteSubscriptionInfo;
+
+/**
+ * {@hide}
+ */
+ parcelable SatelliteModemEnableRequestAttributes {
+ /**
+ * {@code true} to enable satellite and {@code false} to disable.
+ */
+ boolean isEnabled;
+ /**
+ * {@code true} to enable demo mode and {@code false} to disable.
+ */
+ boolean isDemoMode;
+ /**
+ * {@code true} to enable emergency modeand {@code false} to disable.
+ */
+ boolean isEmergencyMode;
+ /**
+ * The subscription related info.
+ */
+ SatelliteSubscriptionInfo satelliteSubscriptionInfo;
+ }
\ No newline at end of file
diff --git a/telephony/java/android/telephony/satellite/stub/SatelliteSubscriptionInfo.aidl b/telephony/java/android/telephony/satellite/stub/SatelliteSubscriptionInfo.aidl
new file mode 100644
index 0000000..f664dda
--- /dev/null
+++ b/telephony/java/android/telephony/satellite/stub/SatelliteSubscriptionInfo.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2023 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 android.telephony.satellite.stub;
+
+/**
+ * {@hide}
+ */
+ parcelable SatelliteSubscriptionInfo {
+ /**
+ * The ICC ID used for satellite attachment.
+ */
+ String iccId;
+ /**
+ * The NIDD(Non IP Data) APN to be used for carrier roaming to satellite attachment.
+ */
+ String niddApn;
+ }
\ No newline at end of file
diff --git a/tests/Internal/src/com/android/internal/protolog/PerfettoProtoLogImplTest.java b/tests/Internal/src/com/android/internal/protolog/PerfettoProtoLogImplTest.java
index 4b745b2..4826f42 100644
--- a/tests/Internal/src/com/android/internal/protolog/PerfettoProtoLogImplTest.java
+++ b/tests/Internal/src/com/android/internal/protolog/PerfettoProtoLogImplTest.java
@@ -43,7 +43,6 @@
import android.tracing.perfetto.DataSource;
import android.util.proto.ProtoInputStream;
-import androidx.test.filters.SmallTest;
import androidx.test.platform.app.InstrumentationRegistry;
import com.android.internal.protolog.common.IProtoLogGroup;
@@ -73,7 +72,6 @@
* Test class for {@link ProtoLogImpl}.
*/
@SuppressWarnings("ConstantConditions")
-@SmallTest
@Presubmit
@RunWith(JUnit4.class)
public class PerfettoProtoLogImplTest {
@@ -166,8 +164,7 @@
mReader = Mockito.spy(new ProtoLogViewerConfigReader(viewerConfigInputStreamProvider));
mProtoLog = new PerfettoProtoLogImpl(
viewerConfigInputStreamProvider, mReader,
- () -> mCacheUpdater.run());
- mProtoLog.registerGroups(TestProtoLogGroup.values());
+ () -> mCacheUpdater.run(), TestProtoLogGroup.values());
}
@After
diff --git a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
index ab406ef..5b17825 100644
--- a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
+++ b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
@@ -1867,7 +1867,7 @@
return true;
}
- public String getName() {
+ public String getUniqueIdentifier() {
return mName;
}
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Exceptions.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Exceptions.kt
index 910bf59..f59e143 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Exceptions.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Exceptions.kt
@@ -15,6 +15,8 @@
*/
package com.android.hoststubgen
+import java.io.File
+
/**
* We will not print the stack trace for exceptions implementing it.
*/
@@ -49,4 +51,22 @@
/**
* We use this for general "user" errors.
*/
-class HostStubGenUserErrorException(message: String) : Exception(message), UserErrorException
+class GeneralUserErrorException(message: String) : Exception(message), UserErrorException
+
+/** Base exception class for invalid command line arguments. */
+open class ArgumentsException(message: String?) : Exception(message), UserErrorException
+
+/** Thrown when the same annotation is used with different annotation arguments. */
+class DuplicateAnnotationException(annotationName: String?) :
+ ArgumentsException("Duplicate annotation specified: '$annotationName'")
+
+/** Thrown when an input file does not exist. */
+class InputFileNotFoundException(filename: String) :
+ ArgumentsException("File '$filename' not found")
+
+fun String.ensureFileExists(): String {
+ if (!File(this).exists()) {
+ throw InputFileNotFoundException(this)
+ }
+ return this
+}
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenErrors.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenErrors.kt
index 6b01d48..a218c55 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenErrors.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenErrors.kt
@@ -19,6 +19,6 @@
open fun onErrorFound(message: String) {
// TODO: For now, we just throw as soon as any error is found, but eventually we should keep
// all errors and print them at the end.
- throw HostStubGenUserErrorException(message)
+ throw GeneralUserErrorException(message)
}
}
\ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenLogger.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenLogger.kt
index fcdf824..4bcee40 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenLogger.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenLogger.kt
@@ -89,6 +89,8 @@
addPrinter(StreamPrinter(level, PrintWriter(BufferedOutputStream(
FileOutputStream(logFilename)))))
+ log.i("Log file set: $logFilename for $level")
+
return this
}
@@ -122,6 +124,9 @@
}
fun println(level: LogLevel, message: String) {
+ if (message.isEmpty()) {
+ return // Don't print an empty message.
+ }
printers.forEach {
if (it.logLevel.ordinal >= level.ordinal) {
it.println(level, indent, message)
@@ -185,31 +190,45 @@
println(LogLevel.Debug, format, *args)
}
- inline fun <T> logTime(level: LogLevel, message: String, block: () -> T): T {
+ inline fun <T> logTime(level: LogLevel, message: String, block: () -> T): Double {
+ var ret: Double = -1.0
val start = System.currentTimeMillis()
try {
- return block()
+ block()
} finally {
val end = System.currentTimeMillis()
+ ret = (end - start) / 1000.0
if (isEnabled(level)) {
println(level,
String.format("%s: took %.1f second(s).", message, (end - start) / 1000.0))
}
}
+ return ret
}
- inline fun <T> iTime(message: String, block: () -> T): T {
+ /** Do an "i" log with how long it took. */
+ inline fun <T> iTime(message: String, block: () -> T): Double {
return logTime(LogLevel.Info, message, block)
}
- inline fun <T> vTime(message: String, block: () -> T): T {
+ /** Do a "v" log with how long it took. */
+ inline fun <T> vTime(message: String, block: () -> T): Double {
return logTime(LogLevel.Verbose, message, block)
}
- inline fun <T> dTime(message: String, block: () -> T): T {
+ /** Do a "d" log with how long it took. */
+ inline fun <T> dTime(message: String, block: () -> T): Double {
return logTime(LogLevel.Debug, message, block)
}
+ /**
+ * Similar to the other "xTime" methods, but the message is not supposed to be printed.
+ * It's only used to measure the duration with the same interface as other log methods.
+ */
+ inline fun <T> nTime(block: () -> T): Double {
+ return logTime(LogLevel.Debug, "", block)
+ }
+
inline fun forVerbose(block: () -> Unit) {
if (isEnabled(LogLevel.Verbose)) {
block()
@@ -253,6 +272,21 @@
}
}
}
+
+ /**
+ * Handle log-related command line arguments.
+ */
+ fun maybeHandleCommandLineArg(currentArg: String, nextArgProvider: () -> String): Boolean {
+ when (currentArg) {
+ "-v", "--verbose" -> setConsoleLogLevel(LogLevel.Verbose)
+ "-d", "--debug" -> setConsoleLogLevel(LogLevel.Debug)
+ "-q", "--quiet" -> setConsoleLogLevel(LogLevel.None)
+ "--verbose-log" -> addFilePrinter(LogLevel.Verbose, nextArgProvider())
+ "--debug-log" -> addFilePrinter(LogLevel.Debug, nextArgProvider())
+ else -> return false
+ }
+ return true
+ }
}
private interface LogPrinter {
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenMain.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenMain.kt
index 45e7e30..8506466 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenMain.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenMain.kt
@@ -24,20 +24,32 @@
*/
fun main(args: Array<String>) {
executableName = "HostStubGen"
+ runMainWithBoilerplate {
+ // Parse the command line arguments.
+ var clanupOnError = false
+ try {
+ val options = HostStubGenOptions.parseArgs(args)
+ clanupOnError = options.cleanUpOnError.get
+ log.v("$executableName started")
+ log.v("Options: $options")
+
+ // Run.
+ HostStubGen(options).run()
+ } catch (e: Throwable) {
+ if (clanupOnError) {
+ TODO("Remove output jars here")
+ }
+ throw e
+ }
+ }
+}
+
+inline fun runMainWithBoilerplate(realMain: () -> Unit) {
var success = false
- var clanupOnError = false
try {
- // Parse the command line arguments.
- val options = HostStubGenOptions.parseArgs(args)
- clanupOnError = options.cleanUpOnError.get
-
- log.v("$executableName started")
- log.v("Options: $options")
-
- // Run.
- HostStubGen(options).run()
+ realMain()
success = true
} catch (e: Throwable) {
@@ -45,9 +57,6 @@
if (e !is UserErrorException) {
e.printStackTrace(PrintWriter(log.getWriter(LogLevel.Error)))
}
- if (clanupOnError) {
- TODO("Remove output jars here")
- }
} finally {
log.i("$executableName finished")
log.flush()
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenOptions.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenOptions.kt
index 2f833a8..f88b107 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenOptions.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenOptions.kt
@@ -17,20 +17,17 @@
import com.android.hoststubgen.filters.FilterPolicy
import java.io.BufferedReader
-import java.io.File
import java.io.FileReader
/**
* A single value that can only set once.
*/
-class SetOnce<T>(
- private var value: T,
-) {
+open class SetOnce<T>(private var value: T) {
class SetMoreThanOnceException : Exception()
private var set = false
- fun set(v: T) {
+ fun set(v: T): T {
if (set) {
throw SetMoreThanOnceException()
}
@@ -39,6 +36,7 @@
}
set = true
value = v
+ return v
}
val get: T
@@ -59,6 +57,16 @@
}
}
+class IntSetOnce(value: Int) : SetOnce<Int>(value) {
+ fun set(v: String): Int {
+ try {
+ return this.set(v.toInt())
+ } catch (e: NumberFormatException) {
+ throw ArgumentsException("Invalid integer $v")
+ }
+ }
+}
+
/**
* Options that can be set from command line arguments.
*/
@@ -113,18 +121,11 @@
var apiListFile: SetOnce<String?> = SetOnce(null),
- var numShards: SetOnce<Int> = SetOnce(1),
- var shard: SetOnce<Int> = SetOnce(0),
+ var numShards: IntSetOnce = IntSetOnce(1),
+ var shard: IntSetOnce = IntSetOnce(0),
) {
companion object {
- private fun String.ensureFileExists(): String {
- if (!File(this).exists()) {
- throw InputFileNotFoundException(this)
- }
- return this
- }
-
private fun parsePackageRedirect(fromColonTo: String): Pair<String, String> {
val colon = fromColonTo.indexOf(':')
if ((colon < 1) || (colon + 1 >= fromColonTo.length)) {
@@ -137,7 +138,7 @@
fun parseArgs(args: Array<String>): HostStubGenOptions {
val ret = HostStubGenOptions()
- val ai = ArgIterator(expandAtFiles(args))
+ val ai = ArgIterator.withAtFiles(args)
var allAnnotations = mutableSetOf<String>()
@@ -148,11 +149,6 @@
return name
}
- fun setLogFile(level: LogLevel, filename: String) {
- log.addFilePrinter(level, filename)
- log.i("$level log file: $filename")
- }
-
while (true) {
val arg = ai.nextArgOptional()
if (arg == null) {
@@ -161,33 +157,23 @@
// Define some shorthands...
fun nextArg(): String = ai.nextArgRequired(arg)
- fun SetOnce<String>.setNextStringArg(): String = nextArg().also { this.set(it) }
- fun SetOnce<String?>.setNextStringArg(): String = nextArg().also { this.set(it) }
fun MutableSet<String>.addUniqueAnnotationArg(): String =
nextArg().also { this += ensureUniqueAnnotation(it) }
- fun SetOnce<Int>.setNextIntArg(): String = nextArg().also {
- try {
- this.set(it.toInt())
- } catch (e: NumberFormatException) {
- throw ArgumentsException("Invalid integer for $arg: $it")
- }
- }
+ if (log.maybeHandleCommandLineArg(arg) { nextArg() }) {
+ continue
+ }
try {
when (arg) {
// TODO: Write help
"-h", "--help" -> TODO("Help is not implemented yet")
- "-v", "--verbose" -> log.setConsoleLogLevel(LogLevel.Verbose)
- "-d", "--debug" -> log.setConsoleLogLevel(LogLevel.Debug)
- "-q", "--quiet" -> log.setConsoleLogLevel(LogLevel.None)
-
- "--in-jar" -> ret.inJar.setNextStringArg().ensureFileExists()
- "--out-stub-jar" -> ret.outStubJar.setNextStringArg()
- "--out-impl-jar" -> ret.outImplJar.setNextStringArg()
+ "--in-jar" -> ret.inJar.set(nextArg()).ensureFileExists()
+ "--out-stub-jar" -> ret.outStubJar.set(nextArg())
+ "--out-impl-jar" -> ret.outImplJar.set(nextArg())
"--policy-override-file" ->
- ret.policyOverrideFile.setNextStringArg().ensureFileExists()
+ ret.policyOverrideFile.set(nextArg())!!.ensureFileExists()
"--clean-up-on-error" -> ret.cleanUpOnError.set(true)
"--no-clean-up-on-error" -> ret.cleanUpOnError.set(false)
@@ -231,19 +217,19 @@
ret.packageRedirects += parsePackageRedirect(nextArg())
"--annotation-allowed-classes-file" ->
- ret.annotationAllowedClassesFile.setNextStringArg()
+ ret.annotationAllowedClassesFile.set(nextArg())
"--default-class-load-hook" ->
- ret.defaultClassLoadHook.setNextStringArg()
+ ret.defaultClassLoadHook.set(nextArg())
"--default-method-call-hook" ->
- ret.defaultMethodCallHook.setNextStringArg()
+ ret.defaultMethodCallHook.set(nextArg())
"--intersect-stub-jar" ->
ret.intersectStubJars += nextArg().ensureFileExists()
"--gen-keep-all-file" ->
- ret.inputJarAsKeepAllFile.setNextStringArg()
+ ret.inputJarAsKeepAllFile.set(nextArg())
// Following options are for debugging.
"--enable-class-checker" -> ret.enableClassChecker.set(true)
@@ -261,16 +247,21 @@
"--no-non-stub-method-check" ->
ret.enableNonStubMethodCallDetection.set(false)
- "--gen-input-dump-file" -> ret.inputJarDumpFile.setNextStringArg()
+ "--gen-input-dump-file" -> ret.inputJarDumpFile.set(nextArg())
- "--verbose-log" -> setLogFile(LogLevel.Verbose, nextArg())
- "--debug-log" -> setLogFile(LogLevel.Debug, nextArg())
+ "--stats-file" -> ret.statsFile.set(nextArg())
+ "--supported-api-list-file" -> ret.apiListFile.set(nextArg())
- "--stats-file" -> ret.statsFile.setNextStringArg()
- "--supported-api-list-file" -> ret.apiListFile.setNextStringArg()
-
- "--num-shards" -> ret.numShards.setNextIntArg()
- "--shard-index" -> ret.shard.setNextIntArg()
+ "--num-shards" -> ret.numShards.set(nextArg()).also {
+ if (it < 1) {
+ throw ArgumentsException("$arg must be positive integer")
+ }
+ }
+ "--shard-index" -> ret.shard.set(nextArg()).also {
+ if (it < 0) {
+ throw ArgumentsException("$arg must be positive integer or zero")
+ }
+ }
else -> throw ArgumentsException("Unknown option: $arg")
}
@@ -286,6 +277,15 @@
log.w("Neither --out-stub-jar nor --out-impl-jar is set." +
" $executableName will not generate jar files.")
}
+ if (ret.numShards.isSet != ret.shard.isSet) {
+ throw ArgumentsException("--num-shards and --shard-index must be used together")
+ }
+
+ if (ret.numShards.isSet) {
+ if (ret.shard.get >= ret.numShards.get) {
+ throw ArgumentsException("--shard-index must be smaller than --num-shards")
+ }
+ }
if (ret.enableNonStubMethodCallDetection.get) {
log.w("--enable-non-stub-method-check is not fully implemented yet." +
@@ -294,87 +294,6 @@
return ret
}
-
- /**
- * Scan the arguments, and if any of them starts with an `@`, then load from the file
- * and use its content as arguments.
- *
- * In this file, each line is treated as a single argument.
- *
- * The file can contain '#' as comments.
- */
- private fun expandAtFiles(args: Array<String>): List<String> {
- val ret = mutableListOf<String>()
-
- args.forEach { arg ->
- if (!arg.startsWith('@')) {
- ret += arg
- return@forEach
- }
- // Read from the file, and add each line to the result.
- val filename = arg.substring(1).ensureFileExists()
-
- log.v("Expanding options file $filename")
-
- BufferedReader(FileReader(filename)).use { reader ->
- while (true) {
- var line = reader.readLine()
- if (line == null) {
- break // EOF
- }
-
- line = normalizeTextLine(line)
- if (line.isNotEmpty()) {
- ret += line
- }
- }
- }
- }
- return ret
- }
- }
-
- open class ArgumentsException(message: String?) : Exception(message), UserErrorException
-
- /** Thrown when the same annotation is used with different annotation arguments. */
- class DuplicateAnnotationException(annotationName: String?) :
- ArgumentsException("Duplicate annotation specified: '$annotationName'")
-
- /** Thrown when an input file does not exist. */
- class InputFileNotFoundException(filename: String) :
- ArgumentsException("File '$filename' not found")
-
- private class ArgIterator(
- private val args: List<String>,
- private var currentIndex: Int = -1
- ) {
- val current: String
- get() = args.get(currentIndex)
-
- /**
- * Get the next argument, or [null] if there's no more arguments.
- */
- fun nextArgOptional(): String? {
- if ((currentIndex + 1) >= args.size) {
- return null
- }
- return args.get(++currentIndex)
- }
-
- /**
- * Get the next argument, or throw if
- */
- fun nextArgRequired(argName: String): String {
- nextArgOptional().let {
- if (it == null) {
- throw ArgumentsException("Missing parameter for option $argName")
- }
- if (it.isEmpty()) {
- throw ArgumentsException("Parameter can't be empty for option $argName")
- }
- return it
- }
- }
}
override fun toString(): String {
@@ -415,3 +334,80 @@
""".trimIndent()
}
}
+
+class ArgIterator(
+ private val args: List<String>,
+ private var currentIndex: Int = -1
+) {
+ val current: String
+ get() = args.get(currentIndex)
+
+ /**
+ * Get the next argument, or [null] if there's no more arguments.
+ */
+ fun nextArgOptional(): String? {
+ if ((currentIndex + 1) >= args.size) {
+ return null
+ }
+ return args.get(++currentIndex)
+ }
+
+ /**
+ * Get the next argument, or throw if
+ */
+ fun nextArgRequired(argName: String): String {
+ nextArgOptional().let {
+ if (it == null) {
+ throw ArgumentsException("Missing parameter for option $argName")
+ }
+ if (it.isEmpty()) {
+ throw ArgumentsException("Parameter can't be empty for option $argName")
+ }
+ return it
+ }
+ }
+
+ companion object {
+ fun withAtFiles(args: Array<String>): ArgIterator {
+ return ArgIterator(expandAtFiles(args))
+ }
+ }
+}
+
+/**
+ * Scan the arguments, and if any of them starts with an `@`, then load from the file
+ * and use its content as arguments.
+ *
+ * In this file, each line is treated as a single argument.
+ *
+ * The file can contain '#' as comments.
+ */
+private fun expandAtFiles(args: Array<String>): List<String> {
+ val ret = mutableListOf<String>()
+
+ args.forEach { arg ->
+ if (!arg.startsWith('@')) {
+ ret += arg
+ return@forEach
+ }
+ // Read from the file, and add each line to the result.
+ val filename = arg.substring(1).ensureFileExists()
+
+ log.v("Expanding options file $filename")
+
+ BufferedReader(FileReader(filename)).use { reader ->
+ while (true) {
+ var line = reader.readLine()
+ if (line == null) {
+ break // EOF
+ }
+
+ line = normalizeTextLine(line)
+ if (line.isNotEmpty()) {
+ ret += line
+ }
+ }
+ }
+ }
+ return ret
+}
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/AsmUtils.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/AsmUtils.kt
index f219dac..6cf2143 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/AsmUtils.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/AsmUtils.kt
@@ -58,7 +58,24 @@
return null
}
-fun findAnnotationValueAsString(an: AnnotationNode, propertyName: String): String? {
+fun ClassNode.findAnyAnnotation(set: Set<String>): AnnotationNode? {
+ return findAnyAnnotation(set, this.visibleAnnotations, this.invisibleAnnotations)
+}
+
+fun MethodNode.findAnyAnnotation(set: Set<String>): AnnotationNode? {
+ return findAnyAnnotation(set, this.visibleAnnotations, this.invisibleAnnotations)
+}
+
+fun FieldNode.findAnyAnnotation(set: Set<String>): AnnotationNode? {
+ return findAnyAnnotation(set, this.visibleAnnotations, this.invisibleAnnotations)
+}
+
+fun <T> findAnnotationValueAsObject(
+ an: AnnotationNode,
+ propertyName: String,
+ expectedTypeHumanReadableName: String,
+ converter: (Any?) -> T?,
+): T? {
for (i in 0..(an.values?.size ?: 0) - 2 step 2) {
val name = an.values[i]
@@ -66,16 +83,30 @@
continue
}
val value = an.values[i + 1]
- if (value is String) {
- return value
+ if (value == null) {
+ return null
}
- throw ClassParseException(
- "The type of '$name' in annotation \"${an.desc}\" must be String" +
- ", but is ${value?.javaClass?.canonicalName}")
+
+ try {
+ return converter(value)
+ } catch (e: ClassCastException) {
+ throw ClassParseException(
+ "The type of '$propertyName' in annotation @${an.desc} must be " +
+ "$expectedTypeHumanReadableName, but is ${value?.javaClass?.canonicalName}")
+ }
}
return null
}
+fun findAnnotationValueAsString(an: AnnotationNode, propertyName: String): String? {
+ return findAnnotationValueAsObject(an, propertyName, "String", {it as String})
+}
+
+fun findAnnotationValueAsType(an: AnnotationNode, propertyName: String): Type? {
+ return findAnnotationValueAsObject(an, propertyName, "Class", {it as Type})
+}
+
+
val periodOrSlash = charArrayOf('.', '/')
fun getPackageNameFromFullClassName(fullClassName: String): String {
@@ -125,6 +156,24 @@
return Pair(name.substring(0, pos), name.substring(pos + 1))
}
+fun String.startsWithAny(vararg prefixes: String): Boolean {
+ prefixes.forEach {
+ if (this.startsWith(it)) {
+ return true
+ }
+ }
+ return false
+}
+
+fun String.endsWithAny(vararg suffixes: String): Boolean {
+ suffixes.forEach {
+ if (this.endsWith(it)) {
+ return true
+ }
+ }
+ return false
+}
+
fun String.toJvmClassName(): String {
return this.replace('.', '/')
}
@@ -137,6 +186,14 @@
return this.replace('/', '.')
}
+fun zipEntryNameToClassName(entryFilename: String): String? {
+ val suffix = ".class"
+ if (!entryFilename.endsWith(suffix)) {
+ return null
+ }
+ return entryFilename.substring(0, entryFilename.length - suffix.length)
+}
+
private val numericalInnerClassName = """.*\$\d+$""".toRegex()
fun isAnonymousInnerClass(cn: ClassNode): Boolean {
@@ -278,6 +335,14 @@
return (this.access and Opcodes.ACC_STATIC) != 0
}
+fun MethodNode.isPublic(): Boolean {
+ return (this.access and Opcodes.ACC_PUBLIC) != 0
+}
+
+fun MethodNode.isSpecial(): Boolean {
+ return CTOR_NAME == this.name || CLASS_INITIALIZER_NAME == this.name
+}
+
fun FieldNode.isEnum(): Boolean {
return (this.access and Opcodes.ACC_ENUM) != 0
}
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/ClassNodes.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/ClassNodes.kt
index 2607df6..e2647eb 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/ClassNodes.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/ClassNodes.kt
@@ -27,6 +27,11 @@
import java.io.BufferedInputStream
import java.io.PrintWriter
import java.util.Arrays
+import java.util.concurrent.Executors
+import java.util.concurrent.TimeUnit
+import java.util.concurrent.atomic.AtomicReference
+import java.util.function.Consumer
+import java.util.zip.ZipEntry
import java.util.zip.ZipFile
/**
@@ -183,10 +188,43 @@
/**
* Load all the classes, without code.
*/
- fun loadClassStructures(inJar: String): ClassNodes {
- log.iTime("Reading class structure from $inJar") {
- val allClasses = ClassNodes()
+ fun loadClassStructures(
+ inJar: String,
+ timeCollector: Consumer<Double>? = null,
+ ): ClassNodes {
+ val allClasses = ClassNodes()
+ // Load classes in parallel.
+ val executor = Executors.newFixedThreadPool(4)
+
+ // First exception defected.
+ val exception = AtomicReference<Throwable>()
+
+ // Called on a BG thread. Read a single jar entry and add it to [allClasses].
+ fun parseClass(inZip: ZipFile, entry: ZipEntry) {
+ try {
+ inZip.getInputStream(entry).use { ins ->
+ val cr = ClassReader(BufferedInputStream(ins))
+ val cn = ClassNode()
+ cr.accept(
+ cn, ClassReader.SKIP_CODE
+ or ClassReader.SKIP_DEBUG
+ or ClassReader.SKIP_FRAMES
+ )
+ synchronized(allClasses) {
+ if (!allClasses.addClass(cn)) {
+ log.w("Duplicate class found: ${cn.name}")
+ }
+ }
+ }
+ } catch (e: Throwable) {
+ log.e("Failed to load class: $e")
+ exception.compareAndSet(null, e)
+ }
+ }
+
+ // Actually open the jar and read it on worker threads.
+ val time = log.iTime("Reading class structure from $inJar") {
log.withIndent {
ZipFile(inJar).use { inZip ->
val inEntries = inZip.entries()
@@ -194,40 +232,42 @@
while (inEntries.hasMoreElements()) {
val entry = inEntries.nextElement()
- BufferedInputStream(inZip.getInputStream(entry)).use { bis ->
- if (entry.name.endsWith(".class")) {
- val cr = ClassReader(bis)
- val cn = ClassNode()
- cr.accept(
- cn, ClassReader.SKIP_CODE
- or ClassReader.SKIP_DEBUG
- or ClassReader.SKIP_FRAMES
- )
- if (!allClasses.addClass(cn)) {
- log.w("Duplicate class found: ${cn.name}")
- }
- } else if (entry.name.endsWith(".dex")) {
- // Seems like it's an ART jar file. We can't process it.
- // It's a fatal error.
- throw InvalidJarFileException(
- "$inJar is not a desktop jar file."
- + " It contains a *.dex file."
- )
- } else {
- // Unknown file type. Skip.
- while (bis.available() > 0) {
- bis.skip((1024 * 1024).toLong())
- }
+ if (entry.name.endsWith(".class")) {
+ executor.submit {
+ parseClass(inZip, entry)
}
+ } else if (entry.name.endsWith(".dex")) {
+ // Seems like it's an ART jar file. We can't process it.
+ // It's a fatal error.
+ throw InvalidJarFileException(
+ "$inJar is not a desktop jar file."
+ + " It contains a *.dex file."
+ )
+ } else {
+ // Unknown file type. Skip.
}
}
+ // Wait for all the work to complete. (must do it before closing the zip)
+ log.i("Waiting for all loaders to finish...")
+ executor.shutdown()
+ executor.awaitTermination(5, TimeUnit.MINUTES)
+ log.i("All loaders to finished.")
}
}
+
+ // If any exception is detected, throw it.
+ exception.get()?.let {
+ throw it
+ }
+
if (allClasses.size == 0) {
log.w("$inJar contains no *.class files.")
+ } else {
+ log.i("Loaded ${allClasses.size} classes from $inJar.")
}
- return allClasses
}
+ timeCollector?.accept(time)
+ return allClasses
}
}
}
\ No newline at end of file
diff --git a/tools/protologtool/src/com/android/protolog/tool/ProtoLogCallProcessorImpl.kt b/tools/protologtool/src/com/android/protolog/tool/ProtoLogCallProcessorImpl.kt
index 3c99e68..c3595b7 100644
--- a/tools/protologtool/src/com/android/protolog/tool/ProtoLogCallProcessorImpl.kt
+++ b/tools/protologtool/src/com/android/protolog/tool/ProtoLogCallProcessorImpl.kt
@@ -120,7 +120,7 @@
logCallVisitor?.processCall(call, messageString, getLevelForMethodName(
call.name.toString(), call, context), groupMap.getValue(groupName))
- } else if (call.name.id == "initialize") {
+ } else if (call.name.id == "init") {
// No processing
} else {
// Process non-log message calls