();
+}
+
diff --git a/core/java/android/hardware/contexthub/HubDiscoveryInfo.java b/core/java/android/hardware/contexthub/HubDiscoveryInfo.java
new file mode 100644
index 0000000000000000000000000000000000000000..581040dbfa5663a816acfa892e349abfe0d6a184
--- /dev/null
+++ b/core/java/android/hardware/contexthub/HubDiscoveryInfo.java
@@ -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 android.hardware.contexthub;
+
+import android.annotation.FlaggedApi;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.chre.flags.Flags;
+import android.hardware.location.ContextHubManager;
+
+/**
+ * Class that represents the result of from an hub endpoint discovery.
+ *
+ * The type is returned from an endpoint discovery query via {@link
+ * ContextHubManager#findEndpoints}.
+ *
+ *
Application may use the values {@link #getHubEndpointInfo} to retrieve the {@link
+ * HubEndpointInfo} that describes the endpoint that matches the query.
+ *
+ *
Application may use the values {@link #getHubServiceInfo()} to retrieve the {@link
+ * HubServiceInfo} that describes the service that matches the query.
+ *
+ * @hide
+ */
+@SystemApi
+@FlaggedApi(Flags.FLAG_OFFLOAD_API)
+public class HubDiscoveryInfo {
+ @NonNull private final HubEndpointInfo mEndpointInfo;
+ @Nullable private final HubServiceInfo mServiceInfo;
+
+ /** @hide */
+ public HubDiscoveryInfo(@NonNull HubEndpointInfo endpointInfo) {
+ mEndpointInfo = endpointInfo;
+ mServiceInfo = null;
+ }
+
+ /** @hide */
+ public HubDiscoveryInfo(
+ @NonNull HubEndpointInfo endpointInfo, @NonNull HubServiceInfo serviceInfo) {
+ mEndpointInfo = endpointInfo;
+ mServiceInfo = serviceInfo;
+ }
+
+ /** Get the {@link HubEndpointInfo} for the endpoint found. */
+ @NonNull
+ public HubEndpointInfo getHubEndpointInfo() {
+ return mEndpointInfo;
+ }
+
+ /**
+ * Get the {@link HubServiceInfo} for the endpoint found. The value will be null if there is no
+ * service info specified in the query.
+ */
+ @Nullable
+ public HubServiceInfo getHubServiceInfo() {
+ return mServiceInfo;
+ }
+}
diff --git a/core/java/android/hardware/contexthub/HubEndpoint.java b/core/java/android/hardware/contexthub/HubEndpoint.java
new file mode 100644
index 0000000000000000000000000000000000000000..078b4d4629e0ea441976283037c6813ed8446a50
--- /dev/null
+++ b/core/java/android/hardware/contexthub/HubEndpoint.java
@@ -0,0 +1,559 @@
+/*
+ * 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.hardware.contexthub;
+
+import android.annotation.CallbackExecutor;
+import android.annotation.FlaggedApi;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.chre.flags.Flags;
+import android.content.Context;
+import android.hardware.location.IContextHubService;
+import android.hardware.location.IContextHubTransactionCallback;
+import android.os.RemoteException;
+import android.util.Log;
+import android.util.SparseArray;
+
+import androidx.annotation.GuardedBy;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.Executor;
+
+/**
+ * An object representing an endpoint exposed to ContextHub and VendorHub. The object encapsulates
+ * the lifecycle and message callbacks for an endpoint.
+ *
+ * @hide
+ */
+@SystemApi
+@FlaggedApi(Flags.FLAG_OFFLOAD_API)
+public class HubEndpoint {
+ private static final String TAG = "HubEndpoint";
+
+ private final Object mLock = new Object();
+ private final HubEndpointInfo mPendingHubEndpointInfo;
+ @Nullable private final IHubEndpointLifecycleCallback mLifecycleCallback;
+ @Nullable private final IHubEndpointMessageCallback mMessageCallback;
+ @NonNull private final Executor mLifecycleCallbackExecutor;
+ @NonNull private final Executor mMessageCallbackExecutor;
+
+ @GuardedBy("mLock")
+ private final SparseArray mActiveSessions = new SparseArray<>();
+
+ private final IContextHubEndpointCallback mServiceCallback =
+ new IContextHubEndpointCallback.Stub() {
+ @Override
+ public void onSessionOpenRequest(
+ int sessionId,
+ HubEndpointInfo initiator,
+ @Nullable HubServiceInfo serviceInfo)
+ throws RemoteException {
+ HubEndpointSession activeSession;
+ synchronized (mLock) {
+ activeSession = mActiveSessions.get(sessionId);
+ // TODO(b/378974199): Consider refactor these assertions
+ if (activeSession != null) {
+ Log.i(
+ TAG,
+ "onSessionOpenComplete: session already exists, id="
+ + sessionId);
+ return;
+ }
+ }
+
+ if (mLifecycleCallback != null) {
+ mLifecycleCallbackExecutor.execute(
+ () ->
+ processSessionOpenRequestResult(
+ sessionId,
+ initiator,
+ serviceInfo,
+ mLifecycleCallback.onSessionOpenRequest(
+ initiator, serviceInfo)));
+ }
+ }
+
+ private void processSessionOpenRequestResult(
+ int sessionId,
+ HubEndpointInfo initiator,
+ @Nullable HubServiceInfo serviceInfo,
+ HubEndpointSessionResult result) {
+ if (result == null) {
+ throw new IllegalArgumentException(
+ "HubEndpointSessionResult shouldn't be null.");
+ }
+
+ if (result.isAccepted()) {
+ acceptSession(sessionId, initiator, serviceInfo);
+ } else {
+ Log.i(
+ TAG,
+ "Session "
+ + sessionId
+ + " from "
+ + initiator
+ + " was rejected, reason="
+ + result.getReason());
+ rejectSession(sessionId);
+ }
+ }
+
+ private void acceptSession(
+ int sessionId,
+ HubEndpointInfo initiator,
+ @Nullable HubServiceInfo serviceInfo) {
+ if (mServiceToken == null || mAssignedHubEndpointInfo == null) {
+ // No longer registered?
+ return;
+ }
+
+ // Retrieve the active session
+ HubEndpointSession activeSession;
+ synchronized (mLock) {
+ activeSession = mActiveSessions.get(sessionId);
+ // TODO(b/378974199): Consider refactor these assertions
+ if (activeSession != null) {
+ Log.e(
+ TAG,
+ "onSessionOpenRequestResult: session already exists, id="
+ + sessionId);
+ return;
+ }
+
+ activeSession =
+ new HubEndpointSession(
+ sessionId,
+ HubEndpoint.this,
+ mAssignedHubEndpointInfo,
+ initiator,
+ serviceInfo);
+ try {
+ // oneway call to notify system service that the request is completed
+ mServiceToken.openSessionRequestComplete(sessionId);
+ } catch (RemoteException e) {
+ Log.e(TAG, "onSessionOpenRequestResult: ", e);
+ return;
+ }
+
+ mActiveSessions.put(sessionId, activeSession);
+ }
+
+ // Execute the callback
+ activeSession.setOpened();
+ if (mLifecycleCallback != null) {
+ final HubEndpointSession finalActiveSession = activeSession;
+ mLifecycleCallbackExecutor.execute(
+ () -> mLifecycleCallback.onSessionOpened(finalActiveSession));
+ }
+ }
+
+ private void rejectSession(int sessionId) {
+ if (mServiceToken == null || mAssignedHubEndpointInfo == null) {
+ // No longer registered?
+ return;
+ }
+
+ try {
+ mServiceToken.closeSession(
+ sessionId,
+ IHubEndpointLifecycleCallback
+ .REASON_OPEN_ENDPOINT_SESSION_REQUEST_REJECTED);
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ }
+
+ @Override
+ public void onSessionOpenComplete(int sessionId) throws RemoteException {
+ final HubEndpointSession activeSession;
+
+ // Retrieve the active session
+ synchronized (mLock) {
+ activeSession = mActiveSessions.get(sessionId);
+ }
+ // TODO(b/378974199): Consider refactor these assertions
+ if (activeSession == null) {
+ Log.i(
+ TAG,
+ "onSessionOpenComplete: no pending session open request? id="
+ + sessionId);
+ return;
+ }
+
+ // Execute the callback
+ activeSession.setOpened();
+ if (mLifecycleCallback != null) {
+ mLifecycleCallbackExecutor.execute(
+ () -> mLifecycleCallback.onSessionOpened(activeSession));
+ }
+ }
+
+ @Override
+ public void onSessionClosed(int sessionId, int reason) throws RemoteException {
+ final HubEndpointSession activeSession;
+
+ // Retrieve the active session
+ synchronized (mLock) {
+ activeSession = mActiveSessions.get(sessionId);
+ }
+ // TODO(b/378974199): Consider refactor these assertions
+ if (activeSession == null) {
+ Log.i(TAG, "onSessionClosed: session not active, id=" + sessionId);
+ return;
+ }
+
+ // Execute the callback
+ if (mLifecycleCallback != null) {
+ mLifecycleCallbackExecutor.execute(
+ () -> {
+ mLifecycleCallback.onSessionClosed(activeSession, reason);
+
+ // Remove the session object first to call
+ activeSession.setClosed();
+ synchronized (mLock) {
+ mActiveSessions.remove(sessionId);
+ }
+ });
+ }
+ }
+
+ @Override
+ public void onMessageReceived(int sessionId, HubMessage message)
+ throws RemoteException {
+ final HubEndpointSession activeSession;
+
+ // Retrieve the active session
+ synchronized (mLock) {
+ activeSession = mActiveSessions.get(sessionId);
+ }
+ if (activeSession == null) {
+ Log.i(TAG, "onMessageReceived: session not active, id=" + sessionId);
+ }
+
+ if (activeSession == null || mMessageCallback == null) {
+ if (message.getDeliveryParams().isResponseRequired()) {
+ try {
+ mServiceToken.sendMessageDeliveryStatus(
+ sessionId,
+ message.getMessageSequenceNumber(),
+ ErrorCode.DESTINATION_NOT_FOUND);
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ }
+ return;
+ }
+
+ // Execute the callback
+ mMessageCallbackExecutor.execute(
+ () -> {
+ mMessageCallback.onMessageReceived(activeSession, message);
+ if (message.getDeliveryParams().isResponseRequired()) {
+ try {
+ mServiceToken.sendMessageDeliveryStatus(
+ sessionId,
+ message.getMessageSequenceNumber(),
+ ErrorCode.OK);
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ }
+ });
+ }
+ };
+
+ /** Binder returned from system service, non-null while registered. */
+ @Nullable private IContextHubEndpoint mServiceToken;
+
+ /** HubEndpointInfo with the assigned endpoint id from system service. */
+ @Nullable private HubEndpointInfo mAssignedHubEndpointInfo;
+
+ private HubEndpoint(
+ @NonNull HubEndpointInfo pendingEndpointInfo,
+ @Nullable IHubEndpointLifecycleCallback endpointLifecycleCallback,
+ @NonNull Executor lifecycleCallbackExecutor,
+ @Nullable IHubEndpointMessageCallback endpointMessageCallback,
+ @NonNull Executor messageCallbackExecutor) {
+ mPendingHubEndpointInfo = pendingEndpointInfo;
+
+ mLifecycleCallback = endpointLifecycleCallback;
+ mLifecycleCallbackExecutor = lifecycleCallbackExecutor;
+ mMessageCallback = endpointMessageCallback;
+ mMessageCallbackExecutor = messageCallbackExecutor;
+ }
+
+ /** @hide */
+ public void register(IContextHubService service) {
+ // TODO(b/378974199): Consider refactor these assertions
+ if (mServiceToken != null) {
+ // Already registered
+ return;
+ }
+ try {
+ IContextHubEndpoint serviceToken =
+ service.registerEndpoint(mPendingHubEndpointInfo, mServiceCallback);
+ mAssignedHubEndpointInfo = serviceToken.getAssignedHubEndpointInfo();
+ mServiceToken = serviceToken;
+ } catch (RemoteException e) {
+ Log.e(TAG, "registerEndpoint: failed to register endpoint", e);
+ e.rethrowFromSystemServer();
+ }
+ }
+
+ /** @hide */
+ public void unregister() {
+ IContextHubEndpoint serviceToken = mServiceToken;
+ // TODO(b/378974199): Consider refactor these assertions
+ if (serviceToken == null) {
+ // Not yet registered
+ return;
+ }
+
+ try {
+ synchronized (mLock) {
+ // Don't call HubEndpointSession.close() here.
+ for (int i = 0; i < mActiveSessions.size(); i++) {
+ mActiveSessions.get(mActiveSessions.keyAt(i)).setClosed();
+ }
+ mActiveSessions.clear();
+ }
+ mServiceToken.unregister();
+ } catch (RemoteException e) {
+ Log.e(TAG, "unregisterEndpoint: failed to unregister endpoint", e);
+ e.rethrowFromSystemServer();
+ } finally {
+ mServiceToken = null;
+ mAssignedHubEndpointInfo = null;
+ }
+ }
+
+ /** @hide */
+ public void openSession(HubEndpointInfo destinationInfo, @Nullable HubServiceInfo serviceInfo) {
+ // TODO(b/378974199): Consider refactor these assertions
+ if (mServiceToken == null || mAssignedHubEndpointInfo == null) {
+ // No longer registered?
+ return;
+ }
+
+ HubEndpointSession newSession;
+ try {
+ // Request system service to assign session id.
+ int sessionId = mServiceToken.openSession(destinationInfo, serviceInfo);
+
+ // Save the newly created session
+ synchronized (mLock) {
+ newSession =
+ new HubEndpointSession(
+ sessionId,
+ HubEndpoint.this,
+ destinationInfo,
+ mAssignedHubEndpointInfo,
+ serviceInfo);
+ mActiveSessions.put(sessionId, newSession);
+ }
+ } catch (RemoteException e) {
+ // Move this to toString
+ Log.e(TAG, "openSession: failed to open session to " + destinationInfo, e);
+ e.rethrowFromSystemServer();
+ }
+ }
+
+ /** @hide */
+ public void closeSession(HubEndpointSession session) {
+ IContextHubEndpoint serviceToken = mServiceToken;
+ // TODO(b/378974199): Consider refactor these assertions
+ if (serviceToken == null || mAssignedHubEndpointInfo == null) {
+ // Not registered
+ return;
+ }
+
+ synchronized (mLock) {
+ if (!mActiveSessions.contains(session.getId())) {
+ // Already closed?
+ return;
+ }
+ session.setClosed();
+ mActiveSessions.remove(session.getId());
+ }
+
+ try {
+ // Oneway notification to system service
+ serviceToken.closeSession(
+ session.getId(),
+ IHubEndpointLifecycleCallback.REASON_CLOSE_ENDPOINT_SESSION_REQUESTED);
+ } catch (RemoteException e) {
+ Log.e(TAG, "closeSession: failed to close session " + session, e);
+ e.rethrowFromSystemServer();
+ }
+ }
+
+ void sendMessage(
+ HubEndpointSession session,
+ HubMessage message,
+ @Nullable IContextHubTransactionCallback transactionCallback) {
+ IContextHubEndpoint serviceToken = mServiceToken;
+ if (serviceToken == null) {
+ // Not registered
+ return;
+ }
+
+ try {
+ serviceToken.sendMessage(session.getId(), message, transactionCallback);
+ } catch (RemoteException e) {
+ Log.e(TAG, "sendMessage: failed to send message session=" + session, e);
+ e.rethrowFromSystemServer();
+ }
+ }
+
+ public int getVersion() {
+ return mPendingHubEndpointInfo.getVersion();
+ }
+
+ @Nullable
+ public String getTag() {
+ return mPendingHubEndpointInfo.getTag();
+ }
+
+ @NonNull
+ public Collection getServiceInfoCollection() {
+ return mPendingHubEndpointInfo.getServiceInfoCollection();
+ }
+
+ @Nullable
+ public IHubEndpointLifecycleCallback getLifecycleCallback() {
+ return mLifecycleCallback;
+ }
+
+ @Nullable
+ public IHubEndpointMessageCallback getMessageCallback() {
+ return mMessageCallback;
+ }
+
+ /** Builder for a {@link HubEndpoint} object. */
+ public static final class Builder {
+ private final String mPackageName;
+
+ @Nullable private IHubEndpointLifecycleCallback mLifecycleCallback;
+
+ @NonNull private Executor mLifecycleCallbackExecutor;
+
+ @Nullable private IHubEndpointMessageCallback mMessageCallback;
+ @NonNull private Executor mMessageCallbackExecutor;
+
+ private int mVersion;
+ @Nullable private String mTag;
+
+ private List mServiceInfos = Collections.emptyList();
+
+ /** Create a builder for {@link HubEndpoint} */
+ public Builder(@NonNull Context context) {
+ mPackageName = context.getPackageName();
+ mVersion = (int) context.getApplicationInfo().longVersionCode;
+ mLifecycleCallbackExecutor = context.getMainExecutor();
+ mMessageCallbackExecutor = context.getMainExecutor();
+ }
+
+ /**
+ * Set the version for the endpoint. Default is 0.
+ *
+ * @hide
+ */
+ @NonNull
+ public Builder setVersion(int version) {
+ mVersion = version;
+ return this;
+ }
+
+ /**
+ * Set a tag string. The tag can be used to further identify the creator of the endpoint.
+ * Endpoints created by the same package share the same name but should have different tags.
+ */
+ @NonNull
+ public Builder setTag(@NonNull String tag) {
+ mTag = tag;
+ return this;
+ }
+
+ /** Attach a callback interface for lifecycle events for this Endpoint */
+ @NonNull
+ public Builder setLifecycleCallback(
+ @NonNull IHubEndpointLifecycleCallback lifecycleCallback) {
+ mLifecycleCallback = lifecycleCallback;
+ return this;
+ }
+
+ /**
+ * Attach a callback interface for lifecycle events for this Endpoint with a specified
+ * executor
+ */
+ @NonNull
+ public Builder setLifecycleCallback(
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull IHubEndpointLifecycleCallback lifecycleCallback) {
+ mLifecycleCallbackExecutor = executor;
+ mLifecycleCallback = lifecycleCallback;
+ return this;
+ }
+
+ /** Attach a callback interface for message events for this Endpoint */
+ @NonNull
+ public Builder setMessageCallback(@NonNull IHubEndpointMessageCallback messageCallback) {
+ mMessageCallback = messageCallback;
+ return this;
+ }
+
+ /**
+ * Attach a callback interface for message events for this Endpoint with a specified
+ * executor
+ */
+ @NonNull
+ public Builder setMessageCallback(
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull IHubEndpointMessageCallback messageCallback) {
+ mMessageCallbackExecutor = executor;
+ mMessageCallback = messageCallback;
+ return this;
+ }
+
+ /**
+ * Add a service to the available services from this endpoint. The {@link HubServiceInfo}
+ * object can be built with {@link HubServiceInfo.Builder}.
+ */
+ @NonNull
+ public Builder setServiceInfoCollection(
+ @NonNull Collection hubServiceInfos) {
+ // Make a copy first
+ mServiceInfos = new ArrayList<>(hubServiceInfos);
+ return this;
+ }
+
+ /** Build the {@link HubEndpoint} object. */
+ @NonNull
+ public HubEndpoint build() {
+ return new HubEndpoint(
+ new HubEndpointInfo(mPackageName, mVersion, mTag, mServiceInfos),
+ mLifecycleCallback,
+ mLifecycleCallbackExecutor,
+ mMessageCallback,
+ mMessageCallbackExecutor);
+ }
+ }
+}
diff --git a/core/java/android/hardware/contexthub/HubEndpointInfo.aidl b/core/java/android/hardware/contexthub/HubEndpointInfo.aidl
new file mode 100644
index 0000000000000000000000000000000000000000..025b2b1f685a3904a75e266a75952bbdba6db976
--- /dev/null
+++ b/core/java/android/hardware/contexthub/HubEndpointInfo.aidl
@@ -0,0 +1,20 @@
+/*
+ * 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.hardware.contexthub;
+
+/** @hide */
+parcelable HubEndpointInfo;
diff --git a/core/java/android/hardware/contexthub/HubEndpointInfo.java b/core/java/android/hardware/contexthub/HubEndpointInfo.java
new file mode 100644
index 0000000000000000000000000000000000000000..b1d55239ac438d0d2e389e12da7e7fda7b44fea3
--- /dev/null
+++ b/core/java/android/hardware/contexthub/HubEndpointInfo.java
@@ -0,0 +1,330 @@
+/*
+ * 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.hardware.contexthub;
+
+import android.annotation.FlaggedApi;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SuppressLint;
+import android.annotation.SystemApi;
+import android.chre.flags.Flags;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Parcelable representing an endpoint from ContextHub or VendorHub.
+ *
+ * HubEndpointInfo contains information about an endpoint, including its name, tag and other
+ * information. A HubEndpointInfo object can be used to accurately identify a specific endpoint.
+ * Application can use this object to identify and describe an endpoint.
+ *
+ *
See: {@link android.hardware.location.ContextHubManager#findEndpoints} for how to retrieve
+ * {@link HubEndpointInfo} for endpoints on a hub.
+ *
+ * @hide
+ */
+@SystemApi
+@FlaggedApi(Flags.FLAG_OFFLOAD_API)
+public final class HubEndpointInfo implements Parcelable {
+ /**
+ * A unique identifier for one endpoint. A unique identifier for one endpoint consists of two
+ * parts: (1) a unique long number for a hub and (2) a long number for the endpoint, unique
+ * within a hub. This class overrides equality methods and can be used to compare if two
+ * endpoints are the same.
+ */
+ public static class HubEndpointIdentifier {
+ private final long mEndpointId;
+ private final long mHubId;
+
+ /** @hide */
+ public HubEndpointIdentifier(long hubId, long endpointId) {
+ mEndpointId = endpointId;
+ mHubId = hubId;
+ }
+
+ /** @hide */
+ public HubEndpointIdentifier(android.hardware.contexthub.EndpointId halEndpointId) {
+ mEndpointId = halEndpointId.id;
+ mHubId = halEndpointId.hubId;
+ }
+
+ /** Get the endpoint portion of the identifier. */
+ public long getEndpoint() {
+ return mEndpointId;
+ }
+
+ /** Get the hub portion of the identifier. */
+ public long getHub() {
+ return mHubId;
+ }
+
+ /**
+ * Create an invalid endpoint id, to represent endpoint that are not yet registered with the
+ * HAL.
+ *
+ * @hide
+ */
+ public static HubEndpointIdentifier invalid() {
+ return new HubEndpointIdentifier(
+ android.hardware.contexthub.HubInfo.HUB_ID_INVALID,
+ android.hardware.contexthub.EndpointId.ENDPOINT_ID_INVALID);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mEndpointId, mHubId);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof HubEndpointIdentifier other)) {
+ return false;
+ }
+ if (other.mHubId != mHubId) {
+ return false;
+ }
+ return other.mEndpointId == mEndpointId;
+ }
+ }
+
+ /** This endpoint is from the Android framework */
+ public static final int TYPE_FRAMEWORK = 1;
+
+ /** This endpoint is from an Android app */
+ public static final int TYPE_APP = 2;
+
+ /** This endpoint is from an Android native program. */
+ public static final int TYPE_NATIVE = 3;
+
+ /** This endpoint is from a nanoapp. */
+ public static final int TYPE_NANOAPP = 4;
+
+ /** This endpoint is a generic endpoint served by a hub (not from a nanoapp). */
+ public static final int TYPE_HUB_ENDPOINT = 5;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({
+ TYPE_FRAMEWORK,
+ TYPE_APP,
+ TYPE_NATIVE,
+ TYPE_NANOAPP,
+ TYPE_HUB_ENDPOINT,
+ })
+ public @interface EndpointType {}
+
+ private final HubEndpointIdentifier mId;
+ @EndpointType private final int mType;
+ private final String mName;
+ private final int mVersion;
+ @Nullable private final String mTag;
+
+ @NonNull private final List mRequiredPermissions;
+ @NonNull private final List mHubServiceInfos;
+
+ /** @hide */
+ public HubEndpointInfo(android.hardware.contexthub.EndpointInfo endpointInfo) {
+ mId = new HubEndpointIdentifier(endpointInfo.id.hubId, endpointInfo.id.id);
+ mType = endpointInfo.type;
+ mName = endpointInfo.name;
+ mVersion = endpointInfo.version;
+ mTag = endpointInfo.tag;
+ mRequiredPermissions = Arrays.asList(endpointInfo.requiredPermissions);
+ mHubServiceInfos = new ArrayList<>(endpointInfo.services.length);
+ for (int i = 0; i < endpointInfo.services.length; i++) {
+ mHubServiceInfos.set(i, new HubServiceInfo(endpointInfo.services[i]));
+ }
+ }
+
+ /** @hide */
+ public HubEndpointInfo(
+ String name,
+ int version,
+ @Nullable String tag,
+ @NonNull List hubServiceInfos) {
+ mId = HubEndpointIdentifier.invalid();
+ mType = TYPE_APP;
+ mName = name;
+ mVersion = version;
+ mTag = tag;
+ mRequiredPermissions = Collections.emptyList();
+ mHubServiceInfos = hubServiceInfos;
+ }
+
+ private HubEndpointInfo(Parcel in) {
+ long hubId = in.readLong();
+ long endpointId = in.readLong();
+ mId = new HubEndpointIdentifier(hubId, endpointId);
+ mType = in.readInt();
+ mName = in.readString();
+ mVersion = in.readInt();
+ mTag = in.readString();
+ mRequiredPermissions = new ArrayList<>();
+ in.readStringList(mRequiredPermissions);
+ mHubServiceInfos = new ArrayList<>();
+ in.readTypedList(mHubServiceInfos, HubServiceInfo.CREATOR);
+ }
+
+ /** Parcel implementation details */
+ @Override
+ public int describeContents() {
+ int flags = 0;
+ for (HubServiceInfo serviceInfo : mHubServiceInfos) {
+ flags |= serviceInfo.describeContents();
+ }
+ return flags;
+ }
+
+ /** Parcel implementation details */
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeLong(mId.getHub());
+ dest.writeLong(mId.getEndpoint());
+ dest.writeInt(mType);
+ dest.writeString(mName);
+ dest.writeInt(mVersion);
+ dest.writeString(mTag);
+ dest.writeStringList(mRequiredPermissions);
+ dest.writeTypedList(mHubServiceInfos, flags);
+ }
+
+ /** Get a unique identifier for this endpoint. */
+ @NonNull
+ public HubEndpointIdentifier getIdentifier() {
+ return mId;
+ }
+
+ /**
+ * Get the type of this endpoint. Application may use this field to get more information about
+ * who registered this endpoint for diagnostic purposes.
+ *
+ * Type can be one of {@link HubEndpointInfo#TYPE_APP}, {@link
+ * HubEndpointInfo#TYPE_FRAMEWORK}, {@link HubEndpointInfo#TYPE_NANOAPP}, {@link
+ * HubEndpointInfo#TYPE_NATIVE} or {@link HubEndpointInfo#TYPE_HUB_ENDPOINT}.
+ */
+ public int getType() {
+ return mType;
+ }
+
+ /** Get the human-readable name of this endpoint (for debugging purposes). */
+ @NonNull
+ public String getName() {
+ return mName;
+ }
+
+ /**
+ * Get the version of this endpoint.
+ *
+ *
Monotonically increasing version number. The two sides of an endpoint session can use this
+ * version number to identify the other side and determine compatibility with each other. The
+ * interpretation of the version number is specific to the implementation of an endpoint.
+ *
+ *
The version number should not be used to compare endpoints implementation freshness for
+ * different endpoint types.
+ *
+ *
Depending on type of the endpoint, the following values (and formats) are used:
+ *
+ *
+ * - {@link #TYPE_FRAMEWORK}: android.os.Build.VERSION.SDK_INT_FULL
+ *
- {@link #TYPE_APP}: versionCode
+ *
- {@link #TYPE_NATIVE}: unspecified format (supplied by endpoint code)
+ *
- {@link #TYPE_NANOAPP}: nanoapp version, typically following 0xMMmmpppp scheme where MM
+ * = major version, mm = minor version, pppp = patch version
+ *
- {@link #TYPE_HUB_ENDPOINT}: unspecified format (supplied by endpoint code), following
+ * nanoapp versioning scheme is recommended
+ *
+ */
+ public int getVersion() {
+ return mVersion;
+ }
+
+ /**
+ * Get the tag that further identifies the submodule that created this endpoint. For example, a
+ * single application could provide multiple endpoints. These endpoints will share the same
+ * name, but will have different tags. This tag can be used to identify the submodule within the
+ * application that provided the endpoint.
+ */
+ @Nullable
+ public String getTag() {
+ return mTag;
+ }
+
+ /**
+ * Get the list of required permissions in order to talk to this endpoint.
+ *
+ * This list is enforced by the Context Hub Service. The app would need to have the required
+ * permissions list to open a session with this particular endpoint. Otherwise this will be
+ * rejected by as permission failures.
+ *
+ *
This is mostly for allowing app to check what permission it needs first internally. App
+ * will need to request permissions grant at runtime if not already granted. See {@link
+ * android.content.Context#checkPermission} for more details.
+ *
+ *
See {@link android.Manifest.permission} for a list of standard Android permissions as
+ * possible values.
+ */
+ @SuppressLint("RequiresPermission")
+ @NonNull
+ public Collection getRequiredPermissions() {
+ return Collections.unmodifiableList(mRequiredPermissions);
+ }
+
+ /**
+ * Get the list of services provided by this endpoint.
+ *
+ * See {@link HubServiceInfo} for more information.
+ */
+ @NonNull
+ public Collection getServiceInfoCollection() {
+ return Collections.unmodifiableList(mHubServiceInfos);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder out = new StringBuilder();
+ out.append("Endpoint [0x");
+ out.append(Long.toHexString(mId.getEndpoint()));
+ out.append("@ Hub 0x");
+ out.append(Long.toHexString(mId.getHub()));
+ out.append("] Name=");
+ out.append(mName);
+ out.append(", Tag=");
+ out.append(mTag);
+ return out.toString();
+ }
+
+ public static final @android.annotation.NonNull Creator CREATOR =
+ new Creator<>() {
+ public HubEndpointInfo createFromParcel(Parcel in) {
+ return new HubEndpointInfo(in);
+ }
+
+ public HubEndpointInfo[] newArray(int size) {
+ return new HubEndpointInfo[size];
+ }
+ };
+}
diff --git a/core/java/android/hardware/contexthub/HubEndpointSession.java b/core/java/android/hardware/contexthub/HubEndpointSession.java
new file mode 100644
index 0000000000000000000000000000000000000000..cf952cbdbfdc54864b9d9c8d18ad9696391ade16
--- /dev/null
+++ b/core/java/android/hardware/contexthub/HubEndpointSession.java
@@ -0,0 +1,170 @@
+/*
+ * 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.hardware.contexthub;
+
+import android.annotation.FlaggedApi;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.chre.flags.Flags;
+import android.hardware.location.ContextHubTransaction;
+import android.hardware.location.ContextHubTransactionHelper;
+import android.hardware.location.IContextHubTransactionCallback;
+import android.util.CloseGuard;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * An object representing a communication session between two different hub endpoints.
+ *
+ * @hide
+ */
+@SystemApi
+@FlaggedApi(Flags.FLAG_OFFLOAD_API)
+public class HubEndpointSession implements AutoCloseable {
+ private final CloseGuard mCloseGuard = new CloseGuard();
+
+ private final int mId;
+
+ @NonNull private final HubEndpoint mHubEndpoint;
+ @NonNull private final HubEndpointInfo mInitiator;
+ @NonNull private final HubEndpointInfo mDestination;
+ @Nullable private final HubServiceInfo mServiceInfo;
+
+ private final AtomicBoolean mIsClosed = new AtomicBoolean(true);
+
+ /** @hide */
+ HubEndpointSession(
+ int id,
+ @NonNull HubEndpoint hubEndpoint,
+ @NonNull HubEndpointInfo destination,
+ @NonNull HubEndpointInfo initiator,
+ @Nullable HubServiceInfo serviceInfo) {
+ mId = id;
+ mHubEndpoint = hubEndpoint;
+ mDestination = destination;
+ mInitiator = initiator;
+ mServiceInfo = serviceInfo;
+ }
+
+ /**
+ * Send a message to the peer endpoint in this session.
+ *
+ * @param message The message object constructed with {@link HubMessage#createMessage}.
+ * @return For messages that does not require a response, the transaction will immediately
+ * complete. For messages that requires a response, the transaction will complete after
+ * receiving the response for the message.
+ */
+ @NonNull
+ public ContextHubTransaction sendMessage(@NonNull HubMessage message) {
+ if (mIsClosed.get()) {
+ throw new IllegalStateException("Session is already closed.");
+ }
+
+ boolean isResponseRequired = message.getDeliveryParams().isResponseRequired();
+ ContextHubTransaction ret =
+ new ContextHubTransaction<>(
+ isResponseRequired
+ ? ContextHubTransaction.TYPE_HUB_MESSAGE_REQUIRES_RESPONSE
+ : ContextHubTransaction.TYPE_HUB_MESSAGE_DEFAULT);
+ if (!isResponseRequired) {
+ // If the message doesn't require acknowledgement, respond with success immediately
+ // TODO(b/379162322): Improve handling of synchronous failures.
+ mHubEndpoint.sendMessage(this, message, null);
+ ret.setResponse(
+ new ContextHubTransaction.Response<>(
+ ContextHubTransaction.RESULT_SUCCESS, null));
+ } else {
+ IContextHubTransactionCallback callback =
+ ContextHubTransactionHelper.createTransactionCallback(ret);
+ // Sequence number will be assigned at the service
+ mHubEndpoint.sendMessage(this, message, callback);
+ }
+ return ret;
+ }
+
+ /** @hide */
+ public int getId() {
+ return mId;
+ }
+
+ /** @hide */
+ public void setOpened() {
+ mIsClosed.set(false);
+ mCloseGuard.open("close");
+ }
+
+ /** @hide */
+ public void setClosed() {
+ mIsClosed.set(true);
+ mCloseGuard.close();
+ }
+
+ /**
+ * Closes the connection for this session between an endpoint and the Context Hub Service.
+ *
+ * When this function is invoked, the messaging associated with this session is invalidated.
+ * All futures messages targeted for this client are dropped.
+ */
+ public void close() {
+ if (!mIsClosed.getAndSet(true)) {
+ mCloseGuard.close();
+ mHubEndpoint.closeSession(this);
+ }
+ }
+
+ /**
+ * Get the {@link HubServiceInfo} associated with this session. Null value indicates that there
+ * is no service associated to this session.
+ *
+ *
For hub initiated sessions, the object was previously used in as an argument for open
+ * request in {@link IHubEndpointLifecycleCallback#onSessionOpenRequest}.
+ *
+ *
For app initiated sessions, the object was previously used in an open request in {@link
+ * android.hardware.location.ContextHubManager#openSession}
+ */
+ @Nullable
+ public HubServiceInfo getServiceInfo() {
+ return mServiceInfo;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder stringBuilder = new StringBuilder();
+ stringBuilder.append("Session [");
+ stringBuilder.append(mId);
+ stringBuilder.append("]: [");
+ stringBuilder.append(mInitiator);
+ stringBuilder.append("]->[");
+ stringBuilder.append(mDestination);
+ stringBuilder.append("]");
+ return stringBuilder.toString();
+ }
+
+ /** @hide */
+ protected void finalize() throws Throwable {
+ try {
+ // Note that guard could be null if the constructor threw.
+ if (mCloseGuard != null) {
+ mCloseGuard.warnIfOpen();
+ }
+ close();
+ } finally {
+ super.finalize();
+ }
+ }
+}
diff --git a/core/java/android/hardware/contexthub/HubEndpointSessionResult.java b/core/java/android/hardware/contexthub/HubEndpointSessionResult.java
new file mode 100644
index 0000000000000000000000000000000000000000..1f2bdb9850087ead2dc37c497a696a255379d5ca
--- /dev/null
+++ b/core/java/android/hardware/contexthub/HubEndpointSessionResult.java
@@ -0,0 +1,79 @@
+/*
+ * 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.hardware.contexthub;
+
+import android.annotation.FlaggedApi;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.chre.flags.Flags;
+
+/**
+ * Return type of {@link IHubEndpointLifecycleCallback#onSessionOpenRequest}. The value determines
+ * whether a open session request from the remote is accepted or not.
+ *
+ * @hide
+ */
+@SystemApi
+@FlaggedApi(Flags.FLAG_OFFLOAD_API)
+public class HubEndpointSessionResult {
+ private final boolean mAccepted;
+
+ @Nullable private final String mReason;
+
+ private HubEndpointSessionResult(boolean accepted, @Nullable String reason) {
+ mAccepted = accepted;
+ mReason = reason;
+ }
+
+ /**
+ * Retrieve the decision of the session request.
+ *
+ * @return Whether a session request was accepted or not, previously set with {@link #accept()}
+ * or {@link #reject(String)}.
+ */
+ public boolean isAccepted() {
+ return mAccepted;
+ }
+
+ /**
+ * Retrieve the decision of the session request.
+ *
+ * @return The reason previously set in {@link #reject(String)}. If the result was {@link
+ * #accept()}, the reason will be null.
+ */
+ @Nullable
+ public String getReason() {
+ return mReason;
+ }
+
+ /** Accept the request. */
+ @NonNull
+ public static HubEndpointSessionResult accept() {
+ return new HubEndpointSessionResult(true, null);
+ }
+
+ /**
+ * Reject the request with a reason.
+ *
+ * @param reason Reason why the request was rejected, for diagnostic purposes.
+ */
+ @NonNull
+ public static HubEndpointSessionResult reject(@NonNull String reason) {
+ return new HubEndpointSessionResult(false, reason);
+ }
+}
diff --git a/core/java/android/hardware/contexthub/HubMessage.aidl b/core/java/android/hardware/contexthub/HubMessage.aidl
new file mode 100644
index 0000000000000000000000000000000000000000..86afce2330623981444846e6322ad0ec224819fa
--- /dev/null
+++ b/core/java/android/hardware/contexthub/HubMessage.aidl
@@ -0,0 +1,22 @@
+/*
+ * Copyright 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.hardware.contexthub;
+
+/**
+ * @hide
+ */
+parcelable HubMessage;
diff --git a/core/java/android/hardware/contexthub/HubMessage.java b/core/java/android/hardware/contexthub/HubMessage.java
new file mode 100644
index 0000000000000000000000000000000000000000..dc8a8c52ea5596cbae49353a3277273781d4d572
--- /dev/null
+++ b/core/java/android/hardware/contexthub/HubMessage.java
@@ -0,0 +1,289 @@
+/*
+ * Copyright 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.hardware.contexthub;
+
+import android.annotation.FlaggedApi;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.chre.flags.Flags;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import libcore.util.HexEncoding;
+
+import java.util.Arrays;
+import java.util.Objects;
+
+/**
+ * A class describing general messages send through the Context Hub Service.
+ *
+ * @hide
+ */
+@SystemApi
+@FlaggedApi(Flags.FLAG_OFFLOAD_API)
+public final class HubMessage implements Parcelable {
+ private static final int DEBUG_LOG_NUM_BYTES = 16;
+
+ private final int mMessageType;
+ private final byte[] mMessageBody;
+
+ private final DeliveryParams mDeliveryParams;
+ private int mMessageSequenceNumber;
+
+ /**
+ * Configurable options for message delivery. This option can be passed into {@link
+ * HubEndpointSession#sendMessage} to specify the behavior of message delivery.
+ */
+ public static class DeliveryParams {
+ private boolean mResponseRequired;
+
+ private DeliveryParams(boolean responseRequired) {
+ mResponseRequired = responseRequired;
+ }
+
+ /** Get the acknowledgement requirement. */
+ public boolean isResponseRequired() {
+ return mResponseRequired;
+ }
+
+ /**
+ * Set the response requirement for a message. Message sent with this option will have a
+ * {@link android.hardware.location.ContextHubTransaction.Response} when the peer received
+ * the message. Default is false.
+ */
+ @NonNull
+ public DeliveryParams setResponseRequired(boolean required) {
+ mResponseRequired = required;
+ return this;
+ }
+
+ /** Construct a default delivery option. */
+ @NonNull
+ public static DeliveryParams makeBasic() {
+ return new DeliveryParams(false);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder out = new StringBuilder();
+ out.append("DeliveryParams[");
+ out.append("responseRequired = ").append(mResponseRequired);
+ out.append("]");
+ return out.toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mResponseRequired);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+
+ if (obj instanceof DeliveryParams other) {
+ return other.mResponseRequired == mResponseRequired;
+ }
+
+ return false;
+ }
+ }
+
+ private HubMessage(int messageType, byte[] messageBody, DeliveryParams deliveryParams) {
+ mMessageType = messageType;
+ mMessageBody = messageBody;
+ mDeliveryParams = deliveryParams;
+ }
+
+ /**
+ * Creates a HubMessage object to send to through an endpoint.
+ *
+ * @param messageType the endpoint & service dependent message type
+ * @param messageBody the byte array message contents
+ * @return the HubMessage object
+ */
+ @NonNull
+ public static HubMessage createMessage(int messageType, @NonNull byte[] messageBody) {
+ return new HubMessage(messageType, messageBody, DeliveryParams.makeBasic());
+ }
+
+ /**
+ * Creates a HubMessage object to send to through an endpoint.
+ *
+ * @param messageType the endpoint & service dependent message type
+ * @param messageBody the byte array message contents
+ * @param deliveryParams The message delivery parameters. See {@link HubMessage.DeliveryParams}
+ * for more details.
+ * @return the HubMessage object
+ */
+ @NonNull
+ public static HubMessage createMessage(
+ int messageType, @NonNull byte[] messageBody, @NonNull DeliveryParams deliveryParams) {
+ return new HubMessage(messageType, messageBody, deliveryParams);
+ }
+
+ /**
+ * Retrieve the message type.
+ *
+ * @return the type of the message
+ */
+ public int getMessageType() {
+ return mMessageType;
+ }
+
+ /**
+ * Retrieve the body of the message. The body can be an empty byte array.
+ *
+ * @return the byte array contents of the message
+ */
+ @NonNull
+ public byte[] getMessageBody() {
+ return mMessageBody;
+ }
+
+ /**
+ * Retrieve the {@link DeliveryParams} object specifying the behavior of message delivery.
+ *
+ * @hide
+ */
+ public DeliveryParams getDeliveryParams() {
+ return mDeliveryParams;
+ }
+
+ /**
+ * Assign a message sequence number. This should only be called by the system service.
+ *
+ * @hide
+ */
+ public void setMessageSequenceNumber(int messageSequenceNumber) {
+ mMessageSequenceNumber = messageSequenceNumber;
+ }
+
+ /**
+ * Returns the message sequence number. The default value is 0.
+ *
+ * @return the message sequence number of the message
+ * @hide
+ */
+ public int getMessageSequenceNumber() {
+ return mMessageSequenceNumber;
+ }
+
+ private HubMessage(@NonNull Parcel in) {
+ mMessageType = in.readInt();
+
+ int msgSize = in.readInt();
+ mMessageBody = new byte[msgSize];
+ in.readByteArray(mMessageBody);
+
+ mDeliveryParams = DeliveryParams.makeBasic();
+ mDeliveryParams.setResponseRequired(in.readInt() == 1);
+ mMessageSequenceNumber = in.readInt();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel out, int flags) {
+ out.writeInt(mMessageType);
+
+ out.writeInt(mMessageBody.length);
+ out.writeByteArray(mMessageBody);
+
+ out.writeInt(mDeliveryParams.isResponseRequired() ? 1 : 0);
+ out.writeInt(mMessageSequenceNumber);
+ }
+
+ public static final @NonNull Creator CREATOR =
+ new Creator<>() {
+ @Override
+ public HubMessage createFromParcel(Parcel in) {
+ return new HubMessage(in);
+ }
+
+ @Override
+ public HubMessage[] newArray(int size) {
+ return new HubMessage[size];
+ }
+ };
+
+ @NonNull
+ @Override
+ public String toString() {
+ int length = mMessageBody.length;
+
+ StringBuilder out = new StringBuilder();
+ out.append("HubMessage[type = ").append(mMessageType);
+ out.append(", length = ").append(mMessageBody.length);
+ out.append(", messageSequenceNumber = ").append(mMessageSequenceNumber);
+ out.append(", deliveryParams = ").append(mDeliveryParams);
+ out.append("](");
+
+ if (length > 0) {
+ out.append("data = 0x");
+ }
+ for (int i = 0; i < Math.min(length, DEBUG_LOG_NUM_BYTES); i++) {
+ out.append(HexEncoding.encodeToString(mMessageBody[i], true /* upperCase */));
+
+ if ((i + 1) % 4 == 0) {
+ out.append(" ");
+ }
+ }
+ if (length > DEBUG_LOG_NUM_BYTES) {
+ out.append("...");
+ }
+ out.append(")");
+
+ return out.toString();
+ }
+
+ @Override
+ public boolean equals(@Nullable Object object) {
+ if (object == this) {
+ return true;
+ }
+
+ boolean isEqual = false;
+ if (object instanceof HubMessage other) {
+ isEqual =
+ (other.getMessageType() == mMessageType)
+ && Arrays.equals(other.getMessageBody(), mMessageBody)
+ && (other.getDeliveryParams().equals(mDeliveryParams))
+ && (other.getMessageSequenceNumber() == mMessageSequenceNumber);
+ }
+
+ return isEqual;
+ }
+
+ @Override
+ public int hashCode() {
+ if (!Flags.fixApiCheck()) {
+ return super.hashCode();
+ }
+
+ return Objects.hash(
+ mMessageType,
+ Arrays.hashCode(mMessageBody),
+ mDeliveryParams,
+ mMessageSequenceNumber);
+ }
+}
diff --git a/core/java/android/hardware/contexthub/HubServiceInfo.aidl b/core/java/android/hardware/contexthub/HubServiceInfo.aidl
new file mode 100644
index 0000000000000000000000000000000000000000..98b1bbab8b60dceb1aeabc5b7efcdc62dc52516b
--- /dev/null
+++ b/core/java/android/hardware/contexthub/HubServiceInfo.aidl
@@ -0,0 +1,22 @@
+/*
+ * Copyright 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.hardware.contexthub;
+
+/**
+ * @hide
+ */
+parcelable HubServiceInfo;
diff --git a/core/java/android/hardware/contexthub/HubServiceInfo.java b/core/java/android/hardware/contexthub/HubServiceInfo.java
new file mode 100644
index 0000000000000000000000000000000000000000..c7fe77c4a0f1589aeab1dda96e0d4bc02d71ed95
--- /dev/null
+++ b/core/java/android/hardware/contexthub/HubServiceInfo.java
@@ -0,0 +1,263 @@
+/*
+ * Copyright 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.hardware.contexthub;
+
+import android.annotation.FlaggedApi;
+import android.annotation.IntDef;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.chre.flags.Flags;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.ParcelableHolder;
+
+import androidx.annotation.NonNull;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Collection;
+import java.util.Objects;
+
+/**
+ * A class describing services provided by endpoints.
+ *
+ * An endpoint can provide zero or more service. See {@link
+ * HubEndpoint.Builder#setServiceInfoCollection(Collection)} and {@link
+ * HubEndpointInfo#getServiceInfoCollection()}.
+ *
+ *
An endpoint session can be service-less or associated to one service.See {@link
+ * HubEndpointSession#getServiceInfo()}.
+ *
+ * @hide
+ */
+@SystemApi
+@FlaggedApi(Flags.FLAG_OFFLOAD_API)
+public final class HubServiceInfo implements Parcelable {
+ /** Customized format for messaging. Fully customized and opaque messaging format. */
+ public static final int FORMAT_CUSTOM = 0;
+
+ /**
+ * Binder-based messaging. The host endpoint is defining this service in Stable AIDL. Messages
+ * between endpoints that uses this service will be using the binder marhsalling format.
+ */
+ public static final int FORMAT_AIDL = 1;
+
+ /**
+ * Pigweed RPC messaging with Protobuf. This endpoint is a Pigweed RPC. Messages between
+ * endpoints will use Pigweed RPC marshalling format (protobuf).
+ */
+ public static final int FORMAT_PW_RPC_PROTOBUF = 2;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({
+ FORMAT_CUSTOM,
+ FORMAT_AIDL,
+ FORMAT_PW_RPC_PROTOBUF,
+ })
+ public @interface ServiceFormat {}
+
+ @NonNull private final String mServiceDescriptor;
+
+ @ServiceFormat private final int mFormat;
+ private final int mMajorVersion;
+ private final int mMinorVersion;
+
+ @NonNull private final ParcelableHolder mExtendedInfo;
+
+ /** @hide */
+ public HubServiceInfo(android.hardware.contexthub.Service service) {
+ mServiceDescriptor = service.serviceDescriptor;
+ mFormat = service.format;
+ mMajorVersion = service.majorVersion;
+ mMinorVersion = service.minorVersion;
+ mExtendedInfo = service.extendedInfo;
+ }
+
+ private HubServiceInfo(Parcel in) {
+ mServiceDescriptor = Objects.requireNonNull(in.readString());
+ mFormat = in.readInt();
+ mMajorVersion = in.readInt();
+ mMinorVersion = in.readInt();
+ mExtendedInfo = ParcelableHolder.CREATOR.createFromParcel(in);
+ }
+
+ public HubServiceInfo(
+ @NonNull String serviceDescriptor,
+ @ServiceFormat int format,
+ int majorVersion,
+ int minorVersion,
+ @NonNull ParcelableHolder extendedInfo) {
+ mServiceDescriptor = serviceDescriptor;
+ mFormat = format;
+ mMajorVersion = majorVersion;
+ mMinorVersion = minorVersion;
+ mExtendedInfo = extendedInfo;
+ }
+
+ /** Get the unique identifier of this service. See {@link Builder} for more information. */
+ @NonNull
+ public String getServiceDescriptor() {
+ return mServiceDescriptor;
+ }
+
+ /**
+ * Get the type of the service.
+ *
+ *
The value can be one of {@link HubServiceInfo#FORMAT_CUSTOM}, {@link
+ * HubServiceInfo#FORMAT_AIDL} or {@link HubServiceInfo#FORMAT_PW_RPC_PROTOBUF}.
+ */
+ public int getFormat() {
+ return mFormat;
+ }
+
+ /** Get the major version of this service. */
+ public int getMajorVersion() {
+ return mMajorVersion;
+ }
+
+ /** Get the minor version of this service. */
+ public int getMinorVersion() {
+ return mMinorVersion;
+ }
+
+ /** Get the {@link ParcelableHolder} for the extended information about the service. */
+ @NonNull
+ public ParcelableHolder getExtendedInfo() {
+ return mExtendedInfo;
+ }
+
+ /** Parcel implementation details */
+ @Override
+ public int describeContents() {
+ // Passthrough describeContents flags for mExtendedInfo because we don't have FD otherwise.
+ return mExtendedInfo.describeContents();
+ }
+
+ /** Parcel implementation details */
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeString(mServiceDescriptor);
+ dest.writeInt(mFormat);
+ dest.writeInt(mMajorVersion);
+ dest.writeInt(mMinorVersion);
+ mExtendedInfo.writeToParcel(dest, flags);
+ }
+
+ /** Builder for a {@link HubServiceInfo} object. */
+ public static final class Builder {
+ @NonNull private final String mServiceDescriptor;
+
+ @ServiceFormat private final int mFormat;
+ private final int mMajorVersion;
+ private final int mMinorVersion;
+
+ private final ParcelableHolder mExtendedInfo =
+ new ParcelableHolder(Parcelable.PARCELABLE_STABILITY_VINTF);
+
+ /**
+ * Create a builder for {@link HubServiceInfo} with a service descriptor.
+ *
+ *
Service descriptor should uniquely identify the interface (scoped to type). Convention
+ * of the descriptor depend on interface type.
+ *
+ *
Examples:
+ *
+ *
+ * - AOSP-defined AIDL: android.hardware.something.IFoo/default
+ *
- Vendor-defined AIDL: com.example.something.IBar/default
+ *
- Pigweed RPC with Protobuf: com.example.proto.ExampleService
+ *
+ *
+ * @param serviceDescriptor The service descriptor.
+ * @param format One of {@link HubServiceInfo#FORMAT_CUSTOM}, {@link
+ * HubServiceInfo#FORMAT_AIDL} or {@link HubServiceInfo#FORMAT_PW_RPC_PROTOBUF}.
+ * @param majorVersion Breaking changes should be a major version bump.
+ * @param minorVersion Monotonically increasing minor version.
+ * @throws IllegalArgumentException if one or more fields are not valid.
+ */
+ public Builder(
+ @NonNull String serviceDescriptor,
+ @ServiceFormat int format,
+ int majorVersion,
+ int minorVersion) {
+ if (format != FORMAT_CUSTOM
+ && format != FORMAT_AIDL
+ && format != FORMAT_PW_RPC_PROTOBUF) {
+ throw new IllegalArgumentException("Invalid format type.");
+ }
+ mFormat = format;
+
+ if (majorVersion < 0) {
+ throw new IllegalArgumentException(
+ "Major version cannot be set to negative number.");
+ }
+ mMajorVersion = majorVersion;
+
+ if (minorVersion < 0) {
+ throw new IllegalArgumentException(
+ "Minor version cannot be set to negative number.");
+ }
+ mMinorVersion = minorVersion;
+
+ if (serviceDescriptor.isBlank()) {
+ throw new IllegalArgumentException("Invalid service descriptor.");
+ }
+ mServiceDescriptor = serviceDescriptor;
+ }
+
+ /**
+ * Set the extended information of this service.
+ *
+ * @param extendedInfo Parcelable with extended information about this service. The
+ * parcelable needs to have at least VINTF stability. Null can be used to clear a
+ * previously set value.
+ * @throws android.os.BadParcelableException if the parcelable cannot be used.
+ */
+ @NonNull
+ public Builder setExtendedInfo(@Nullable Parcelable extendedInfo) {
+ mExtendedInfo.setParcelable(extendedInfo);
+ return this;
+ }
+
+ /**
+ * Build the {@link HubServiceInfo} object.
+ *
+ * @throws IllegalStateException if the Builder is missing required info.
+ */
+ @NonNull
+ public HubServiceInfo build() {
+ if (mMajorVersion < 0 || mMinorVersion < 0) {
+ throw new IllegalStateException("Major and minor version must be set.");
+ }
+ return new HubServiceInfo(
+ mServiceDescriptor, mFormat, mMajorVersion, mMinorVersion, mExtendedInfo);
+ }
+ }
+
+ /** Parcel implementation details */
+ @NonNull
+ public static final Parcelable.Creator CREATOR =
+ new Parcelable.Creator<>() {
+ public HubServiceInfo createFromParcel(Parcel in) {
+ return new HubServiceInfo(in);
+ }
+
+ public HubServiceInfo[] newArray(int size) {
+ return new HubServiceInfo[size];
+ }
+ };
+}
diff --git a/core/java/android/hardware/contexthub/IContextHubEndpoint.aidl b/core/java/android/hardware/contexthub/IContextHubEndpoint.aidl
new file mode 100644
index 0000000000000000000000000000000000000000..1c98b4b3f4f569d6e56d25de180d9001a12b5eec
--- /dev/null
+++ b/core/java/android/hardware/contexthub/IContextHubEndpoint.aidl
@@ -0,0 +1,90 @@
+/*
+ * Copyright 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.hardware.contexthub;
+
+import android.hardware.contexthub.HubEndpointInfo;
+import android.hardware.contexthub.HubMessage;
+import android.hardware.contexthub.HubServiceInfo;
+import android.hardware.location.IContextHubTransactionCallback;
+
+/**
+ * @hide
+ */
+interface IContextHubEndpoint {
+ /**
+ * Retrieve the up-to-date EndpointInfo, with assigned endpoint id.
+ */
+ HubEndpointInfo getAssignedHubEndpointInfo();
+
+ /**
+ * Request system service to open a session with a specific destination.
+ *
+ * @param destination A valid HubEndpointInfo representing the destination.
+ *
+ * @throws IllegalArgumentException If the HubEndpointInfo is not valid.
+ * @throws IllegalStateException If there are too many opened sessions.
+ */
+ int openSession(in HubEndpointInfo destination, in @nullable HubServiceInfo serviceInfo);
+
+ /**
+ * Request system service to close a specific session
+ *
+ * @param sessionId An integer identifying the session, assigned by system service
+ * @param reason An integer identifying the reason
+ *
+ * @throws IllegalStateException If the session wasn't opened.
+ */
+ void closeSession(int sessionId, int reason);
+
+ /**
+ * Callback when a session is opened. This callback is the status callback for a previous
+ * IContextHubEndpointCallback.onSessionOpenRequest().
+ *
+ * @param sessionId The integer representing the communication session, previously set in
+ * onSessionOpenRequest().
+ *
+ * @throws IllegalStateException If the session wasn't opened.
+ */
+ void openSessionRequestComplete(int sessionId);
+
+ /**
+ * Unregister this endpoint from the HAL, invalidate the EndpointInfo previously assigned.
+ */
+ void unregister();
+
+ /**
+ * Send a message parcelable to system service for a specific session.
+ *
+ * @param sessionId The integer representing the communication session, previously set in
+ * IContextHubEndpoint.openSession(). This id is assigned by the HAL.
+ * @param message The HubMessage parcelable that represents the message and its delivery options.
+ * @param transactionCallback Nullable. If the hub message requires a reply, the transactionCallback
+ * will be set to non-null.
+ */
+ void sendMessage(int sessionId, in HubMessage message,
+ in @nullable IContextHubTransactionCallback transactionCallback);
+
+ /**
+ * Send a message delivery status to system service for a specific message
+ *
+ * @param sessionId The integer representing the communication session, previously set in
+ * IContextHubEndpoint.openSession(). This id is assigned by the HAL.
+ * @param messageSeqNumber The message sequence number, this should match a previously received HubMessage.
+ * @param errorCode The message delivery status detail.
+ */
+ void sendMessageDeliveryStatus(int sessionId, int messageSeqNumber, byte errorCode);
+}
diff --git a/core/java/android/hardware/contexthub/IContextHubEndpointCallback.aidl b/core/java/android/hardware/contexthub/IContextHubEndpointCallback.aidl
new file mode 100644
index 0000000000000000000000000000000000000000..1ae5fb9d28c1a2d989ed1f41a629dff648f67c49
--- /dev/null
+++ b/core/java/android/hardware/contexthub/IContextHubEndpointCallback.aidl
@@ -0,0 +1,61 @@
+/*
+ * Copyright 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.hardware.contexthub;
+
+import android.hardware.contexthub.HubEndpointInfo;
+import android.hardware.contexthub.HubMessage;
+import android.hardware.contexthub.HubServiceInfo;
+
+/**
+ * @hide
+ */
+oneway interface IContextHubEndpointCallback {
+ /**
+ * Request from system service to open a session, requested by a specific initiator.
+ *
+ * @param sessionId An integer identifying the session, assigned by the initiator
+ * @param initiator HubEndpointInfo representing the requester
+ * @param serviceInfo Nullable HubServiceInfo representing the service associated with this session
+ */
+ void onSessionOpenRequest(int sessionId, in HubEndpointInfo initiator, in @nullable HubServiceInfo serviceInfo);
+
+ /**
+ * Request from system service to close a specific session
+ *
+ * @param sessionId An integer identifying the session
+ * @param reason An integer identifying the reason
+ */
+ void onSessionClosed(int sessionId, int reason);
+
+ /**
+ * Notifies the system service that the session requested by IContextHubEndpoint.openSession
+ * is ready to use.
+ *
+ * @param sessionId The integer representing the communication session, previously set in
+ * IContextHubEndpoint.openSession(). This id is assigned by the HAL.
+ */
+ void onSessionOpenComplete(int sessionId);
+
+ /**
+ * Message notification from system service for a specific session
+
+ * @param sessionId The integer representing the communication session, previously set in
+ * IContextHubEndpoint.openSession(). This id is assigned by the HAL.
+ * @param message The HubMessage parcelable that represents the message.
+ */
+ void onMessageReceived(int sessionId, in HubMessage message);
+}
diff --git a/core/java/android/hardware/contexthub/IHubEndpointLifecycleCallback.java b/core/java/android/hardware/contexthub/IHubEndpointLifecycleCallback.java
new file mode 100644
index 0000000000000000000000000000000000000000..46884393b49ba9ec89bc5ddd5b0b606943be301a
--- /dev/null
+++ b/core/java/android/hardware/contexthub/IHubEndpointLifecycleCallback.java
@@ -0,0 +1,82 @@
+/*
+ * 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.hardware.contexthub;
+
+import android.annotation.FlaggedApi;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.chre.flags.Flags;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Interface for listening to lifecycle events of a hub endpoint.
+ *
+ * @hide
+ */
+@SystemApi
+@FlaggedApi(Flags.FLAG_OFFLOAD_API)
+public interface IHubEndpointLifecycleCallback {
+ /** Unknown reason. */
+ int REASON_UNSPECIFIED = 0;
+
+ /** The peer rejected the request to open this endpoint session. */
+ int REASON_OPEN_ENDPOINT_SESSION_REQUEST_REJECTED = 3;
+
+ /** The peer closed this endpoint session. */
+ int REASON_CLOSE_ENDPOINT_SESSION_REQUESTED = 4;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({
+ REASON_UNSPECIFIED,
+ REASON_OPEN_ENDPOINT_SESSION_REQUEST_REJECTED,
+ REASON_CLOSE_ENDPOINT_SESSION_REQUESTED,
+ })
+ @interface EndpointLifecycleReason {}
+
+ /**
+ * Called when an endpoint is requesting a session be opened with another endpoint.
+ *
+ * @param requester The {@link HubEndpointInfo} object representing the requester
+ * @param serviceInfo The {@link HubServiceInfo} object representing the service associated with
+ * this session. Null indicates that there is no service associated with this session.
+ */
+ @NonNull
+ HubEndpointSessionResult onSessionOpenRequest(
+ @NonNull HubEndpointInfo requester, @Nullable HubServiceInfo serviceInfo);
+
+ /**
+ * Called when a communication session is opened and ready to be used.
+ *
+ * @param session The {@link HubEndpointSession} object that can be used for communication
+ */
+ void onSessionOpened(@NonNull HubEndpointSession session);
+
+ /**
+ * Called when a communication session is requested to be closed, or the peer endpoint rejected
+ * the session open request.
+ *
+ * @param session The {@link HubEndpointSession} object that is now closed and shouldn't be
+ * used.
+ * @param reason The reason why this session was closed.
+ */
+ void onSessionClosed(@NonNull HubEndpointSession session, @EndpointLifecycleReason int reason);
+}
diff --git a/core/java/android/hardware/contexthub/IHubEndpointMessageCallback.java b/core/java/android/hardware/contexthub/IHubEndpointMessageCallback.java
new file mode 100644
index 0000000000000000000000000000000000000000..fde7017b5e76d1775b0b2987f2e2c1239b1630da
--- /dev/null
+++ b/core/java/android/hardware/contexthub/IHubEndpointMessageCallback.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 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.hardware.contexthub;
+
+import android.annotation.FlaggedApi;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.chre.flags.Flags;
+
+/**
+ * An interface used to deliver messages to an opened endpoint session.
+ *
+ * This interface can be attached to an endpoint through {@link
+ * HubEndpoint.Builder#setMessageCallback} method. Methods in this interface will only be called
+ * when the endpoint is currently registered and has an open session. The endpoint will receive
+ * session lifecycle callbacks through {@link IHubEndpointLifecycleCallback}.
+ *
+ * @hide
+ */
+@SystemApi
+@FlaggedApi(Flags.FLAG_OFFLOAD_API)
+public interface IHubEndpointMessageCallback {
+ /**
+ * Callback interface for receiving messages for a particular endpoint session.
+ *
+ * @param session The session this message is sent through. Previously specified in a {@link
+ * IHubEndpointLifecycleCallback#onSessionOpened(HubEndpointSession)} call.
+ * @param message The {@link HubMessage} object representing a message received by the endpoint
+ * that registered this callback interface. This message is constructed by the
+ */
+ void onMessageReceived(@NonNull HubEndpointSession session, @NonNull HubMessage message);
+}
diff --git a/core/java/android/hardware/contexthub/OWNERS b/core/java/android/hardware/contexthub/OWNERS
new file mode 100644
index 0000000000000000000000000000000000000000..a65a2bf9ee3615116b6ada6a8966eb1921b8d716
--- /dev/null
+++ b/core/java/android/hardware/contexthub/OWNERS
@@ -0,0 +1,2 @@
+# ContextHub team
+file:platform/system/chre:/OWNERS
diff --git a/core/java/android/hardware/devicestate/DeviceState.java b/core/java/android/hardware/devicestate/DeviceState.java
index e583627c09600a0e4fced944a8789ece57209fde..8b4d0da147bccb85c9e0940bb69ce581e7d3c856 100644
--- a/core/java/android/hardware/devicestate/DeviceState.java
+++ b/core/java/android/hardware/devicestate/DeviceState.java
@@ -172,6 +172,23 @@ public final class DeviceState {
*/
public static final int PROPERTY_FEATURE_DUAL_DISPLAY_INTERNAL_DEFAULT = 17;
+ /**
+ * Property that indicates that this state corresponds to the device state for rear display
+ * mode, where both the inner and outer displays are on. In this state, the outer display
+ * is the default display where the app is shown, and the inner display is used by the system to
+ * show a UI affordance for exiting the mode.
+ *
+ * Note that this value should generally not be used, and may be removed in the future (e.g.
+ * if or when it becomes the only type of rear display mode when
+ * {@link android.hardware.devicestate.feature.flags.Flags#deviceStateRdmV2} is removed).
+ *
+ * As such, clients should strongly consider relying on {@link #PROPERTY_FEATURE_REAR_DISPLAY}
+ * instead.
+ *
+ * @hide
+ */
+ public static final int PROPERTY_FEATURE_REAR_DISPLAY_OUTER_DEFAULT = 1001;
+
/** @hide */
@IntDef(prefix = {"PROPERTY_"}, flag = false, value = {
PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_CLOSED,
@@ -190,7 +207,8 @@ public final class DeviceState {
PROPERTY_POWER_CONFIGURATION_TRIGGER_WAKE,
PROPERTY_EXTENDED_DEVICE_STATE_EXTERNAL_DISPLAY,
PROPERTY_FEATURE_REAR_DISPLAY,
- PROPERTY_FEATURE_DUAL_DISPLAY_INTERNAL_DEFAULT
+ PROPERTY_FEATURE_DUAL_DISPLAY_INTERNAL_DEFAULT,
+ PROPERTY_FEATURE_REAR_DISPLAY_OUTER_DEFAULT
})
@Retention(RetentionPolicy.SOURCE)
@Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})
diff --git a/core/java/android/hardware/devicestate/feature/flags.aconfig b/core/java/android/hardware/devicestate/feature/flags.aconfig
index 98ba9192044d03d7a63e18fc82501e2d92d475ea..6230f4dbf6f46bd319ffc6e7864864b339536500 100644
--- a/core/java/android/hardware/devicestate/feature/flags.aconfig
+++ b/core/java/android/hardware/devicestate/feature/flags.aconfig
@@ -29,4 +29,13 @@ flag {
metadata {
purpose: PURPOSE_BUGFIX
}
+}
+
+flag {
+ name: "device_state_rdm_v2"
+ is_exported: true
+ namespace: "windowing_sdk"
+ description: "Enables Rear Display Mode V2, where the inner display shows the user a UI affordance for exiting the state"
+ bug: "372486634"
+ is_fixed_read_only: true
}
\ No newline at end of file
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index 28da644dd837710f5796427a4e39427e34fc5fdf..25327a9b1d52583d7b7a36350c97bd089ea55981 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -21,6 +21,8 @@ import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.HdrCapabilities.HdrType;
import static android.view.Display.INVALID_DISPLAY;
+import static com.android.server.display.feature.flags.Flags.FLAG_DISPLAY_LISTENER_PERFORMANCE_IMPROVEMENTS;
+
import android.Manifest;
import android.annotation.FlaggedApi;
import android.annotation.FloatRange;
@@ -59,6 +61,7 @@ import android.view.Surface;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
+import com.android.server.display.feature.flags.Flags;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -100,6 +103,7 @@ public final class DisplayManager {
private final WeakDisplayCache mDisplayCache = new WeakDisplayCache();
private int mDisplayIdToMirror = INVALID_DISPLAY;
+ private AmbientDisplayConfiguration mAmbientDisplayConfiguration;
/**
* Broadcast receiver that indicates when the Wifi display status changes.
@@ -576,6 +580,8 @@ public final class DisplayManager {
EVENT_FLAG_DISPLAY_ADDED,
EVENT_FLAG_DISPLAY_CHANGED,
EVENT_FLAG_DISPLAY_REMOVED,
+ EVENT_FLAG_DISPLAY_REFRESH_RATE,
+ EVENT_FLAG_DISPLAY_STATE
})
@Retention(RetentionPolicy.SOURCE)
public @interface EventFlag {}
@@ -596,8 +602,8 @@ public final class DisplayManager {
*
* @see #registerDisplayListener(DisplayListener, Handler, long)
*
- * @hide
*/
+ @FlaggedApi(FLAG_DISPLAY_LISTENER_PERFORMANCE_IMPROVEMENTS)
public static final long EVENT_FLAG_DISPLAY_ADDED = 1L << 0;
/**
@@ -605,8 +611,8 @@ public final class DisplayManager {
*
* @see #registerDisplayListener(DisplayListener, Handler, long)
*
- * @hide
*/
+ @FlaggedApi(FLAG_DISPLAY_LISTENER_PERFORMANCE_IMPROVEMENTS)
public static final long EVENT_FLAG_DISPLAY_REMOVED = 1L << 1;
/**
@@ -614,10 +620,27 @@ public final class DisplayManager {
*
* @see #registerDisplayListener(DisplayListener, Handler, long)
*
- * @hide
*/
+ @FlaggedApi(FLAG_DISPLAY_LISTENER_PERFORMANCE_IMPROVEMENTS)
public static final long EVENT_FLAG_DISPLAY_CHANGED = 1L << 2;
+
+ /**
+ * Event flag to register for a display's refresh rate changes.
+ *
+ * @see #registerDisplayListener(DisplayListener, Handler, long)
+ */
+ @FlaggedApi(FLAG_DISPLAY_LISTENER_PERFORMANCE_IMPROVEMENTS)
+ public static final long EVENT_FLAG_DISPLAY_REFRESH_RATE = 1L << 3;
+
+ /**
+ * Event flag to register for a display state changes.
+ *
+ * @see #registerDisplayListener(DisplayListener, Handler, long)
+ */
+ @FlaggedApi(FLAG_DISPLAY_LISTENER_PERFORMANCE_IMPROVEMENTS)
+ public static final long EVENT_FLAG_DISPLAY_STATE = 1L << 4;
+
/**
* Event flag to register for a display's brightness changes. This notification is sent
* through the {@link DisplayListener#onDisplayChanged} callback method. New brightness
@@ -787,9 +810,6 @@ public final class DisplayManager {
* if the listener should be invoked on the calling thread's looper.
* @param eventFlags A bitmask of the event types for which this listener is subscribed.
*
- * @see #EVENT_FLAG_DISPLAY_ADDED
- * @see #EVENT_FLAG_DISPLAY_CHANGED
- * @see #EVENT_FLAG_DISPLAY_REMOVED
* @see #registerDisplayListener(DisplayListener, Handler)
* @see #unregisterDisplayListener
*
@@ -802,6 +822,25 @@ public final class DisplayManager {
ActivityThread.currentPackageName());
}
+ /**
+ * Registers a display listener to receive notifications about given display event types.
+ *
+ * @param listener The listener to register.
+ * @param executor Executor for the thread that will be receiving the callbacks. Cannot be null.
+ * @param eventFlags A bitmask of the event types for which this listener is subscribed.
+ *
+ * @see #registerDisplayListener(DisplayListener, Handler)
+ * @see #unregisterDisplayListener
+ *
+ */
+ @FlaggedApi(FLAG_DISPLAY_LISTENER_PERFORMANCE_IMPROVEMENTS)
+ public void registerDisplayListener(@NonNull Executor executor, @EventFlag long eventFlags,
+ @NonNull DisplayListener listener) {
+ mGlobal.registerDisplayListener(listener, executor,
+ mGlobal.mapFlagsToInternalEventFlag(eventFlags, 0),
+ ActivityThread.currentPackageName());
+ }
+
/**
* Registers a display listener to receive notifications about given display event types.
*
@@ -812,12 +851,6 @@ public final class DisplayManager {
* @param privateEventFlags A bitmask of the private event types for which this listener
* is subscribed.
*
- * @see #EVENT_FLAG_DISPLAY_ADDED
- * @see #EVENT_FLAG_DISPLAY_CHANGED
- * @see #EVENT_FLAG_DISPLAY_REMOVED
- * @see #PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS
- * @see #PRIVATE_EVENT_FLAG_DISPLAY_CONNECTION_CHANGED
- * @see #PRIVATE_EVENT_FLAG_HDR_SDR_RATIO_CHANGED
* @see #registerDisplayListener(DisplayListener, Handler)
* @see #unregisterDisplayListener
*
@@ -1581,6 +1614,17 @@ public final class DisplayManager {
return mGlobal.shouldAlwaysRespectAppRequestedMode();
}
+ /**
+ * Returns whether this device supports Always On Display.
+ *
+ * @hide
+ */
+ @SystemApi
+ @FlaggedApi(Flags.FLAG_IS_ALWAYS_ON_AVAILABLE_API)
+ public boolean isAlwaysOnDisplayCurrentlyAvailable() {
+ return getAmbientDisplayConfiguration().alwaysOnAvailableForUser(mContext.getUserId());
+ }
+
/**
* Returns whether device supports seamless refresh rate switching.
*
@@ -1643,6 +1687,15 @@ public final class DisplayManager {
}
}
+ private AmbientDisplayConfiguration getAmbientDisplayConfiguration() {
+ synchronized (this) {
+ if (mAmbientDisplayConfiguration == null) {
+ mAmbientDisplayConfiguration = new AmbientDisplayConfiguration(mContext);
+ }
+ }
+ return mAmbientDisplayConfiguration;
+ }
+
/**
* Creates a VirtualDisplay that will mirror the content of displayIdToMirror
* @param name The name for the virtual display
diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java
index 03b44f63e3b76a038083bb38d409667dcb1f570d..1e66beea42a63ff95498f0e1d2af95242ab1ecd1 100644
--- a/core/java/android/hardware/display/DisplayManagerGlobal.java
+++ b/core/java/android/hardware/display/DisplayManagerGlobal.java
@@ -17,6 +17,7 @@
package android.hardware.display;
+import static android.app.PropertyInvalidatedCache.MODULE_SYSTEM;
import static android.hardware.display.DisplayManager.EventFlag;
import static android.Manifest.permission.MANAGE_DISPLAYS;
import static android.view.Display.HdrCapabilities.HdrType;
@@ -62,6 +63,7 @@ import android.view.DisplayInfo;
import android.view.Surface;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.display.feature.flags.Flags;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -108,6 +110,8 @@ public final class DisplayManagerGlobal {
EVENT_DISPLAY_HDR_SDR_RATIO_CHANGED,
EVENT_DISPLAY_CONNECTED,
EVENT_DISPLAY_DISCONNECTED,
+ EVENT_DISPLAY_REFRESH_RATE_CHANGED,
+ EVENT_DISPLAY_STATE_CHANGED
})
@Retention(RetentionPolicy.SOURCE)
public @interface DisplayEvent {}
@@ -119,6 +123,8 @@ public final class DisplayManagerGlobal {
public static final int EVENT_DISPLAY_HDR_SDR_RATIO_CHANGED = 5;
public static final int EVENT_DISPLAY_CONNECTED = 6;
public static final int EVENT_DISPLAY_DISCONNECTED = 7;
+ public static final int EVENT_DISPLAY_REFRESH_RATE_CHANGED = 8;
+ public static final int EVENT_DISPLAY_STATE_CHANGED = 9;
@LongDef(prefix = {"INTERNAL_EVENT_DISPLAY"}, flag = true, value = {
INTERNAL_EVENT_FLAG_DISPLAY_ADDED,
@@ -127,6 +133,8 @@ public final class DisplayManagerGlobal {
INTERNAL_EVENT_FLAG_DISPLAY_BRIGHTNESS_CHANGED,
INTERNAL_EVENT_FLAG_DISPLAY_HDR_SDR_RATIO_CHANGED,
INTERNAL_EVENT_FLAG_DISPLAY_CONNECTION_CHANGED,
+ INTERNAL_EVENT_FLAG_DISPLAY_REFRESH_RATE,
+ INTERNAL_EVENT_FLAG_DISPLAY_STATE
})
@Retention(RetentionPolicy.SOURCE)
public @interface InternalEventFlag {}
@@ -137,6 +145,8 @@ public final class DisplayManagerGlobal {
public static final long INTERNAL_EVENT_FLAG_DISPLAY_BRIGHTNESS_CHANGED = 1L << 3;
public static final long INTERNAL_EVENT_FLAG_DISPLAY_HDR_SDR_RATIO_CHANGED = 1L << 4;
public static final long INTERNAL_EVENT_FLAG_DISPLAY_CONNECTION_CHANGED = 1L << 5;
+ public static final long INTERNAL_EVENT_FLAG_DISPLAY_REFRESH_RATE = 1L << 6;
+ public static final long INTERNAL_EVENT_FLAG_DISPLAY_STATE = 1L << 7;
@UnsupportedAppUsage
private static DisplayManagerGlobal sInstance;
@@ -179,9 +189,11 @@ public final class DisplayManagerGlobal {
}
private PropertyInvalidatedCache mDisplayCache =
- new PropertyInvalidatedCache(
- 8, // size of display cache
- CACHE_KEY_DISPLAY_INFO_PROPERTY) {
+ new PropertyInvalidatedCache<>(
+ new PropertyInvalidatedCache.Args(MODULE_SYSTEM)
+ .maxEntries(8).api(CACHE_KEY_DISPLAY_INFO_API).isolateUids(false),
+ CACHE_KEY_DISPLAY_INFO_API, null) {
+
@Override
public DisplayInfo recompute(Integer id) {
try {
@@ -1427,6 +1439,18 @@ public final class DisplayManagerGlobal {
mListener.onDisplayDisconnected(displayId);
}
break;
+ case EVENT_DISPLAY_REFRESH_RATE_CHANGED:
+ if ((mInternalEventFlagsMask
+ & INTERNAL_EVENT_FLAG_DISPLAY_REFRESH_RATE) != 0) {
+ mListener.onDisplayChanged(displayId);
+ }
+ break;
+ case EVENT_DISPLAY_STATE_CHANGED:
+ if ((mInternalEventFlagsMask
+ & INTERNAL_EVENT_FLAG_DISPLAY_STATE) != 0) {
+ mListener.onDisplayChanged(displayId);
+ }
+ break;
}
if (DEBUG) {
Trace.endSection();
@@ -1493,18 +1517,17 @@ public final class DisplayManagerGlobal {
}
/**
- * Name of the property containing a unique token which changes every time we update the
- * system's display configuration.
+ * The API portion of the key that identifies the unique PropertyInvalidatedCache token which
+ * changes every time we update the system's display configuration.
*/
- public static final String CACHE_KEY_DISPLAY_INFO_PROPERTY =
- PropertyInvalidatedCache.createSystemCacheKey("display_info");
+ private static final String CACHE_KEY_DISPLAY_INFO_API = "display_info";
/**
* Invalidates the contents of the display info cache for all applications. Can only
* be called by system_server.
*/
public static void invalidateLocalDisplayInfoCaches() {
- PropertyInvalidatedCache.invalidateCache(CACHE_KEY_DISPLAY_INFO_PROPERTY);
+ PropertyInvalidatedCache.invalidateCache(MODULE_SYSTEM, CACHE_KEY_DISPLAY_INFO_API);
}
/**
@@ -1566,6 +1589,10 @@ public final class DisplayManagerGlobal {
return "EVENT_DISPLAY_CONNECTED";
case EVENT_DISPLAY_DISCONNECTED:
return "EVENT_DISPLAY_DISCONNECTED";
+ case EVENT_DISPLAY_REFRESH_RATE_CHANGED:
+ return "EVENT_DISPLAY_REFRESH_RATE_CHANGED";
+ case EVENT_DISPLAY_STATE_CHANGED:
+ return "EVENT_DISPLAY_STATE_CHANGED";
}
return "UNKNOWN";
}
@@ -1630,6 +1657,17 @@ public final class DisplayManagerGlobal {
baseEventMask |= INTERNAL_EVENT_FLAG_DISPLAY_REMOVED;
}
+ if (Flags.displayListenerPerformanceImprovements()) {
+ if ((eventFlags & DisplayManager.EVENT_FLAG_DISPLAY_REFRESH_RATE) != 0) {
+ baseEventMask |= INTERNAL_EVENT_FLAG_DISPLAY_REFRESH_RATE;
+ }
+
+ if ((eventFlags & DisplayManager.EVENT_FLAG_DISPLAY_STATE) != 0) {
+ baseEventMask |= INTERNAL_EVENT_FLAG_DISPLAY_STATE;
+ }
+ }
+
+
return baseEventMask;
}
}
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java
index 399184cfaecb5cf54d96e89f6ca96409bdf70fb3..68b6cfc012fc50a7dd7e5731cabec4addc57931a 100644
--- a/core/java/android/hardware/display/DisplayManagerInternal.java
+++ b/core/java/android/hardware/display/DisplayManagerInternal.java
@@ -470,6 +470,31 @@ public abstract class DisplayManagerInternal {
*/
public abstract boolean isDisplayReadyForMirroring(int displayId);
+
+ /**
+ * Used by the window manager to override the per-display screen brightness based on the
+ * current foreground activity.
+ *
+ * The key of the array is the displayId. If a displayId is missing from the array, this is
+ * equivalent to clearing any existing brightness overrides for that display.
+ *
+ * This method must only be called by the window manager.
+ */
+ public abstract void setScreenBrightnessOverrideFromWindowManager(
+ SparseArray brightnessOverrides);
+
+ /**
+ * Describes a request for overriding the brightness of a single display.
+ */
+ public static class DisplayBrightnessOverrideRequest {
+ // An override of the screen brightness.
+ // Set to PowerManager.BRIGHTNESS_INVALID if there's no override.
+ public float brightness = PowerManager.BRIGHTNESS_INVALID_FLOAT;
+
+ // Tag used to identify the app window requesting the brightness override.
+ public CharSequence tag;
+ }
+
/**
* Describes the requested power state of the display.
*
@@ -505,11 +530,11 @@ public abstract class DisplayManagerInternal {
// nearby, turning it off temporarily until the object is moved away.
public boolean useProximitySensor;
- // An override of the screen brightness.
+ // A global override of the screen brightness, applied to all displays.
// Set to PowerManager.BRIGHTNESS_INVALID if there's no override.
public float screenBrightnessOverride;
- // Tag used to identify the app window requesting the brightness override.
+ // Tag used to identify the reason for the global brightness override.
public CharSequence screenBrightnessOverrideTag;
// An override of the screen auto-brightness adjustment factor in the range -1 (dimmer) to
diff --git a/core/java/android/hardware/display/DisplayTopology.java b/core/java/android/hardware/display/DisplayTopology.java
index e349b81614bc9fa2a5086d77aed8a94f60dd313e..f00c3a53ad0cb050a685001ea2714b4aa5c8672f 100644
--- a/core/java/android/hardware/display/DisplayTopology.java
+++ b/core/java/android/hardware/display/DisplayTopology.java
@@ -23,6 +23,7 @@ import static android.hardware.display.DisplayTopology.TreeNode.POSITION_TOP;
import android.annotation.IntDef;
import android.annotation.Nullable;
+import android.graphics.PointF;
import android.graphics.RectF;
import android.os.Parcel;
import android.os.Parcelable;
@@ -150,6 +151,138 @@ public final class DisplayTopology implements Parcelable {
}
}
+ /**
+ * Rearranges the topology toward the positions given for each display. The width and height of
+ * each display, as well as the primary display, are not changed by this call.
+ *
+ * Upon returning, the topology will be valid and normalized with each display as close to the
+ * requested positions as possible.
+ *
+ * @param newPos the desired positions (upper-left corner) of each display. The keys in the map
+ * are the display IDs.
+ * @throws IllegalArgumentException if the keys in {@code positions} are not the exact display
+ * IDs in this topology, no more, no less
+ */
+ public void rearrange(Map newPos) {
+ var availableParents = new ArrayList();
+
+ availableParents.addLast(mRoot);
+
+ var needsParent = allNodesIdMap();
+
+ // In the case of missing items, if this check doesn't detect it, a NPE will be thrown
+ // later.
+ if (needsParent.size() != newPos.size()) {
+ throw new IllegalArgumentException("newPos has wrong number of entries: " + newPos);
+ }
+
+ mRoot.mChildren.clear();
+ for (TreeNode n : needsParent.values()) {
+ n.mChildren.clear();
+ }
+
+ needsParent.remove(mRoot.mDisplayId);
+ // Start with a root island and add children to it one-by-one until the island consists of
+ // all the displays. The root island begins with only the root node, which has no
+ // parent. Then we greedily choose an optimal pairing of two nodes, consisting of a node
+ // from the island and a node not yet in the island. This is repeating until all nodes are
+ // in the island.
+ //
+ // The optimal pair is the pair which has the smallest deviation. The deviation consists of
+ // an x-axis component and a y-axis component, called xDeviation and yDeviation.
+ //
+ // The deviations are like distances but a little different. They are calculated in two
+ // steps. The first step calculates both axes in a similar way. The next step compares the
+ // two values and chooses which axis to attach along. Depending on which axis is chosen,
+ // the deviation for one axis is updated. See below for details.
+ while (!needsParent.isEmpty()) {
+ double bestDist = Double.POSITIVE_INFINITY;
+ TreeNode bestChild = null, bestParent = null;
+
+ for (var child : needsParent.values()) {
+ PointF childPos = newPos.get(child.mDisplayId);
+ float childRight = childPos.x + child.getWidth();
+ float childBottom = childPos.y + child.getHeight();
+ for (var parent : availableParents) {
+ PointF parentPos = newPos.get(parent.mDisplayId);
+ float parentRight = parentPos.x + parent.getWidth();
+ float parentBottom = parentPos.y + parent.getHeight();
+
+ // This is the smaller of the two ranges minus the amount of overlap shared
+ // between them. The "amount of overlap" is negative if there is no overlap, but
+ // this does not make a parenting ineligible, because we allow for attaching at
+ // the corner and for floating point error. The overlap is more negative the
+ // farther apart the closest corner pair is.
+ //
+ // For each axis, this calculates (SmallerRange - Overlap). If one range lies
+ // completely in the other (or they are equal), the axis' deviation will be
+ // zero.
+ //
+ // The "SmallerRange," which refers to smaller of the widths of the two rects,
+ // or smaller of the heights of the two rects, is added to the deviation so that
+ // a maximum overlap results in a deviation of zero.
+ float xSmallerRange = Math.min(child.getWidth(), parent.getWidth());
+ float ySmallerRange = Math.min(child.getHeight(), parent.getHeight());
+ float xOverlap
+ = Math.min(parentRight, childRight)
+ - Math.max(parentPos.x, childPos.x);
+ float yOverlap
+ = Math.min(parentBottom, childBottom)
+ - Math.max(parentPos.y, childPos.y);
+ float xDeviation = xSmallerRange - xOverlap;
+ float yDeviation = ySmallerRange - yOverlap;
+
+ float offset;
+ int pos;
+ if (xDeviation <= yDeviation) {
+ if (childPos.y < parentPos.y) {
+ yDeviation = childBottom - parentPos.y;
+ pos = POSITION_TOP;
+ } else {
+ yDeviation = parentBottom - childPos.y;
+ pos = POSITION_BOTTOM;
+ }
+ offset = childPos.x - parentPos.x;
+ } else {
+ if (childPos.x < parentPos.x) {
+ xDeviation = childRight - parentPos.x;
+ pos = POSITION_LEFT;
+ } else {
+ xDeviation = parentRight - childPos.x;
+ pos = POSITION_RIGHT;
+ }
+ offset = childPos.y - parentPos.y;
+ }
+
+ double dist = Math.hypot(xDeviation, yDeviation);
+ if (dist >= bestDist) {
+ continue;
+ }
+
+ bestDist = dist;
+ bestChild = child;
+ bestParent = parent;
+ // Eagerly update the child's parenting info, even though we may not use it, in
+ // which case it will be overwritten later.
+ bestChild.mPosition = pos;
+ bestChild.mOffset = offset;
+ }
+ }
+
+ assert bestParent != null & bestChild != null;
+
+ bestParent.addChild(bestChild);
+ if (null == needsParent.remove(bestChild.mDisplayId)) {
+ throw new IllegalStateException("child not in pending set! " + bestChild);
+ }
+ availableParents.add(bestChild);
+ }
+
+ // The conversion may have introduced an intersection of two display rects. If they are
+ // bigger than our error tolerance, this function will remove them.
+ normalize();
+ }
+
@Override
public int describeContents() {
return 0;
@@ -450,6 +583,20 @@ public final class DisplayTopology implements Parcelable {
return a == b || (Float.isNaN(a) && Float.isNaN(b)) || Math.abs(a - b) < EPSILON;
}
+ private Map allNodesIdMap() {
+ var pend = new ArrayDeque();
+ var found = new HashMap();
+
+ pend.push(mRoot);
+ do {
+ TreeNode node = pend.pop();
+ found.put(node.mDisplayId, node);
+ pend.addAll(node.mChildren);
+ } while (!pend.isEmpty());
+
+ return found;
+ }
+
public static final class TreeNode implements Parcelable {
public static final int POSITION_LEFT = 0;
public static final int POSITION_TOP = 1;
diff --git a/core/java/android/hardware/flags/overlayproperties_flags.aconfig b/core/java/android/hardware/flags/flags.aconfig
similarity index 63%
rename from core/java/android/hardware/flags/overlayproperties_flags.aconfig
rename to core/java/android/hardware/flags/flags.aconfig
index 6c86108c4034b7824dbd6e418501d62a05fb09f6..5ca6c6bed1f0f190d8baf4a5b219bd0ac1f3386c 100644
--- a/core/java/android/hardware/flags/overlayproperties_flags.aconfig
+++ b/core/java/android/hardware/flags/flags.aconfig
@@ -1,6 +1,15 @@
package: "android.hardware.flags"
container: "system"
+flag {
+ name: "luts_api"
+ is_exported: true
+ is_fixed_read_only: true
+ namespace: "core_graphics"
+ description: "public Luts related Apis"
+ bug: "349667978"
+}
+
flag {
name: "overlayproperties_class_api"
is_exported: true
diff --git a/core/java/android/hardware/input/AidlInputGestureData.aidl b/core/java/android/hardware/input/AidlInputGestureData.aidl
index e33ec53dd20850b01c9bbe86156bf3db7d555d42..f7410d2e7783afa3e9ca8ba8e6ccc18e73396ed6 100644
--- a/core/java/android/hardware/input/AidlInputGestureData.aidl
+++ b/core/java/android/hardware/input/AidlInputGestureData.aidl
@@ -28,15 +28,18 @@ parcelable AidlInputGestureData {
String appLaunchPackageName;
String appLaunchClassName;
+ @JavaDerive(equals=true)
parcelable KeyTrigger {
int keycode;
int modifierState;
}
+ @JavaDerive(equals=true)
parcelable TouchpadGestureTrigger {
int gestureType;
}
+ @JavaDerive(equals=true)
union Trigger {
KeyTrigger key;
TouchpadGestureTrigger touchpadGesture;
diff --git a/core/java/android/hardware/input/InputSettings.java b/core/java/android/hardware/input/InputSettings.java
index 96f6ad117035a3f2b9accd93fde6673ce372923a..71b60cff936762d77706f8b0448230bcf4b55475 100644
--- a/core/java/android/hardware/input/InputSettings.java
+++ b/core/java/android/hardware/input/InputSettings.java
@@ -31,6 +31,7 @@ import static com.android.hardware.input.Flags.touchpadTapDragging;
import static com.android.hardware.input.Flags.touchpadThreeFingerTapShortcut;
import static com.android.hardware.input.Flags.touchpadVisualizer;
import static com.android.hardware.input.Flags.useKeyGestureEventHandler;
+import static com.android.hardware.input.Flags.useKeyGestureEventHandlerMultiPressGestures;
import static com.android.input.flags.Flags.FLAG_KEYBOARD_REPEAT_KEYS;
import static com.android.input.flags.Flags.enableInputFilterRustImpl;
import static com.android.input.flags.Flags.keyboardRepeatKeys;
@@ -1147,4 +1148,13 @@ public class InputSettings {
public static boolean isCustomizableInputGesturesFeatureFlagEnabled() {
return enableCustomizableInputGestures() && useKeyGestureEventHandler();
}
+
+ /**
+ * Whether multi-key gestures are supported using {@code KeyGestureEventHandler}
+ *
+ * @hide
+ */
+ public static boolean doesKeyGestureEventHandlerSupportMultiKeyGestures() {
+ return useKeyGestureEventHandler() && useKeyGestureEventHandlerMultiPressGestures();
+ }
}
diff --git a/core/java/android/hardware/input/KeyGestureEvent.java b/core/java/android/hardware/input/KeyGestureEvent.java
index 24951c4d516e0339f34951445b155a65824818b7..711dc3a2cf7c49ce86c0b96b9cbcf1900d249c1c 100644
--- a/core/java/android/hardware/input/KeyGestureEvent.java
+++ b/core/java/android/hardware/input/KeyGestureEvent.java
@@ -115,12 +115,14 @@ public final class KeyGestureEvent {
public static final int KEY_GESTURE_TYPE_TOGGLE_MOUSE_KEYS = 67;
public static final int KEY_GESTURE_TYPE_SNAP_LEFT_FREEFORM_WINDOW = 68;
public static final int KEY_GESTURE_TYPE_SNAP_RIGHT_FREEFORM_WINDOW = 69;
- public static final int KEY_GESTURE_TYPE_MAXIMIZE_FREEFORM_WINDOW = 70;
- public static final int KEY_GESTURE_TYPE_RESTORE_FREEFORM_WINDOW_SIZE = 71;
+ public static final int KEY_GESTURE_TYPE_MINIMIZE_FREEFORM_WINDOW = 70;
+ public static final int KEY_GESTURE_TYPE_TOGGLE_MAXIMIZE_FREEFORM_WINDOW = 71;
public static final int KEY_GESTURE_TYPE_MAGNIFIER_ZOOM_IN = 72;
public static final int KEY_GESTURE_TYPE_MAGNIFIER_ZOOM_OUT = 73;
public static final int KEY_GESTURE_TYPE_TOGGLE_MAGNIFICATION = 74;
public static final int KEY_GESTURE_TYPE_ACTIVATE_SELECT_TO_SPEAK = 75;
+ public static final int KEY_GESTURE_TYPE_MAXIMIZE_FREEFORM_WINDOW = 76;
+
public static final int FLAG_CANCELLED = 1;
@@ -205,12 +207,13 @@ public final class KeyGestureEvent {
KEY_GESTURE_TYPE_TOGGLE_MOUSE_KEYS,
KEY_GESTURE_TYPE_SNAP_LEFT_FREEFORM_WINDOW,
KEY_GESTURE_TYPE_SNAP_RIGHT_FREEFORM_WINDOW,
- KEY_GESTURE_TYPE_MAXIMIZE_FREEFORM_WINDOW,
- KEY_GESTURE_TYPE_RESTORE_FREEFORM_WINDOW_SIZE,
+ KEY_GESTURE_TYPE_MINIMIZE_FREEFORM_WINDOW,
+ KEY_GESTURE_TYPE_TOGGLE_MAXIMIZE_FREEFORM_WINDOW,
KEY_GESTURE_TYPE_MAGNIFIER_ZOOM_IN,
KEY_GESTURE_TYPE_MAGNIFIER_ZOOM_OUT,
KEY_GESTURE_TYPE_TOGGLE_MAGNIFICATION,
KEY_GESTURE_TYPE_ACTIVATE_SELECT_TO_SPEAK,
+ KEY_GESTURE_TYPE_MAXIMIZE_FREEFORM_WINDOW
})
@Retention(RetentionPolicy.SOURCE)
public @interface KeyGestureType {
@@ -557,14 +560,6 @@ public final class KeyGestureEvent {
return FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__DESKTOP_MODE;
case KEY_GESTURE_TYPE_MULTI_WINDOW_NAVIGATION:
return FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__MULTI_WINDOW_NAVIGATION;
- case KEY_GESTURE_TYPE_SNAP_LEFT_FREEFORM_WINDOW:
- return FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__SNAP_LEFT_FREEFORM_WINDOW;
- case KEY_GESTURE_TYPE_SNAP_RIGHT_FREEFORM_WINDOW:
- return FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__SNAP_RIGHT_FREEFORM_WINDOW;
- case KEY_GESTURE_TYPE_MAXIMIZE_FREEFORM_WINDOW:
- return FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__MAXIMIZE_FREEFORM_WINDOW;
- case KEY_GESTURE_TYPE_RESTORE_FREEFORM_WINDOW_SIZE:
- return FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__RESTORE_FREEFORM_WINDOW_SIZE;
default:
return LOG_EVENT_UNSPECIFIED;
}
@@ -777,10 +772,10 @@ public final class KeyGestureEvent {
return "KEY_GESTURE_TYPE_SNAP_LEFT_FREEFORM_WINDOW";
case KEY_GESTURE_TYPE_SNAP_RIGHT_FREEFORM_WINDOW:
return "KEY_GESTURE_TYPE_SNAP_RIGHT_FREEFORM_WINDOW";
- case KEY_GESTURE_TYPE_MAXIMIZE_FREEFORM_WINDOW:
- return "KEY_GESTURE_TYPE_SNAP_RIGHT_FREEFORM_WINDOW";
- case KEY_GESTURE_TYPE_RESTORE_FREEFORM_WINDOW_SIZE:
- return "KEY_GESTURE_TYPE_RESTORE_FREEFORM_WINDOW_SIZE";
+ case KEY_GESTURE_TYPE_MINIMIZE_FREEFORM_WINDOW:
+ return "KEY_GESTURE_TYPE_MINIMIZE_FREEFORM_WINDOW";
+ case KEY_GESTURE_TYPE_TOGGLE_MAXIMIZE_FREEFORM_WINDOW:
+ return "KEY_GESTURE_TYPE_TOGGLE_MAXIMIZE_FREEFORM_WINDOW";
case KEY_GESTURE_TYPE_MAGNIFIER_ZOOM_IN:
return "KEY_GESTURE_TYPE_MAGNIFIER_ZOOM_IN";
case KEY_GESTURE_TYPE_MAGNIFIER_ZOOM_OUT:
@@ -789,6 +784,8 @@ public final class KeyGestureEvent {
return "KEY_GESTURE_TYPE_TOGGLE_MAGNIFICATION";
case KEY_GESTURE_TYPE_ACTIVATE_SELECT_TO_SPEAK:
return "KEY_GESTURE_TYPE_ACTIVATE_SELECT_TO_SPEAK";
+ case KEY_GESTURE_TYPE_MAXIMIZE_FREEFORM_WINDOW:
+ return "KEY_GESTURE_TYPE_MAXIMIZE_FREEFORM_WINDOW";
default:
return Integer.toHexString(value);
}
diff --git a/core/java/android/hardware/input/input_framework.aconfig b/core/java/android/hardware/input/input_framework.aconfig
index a8eb11d88aa48ec2254fc0edeaf1e596a31e5266..fee074901c10f8f1593c58d1fb74f59fa5cb1c56 100644
--- a/core/java/android/hardware/input/input_framework.aconfig
+++ b/core/java/android/hardware/input/input_framework.aconfig
@@ -153,8 +153,8 @@ flag {
flag {
name: "override_power_key_behavior_in_focused_window"
- namespace: "input_native"
- description: "Allows privileged focused windows to capture power key events."
+ namespace: "wallet_integration"
+ description: "Allows privileged focused windows to override the power key double tap behavior."
bug: "357144512"
}
@@ -170,4 +170,11 @@ flag {
namespace: "input"
description: "Adds key gestures for talkback and magnifier"
bug: "375277034"
-}
\ No newline at end of file
+}
+
+flag {
+ name: "can_window_override_power_gesture_api"
+ namespace: "wallet_integration"
+ description: "Adds new API in WindowManager class to check if the window can override the power key double tap behavior."
+ bug: "378736024"
+ }
\ No newline at end of file
diff --git a/core/java/android/hardware/lights/Light.java b/core/java/android/hardware/lights/Light.java
index 163f9fa83fe22dbf6d8561a1cb117542939c0381..38f34e961ec0443c32cd4fdf481cc1dd1a4b5728 100644
--- a/core/java/android/hardware/lights/Light.java
+++ b/core/java/android/hardware/lights/Light.java
@@ -70,6 +70,12 @@ public final class Light implements Parcelable {
*/
public static final int LIGHT_TYPE_KEYBOARD_MIC_MUTE = 10004;
+ /**
+ * Type for keyboard volume mute light.
+ * @hide
+ */
+ public static final int LIGHT_TYPE_KEYBOARD_VOLUME_MUTE = 10005;
+
/**
* Capability for lights that could adjust its LED brightness. If the capability is not present
* the LED can only be turned either on or off.
@@ -99,6 +105,7 @@ public final class Light implements Parcelable {
LIGHT_TYPE_PLAYER_ID,
LIGHT_TYPE_KEYBOARD_BACKLIGHT,
LIGHT_TYPE_KEYBOARD_MIC_MUTE,
+ LIGHT_TYPE_KEYBOARD_VOLUME_MUTE,
})
public @interface LightType {}
diff --git a/core/java/android/hardware/location/ContextHubManager.java b/core/java/android/hardware/location/ContextHubManager.java
index 494bfc92638426c57d9c2b4f72ece47d1c4d3c25..426cd69f76a0a245c11c640952170f5fcb8ef921 100644
--- a/core/java/android/hardware/location/ContextHubManager.java
+++ b/core/java/android/hardware/location/ContextHubManager.java
@@ -34,6 +34,11 @@ import android.chre.flags.Flags;
import android.content.Context;
import android.content.pm.PackageManager;
import android.hardware.contexthub.ErrorCode;
+import android.hardware.contexthub.HubDiscoveryInfo;
+import android.hardware.contexthub.HubEndpoint;
+import android.hardware.contexthub.HubEndpointInfo;
+import android.hardware.contexthub.HubServiceInfo;
+import android.hardware.contexthub.IHubEndpointLifecycleCallback;
import android.os.Handler;
import android.os.HandlerExecutor;
import android.os.Looper;
@@ -42,6 +47,7 @@ import android.util.Log;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.Executor;
@@ -678,6 +684,65 @@ public final class ContextHubManager {
return transaction;
}
+ /**
+ * Find a list of endpoints that matches a specific ID.
+ *
+ * @param endpointId Statically generated ID for an endpoint.
+ * @return A list of {@link HubDiscoveryInfo} objects that represents the result of discovery.
+ */
+ @FlaggedApi(Flags.FLAG_OFFLOAD_API)
+ @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB)
+ @NonNull
+ public List findEndpoints(long endpointId) {
+ // TODO(b/379323274): Consider improving these getters to avoid racing with nano app load
+ // timing.
+ try {
+ List endpointInfos = mService.findEndpoints(endpointId);
+ List results = new ArrayList<>(endpointInfos.size());
+ // Wrap with result type
+ for (HubEndpointInfo endpointInfo : endpointInfos) {
+ results.add(new HubDiscoveryInfo(endpointInfo));
+ }
+ return results;
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Find a list of endpoints that provides a specific service.
+ *
+ * @param serviceDescriptor Statically generated ID for an endpoint.
+ * @return A list of {@link HubDiscoveryInfo} objects that represents the result of discovery.
+ * @throws IllegalArgumentException if the serviceDescriptor is empty/null.
+ */
+ @FlaggedApi(Flags.FLAG_OFFLOAD_API)
+ @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB)
+ @NonNull
+ public List findEndpoints(@NonNull String serviceDescriptor) {
+ // TODO(b/379323274): Consider improving these getters to avoid racing with nano app load
+ // timing.
+ if (serviceDescriptor.isBlank()) {
+ throw new IllegalArgumentException("Invalid service descriptor: " + serviceDescriptor);
+ }
+ try {
+ List endpointInfos =
+ mService.findEndpointsWithService(serviceDescriptor);
+ List results = new ArrayList<>(endpointInfos.size());
+ // Wrap with result type
+ for (HubEndpointInfo endpointInfo : endpointInfos) {
+ for (HubServiceInfo serviceInfo : endpointInfo.getServiceInfoCollection()) {
+ if (serviceInfo.getServiceDescriptor().equals(serviceDescriptor)) {
+ results.add(new HubDiscoveryInfo(endpointInfo, serviceInfo));
+ }
+ }
+ }
+ return results;
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
/**
* Set a callback to receive messages from the context hub
*
@@ -1009,6 +1074,80 @@ public final class ContextHubManager {
return createClient(null /* context */, hubInfo, pendingIntent, nanoAppId);
}
+ /**
+ * Registers an endpoint and its callback with the Context Hub Service.
+ *
+ * An endpoint is registered with the Context Hub Service and published to the HAL. When the
+ * registration succeeds, the endpoint can receive notifications through the provided callback.
+ *
+ * @param hubEndpoint {@link HubEndpoint} object created by {@link HubEndpoint.Builder}
+ */
+ @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB)
+ @FlaggedApi(Flags.FLAG_OFFLOAD_API)
+ public void registerEndpoint(@NonNull HubEndpoint hubEndpoint) {
+ hubEndpoint.register(mService);
+ }
+
+ /**
+ * Use a registered endpoint to connect to another endpoint (destination) without specifying a
+ * service.
+ *
+ *
Context Hub Service will create the endpoint session and notify the registered endpoint.
+ * The registered endpoint will receive callbacks on its {@link IHubEndpointLifecycleCallback}
+ * object regarding the lifecycle events of the session.
+ *
+ * @param hubEndpoint {@link HubEndpoint} object previously registered via {@link
+ * ContextHubManager#registerEndpoint(HubEndpoint)}.
+ * @param destination {@link HubEndpointInfo} object that represents an endpoint from previous
+ * endpoint discovery results (e.g. from {@link ContextHubManager#findEndpoints(long)}).
+ */
+ @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB)
+ @FlaggedApi(Flags.FLAG_OFFLOAD_API)
+ public void openSession(
+ @NonNull HubEndpoint hubEndpoint, @NonNull HubEndpointInfo destination) {
+ hubEndpoint.openSession(destination, null);
+ }
+
+ /**
+ * Use a registered endpoint to connect to another endpoint (destination) for a service
+ * described by a {@link HubServiceInfo} object.
+ *
+ *
Context Hub Service will create the endpoint session and notify the registered endpoint.
+ * The registered endpoint will receive callbacks on its {@link IHubEndpointLifecycleCallback}
+ * object regarding the lifecycle events of the session.
+ *
+ * @param hubEndpoint {@link HubEndpoint} object previously registered via {@link
+ * ContextHubManager#registerEndpoint(HubEndpoint)}.
+ * @param destination {@link HubEndpointInfo} object that represents an endpoint from previous
+ * endpoint discovery results (e.g. from {@link ContextHubManager#findEndpoints(long)}).
+ * @param serviceInfo {@link HubServiceInfo} object that describes the service associated with
+ * this session. The information will be sent to the destination as part of open request.
+ */
+ @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB)
+ @FlaggedApi(Flags.FLAG_OFFLOAD_API)
+ public void openSession(
+ @NonNull HubEndpoint hubEndpoint,
+ @NonNull HubEndpointInfo destination,
+ @NonNull HubServiceInfo serviceInfo) {
+ hubEndpoint.openSession(destination, serviceInfo);
+ }
+
+ /**
+ * Unregisters an endpoint and its callback with the Context Hub Service.
+ *
+ *
An endpoint is unregistered from the HAL. The endpoint object will no longer receive
+ * notification through the provided callback.
+ *
+ * @param hubEndpoint {@link HubEndpoint} object created by {@link HubEndpoint.Builder}. This
+ * should match a previously registered object via {@link
+ * ContextHubManager#registerEndpoint(HubEndpoint)}.
+ */
+ @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB)
+ @FlaggedApi(Flags.FLAG_OFFLOAD_API)
+ public void unregisterEndpoint(@NonNull HubEndpoint hubEndpoint) {
+ hubEndpoint.unregister();
+ }
+
/**
* Queries for the list of preloaded nanoapp IDs on the system.
*
@@ -1168,6 +1307,7 @@ public final class ContextHubManager {
requireNonNull(mainLooper, "mainLooper cannot be null");
mService = service;
mMainLooper = mainLooper;
+
try {
mService.registerCallback(mClientCallback);
} catch (RemoteException e) {
diff --git a/core/java/android/hardware/location/ContextHubTransaction.java b/core/java/android/hardware/location/ContextHubTransaction.java
index bd87b5cb6d5431d06961cf0083d3d289d66d5a1a..ee55f81bb2a7308961fc5d6cc21d2923ca15d95a 100644
--- a/core/java/android/hardware/location/ContextHubTransaction.java
+++ b/core/java/android/hardware/location/ContextHubTransaction.java
@@ -51,18 +51,23 @@ public class ContextHubTransaction {
/**
* Constants describing the type of a transaction through the Context Hub Service.
- * {@hide}
+ *
+ * @hide
*/
@Retention(RetentionPolicy.SOURCE)
- @IntDef(prefix = { "TYPE_" }, value = {
- TYPE_LOAD_NANOAPP,
- TYPE_UNLOAD_NANOAPP,
- TYPE_ENABLE_NANOAPP,
- TYPE_DISABLE_NANOAPP,
- TYPE_QUERY_NANOAPPS,
- TYPE_RELIABLE_MESSAGE,
- })
- public @interface Type { }
+ @IntDef(
+ prefix = {"TYPE_"},
+ value = {
+ TYPE_LOAD_NANOAPP,
+ TYPE_UNLOAD_NANOAPP,
+ TYPE_ENABLE_NANOAPP,
+ TYPE_DISABLE_NANOAPP,
+ TYPE_QUERY_NANOAPPS,
+ TYPE_RELIABLE_MESSAGE,
+ TYPE_HUB_MESSAGE_DEFAULT,
+ TYPE_HUB_MESSAGE_REQUIRES_RESPONSE,
+ })
+ public @interface Type {}
public static final int TYPE_LOAD_NANOAPP = 0;
public static final int TYPE_UNLOAD_NANOAPP = 1;
@@ -71,24 +76,34 @@ public class ContextHubTransaction {
public static final int TYPE_QUERY_NANOAPPS = 4;
public static final int TYPE_RELIABLE_MESSAGE = 5;
+ @FlaggedApi(Flags.FLAG_OFFLOAD_API)
+ public static final int TYPE_HUB_MESSAGE_DEFAULT = 6;
+
+ @FlaggedApi(Flags.FLAG_OFFLOAD_API)
+ public static final int TYPE_HUB_MESSAGE_REQUIRES_RESPONSE = 7;
+
/**
* Constants describing the result of a transaction or request through the Context Hub Service.
- * {@hide}
+ *
+ * @hide
*/
@Retention(RetentionPolicy.SOURCE)
- @IntDef(prefix = { "RESULT_" }, value = {
- RESULT_SUCCESS,
- RESULT_FAILED_UNKNOWN,
- RESULT_FAILED_BAD_PARAMS,
- RESULT_FAILED_UNINITIALIZED,
- RESULT_FAILED_BUSY,
- RESULT_FAILED_AT_HUB,
- RESULT_FAILED_TIMEOUT,
- RESULT_FAILED_SERVICE_INTERNAL_FAILURE,
- RESULT_FAILED_HAL_UNAVAILABLE,
- RESULT_FAILED_NOT_SUPPORTED,
- })
+ @IntDef(
+ prefix = {"RESULT_"},
+ value = {
+ RESULT_SUCCESS,
+ RESULT_FAILED_UNKNOWN,
+ RESULT_FAILED_BAD_PARAMS,
+ RESULT_FAILED_UNINITIALIZED,
+ RESULT_FAILED_BUSY,
+ RESULT_FAILED_AT_HUB,
+ RESULT_FAILED_TIMEOUT,
+ RESULT_FAILED_SERVICE_INTERNAL_FAILURE,
+ RESULT_FAILED_HAL_UNAVAILABLE,
+ RESULT_FAILED_NOT_SUPPORTED,
+ })
public @interface Result {}
+
public static final int RESULT_SUCCESS = 0;
/**
* Generic failure mode.
@@ -143,7 +158,8 @@ public class ContextHubTransaction {
*/
private R mContents;
- Response(@ContextHubTransaction.Result int result, R contents) {
+ /** @hide */
+ public Response(@ContextHubTransaction.Result int result, R contents) {
mResult = result;
mContents = contents;
}
@@ -206,7 +222,8 @@ public class ContextHubTransaction {
*/
private boolean mIsResponseSet = false;
- ContextHubTransaction(@Type int type) {
+ /** @hide */
+ public ContextHubTransaction(@Type int type) {
mTransactionType = type;
}
@@ -338,16 +355,16 @@ public class ContextHubTransaction {
/**
* Sets the response of the transaction.
*
- * This method should only be invoked by ContextHubManager as a result of a callback from
- * the Context Hub Service indicating the response from a transaction. This method should not be
+ * This method should only be invoked by ContextHubManager as a result of a callback from the
+ * Context Hub Service indicating the response from a transaction. This method should not be
* invoked more than once.
*
* @param response the response to set
- *
* @throws IllegalStateException if this method is invoked multiple times
* @throws NullPointerException if the response is null
+ * @hide
*/
- /* package */ void setResponse(ContextHubTransaction.Response response) {
+ public void setResponse(ContextHubTransaction.Response response) {
synchronized (this) {
Objects.requireNonNull(response, "Response cannot be null");
if (mIsResponseSet) {
diff --git a/core/java/android/hardware/location/IContextHubService.aidl b/core/java/android/hardware/location/IContextHubService.aidl
index b0cc763dc8fd1615a12fb6c88a257e0ee12eaf51..f9f41244603880e7ca58372c3b216854e5e5a3da 100644
--- a/core/java/android/hardware/location/IContextHubService.aidl
+++ b/core/java/android/hardware/location/IContextHubService.aidl
@@ -18,17 +18,20 @@ package android.hardware.location;
// Declare any non-default types here with import statements
import android.app.PendingIntent;
-import android.hardware.location.HubInfo;
+import android.hardware.contexthub.HubEndpointInfo;
+import android.hardware.contexthub.IContextHubEndpoint;
+import android.hardware.contexthub.IContextHubEndpointCallback;
import android.hardware.location.ContextHubInfo;
import android.hardware.location.ContextHubMessage;
-import android.hardware.location.NanoApp;
-import android.hardware.location.NanoAppBinary;
-import android.hardware.location.NanoAppFilter;
-import android.hardware.location.NanoAppInstanceInfo;
+import android.hardware.location.HubInfo;
import android.hardware.location.IContextHubCallback;
import android.hardware.location.IContextHubClient;
import android.hardware.location.IContextHubClientCallback;
import android.hardware.location.IContextHubTransactionCallback;
+import android.hardware.location.NanoApp;
+import android.hardware.location.NanoAppBinary;
+import android.hardware.location.NanoAppFilter;
+import android.hardware.location.NanoAppInstanceInfo;
/**
* @hide
@@ -122,4 +125,16 @@ interface IContextHubService {
// Enables or disables test mode
@EnforcePermission("ACCESS_CONTEXT_HUB")
boolean setTestMode(in boolean enable);
+
+ // Finds all endpoints that has a specific ID
+ @EnforcePermission("ACCESS_CONTEXT_HUB")
+ List findEndpoints(long endpointId);
+
+ // Finds all endpoints that has a specific service
+ @EnforcePermission("ACCESS_CONTEXT_HUB")
+ List findEndpointsWithService(String service);
+
+ // Register an endpoint with the context hub
+ @EnforcePermission("ACCESS_CONTEXT_HUB")
+ IContextHubEndpoint registerEndpoint(in HubEndpointInfo pendingEndpointInfo, in IContextHubEndpointCallback callback);
}
diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java
index 92608d048135185acacd805193e364e085f52f64..d2e232a946222cdc2a525ca1d20fad95e1cb983f 100644
--- a/core/java/android/hardware/usb/UsbManager.java
+++ b/core/java/android/hardware/usb/UsbManager.java
@@ -54,6 +54,11 @@ import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
@@ -823,6 +828,216 @@ public class UsbManager {
}
}
+ /**
+ * Opens the handle for accessory, marks it as input or output, and adds it to the map
+ * if it is the first time the accessory has had an I/O stream associated with it.
+ */
+ private AccessoryHandle openHandleForAccessory(UsbAccessory accessory,
+ boolean openingInputStream)
+ throws RemoteException {
+ synchronized (mAccessoryHandleMapLock) {
+ if (mAccessoryHandleMap == null) {
+ mAccessoryHandleMap = new ArrayMap<>();
+ }
+
+ // If accessory isn't available in map
+ if (!mAccessoryHandleMap.containsKey(accessory)) {
+ // open accessory and store associated AccessoryHandle in map
+ ParcelFileDescriptor pfd = mService.openAccessory(accessory);
+ AccessoryHandle newHandle = new AccessoryHandle(pfd, openingInputStream,
+ !openingInputStream);
+ mAccessoryHandleMap.put(accessory, newHandle);
+
+ return newHandle;
+ }
+
+ // if accessory is already in map, get modified handle
+ AccessoryHandle currentHandle = mAccessoryHandleMap.get(accessory);
+ if (currentHandle == null) {
+ throw new IllegalStateException("Accessory doesn't have an associated handle yet!");
+ }
+
+ AccessoryHandle modifiedHandle = getModifiedHandleForOpeningStream(
+ openingInputStream, currentHandle);
+
+ mAccessoryHandleMap.put(accessory, modifiedHandle);
+
+ return modifiedHandle;
+ }
+ }
+
+ private AccessoryHandle getModifiedHandleForOpeningStream(boolean openingInputStream,
+ @NonNull AccessoryHandle currentHandle) {
+ if (currentHandle.isInputStreamOpened() && openingInputStream) {
+ throw new IllegalStateException("Input stream already open for this accessory! "
+ + "Please close the existing input stream before opening a new one.");
+ }
+
+ if (currentHandle.isOutputStreamOpened() && !openingInputStream) {
+ throw new IllegalStateException("Output stream already open for this accessory! "
+ + "Please close the existing output stream before opening a new one.");
+ }
+
+ boolean isInputStreamOpened = openingInputStream || currentHandle.isInputStreamOpened();
+ boolean isOutputStreamOpened = !openingInputStream || currentHandle.isOutputStreamOpened();
+
+ return new AccessoryHandle(
+ currentHandle.getPfd(), isInputStreamOpened, isOutputStreamOpened);
+ }
+
+ /**
+ * Marks the handle for the given accessory closed for input or output, and closes the handle
+ * and removes it from the map if there are no more I/O streams associated with the handle.
+ */
+ private void closeHandleForAccessory(UsbAccessory accessory, boolean closingInputStream)
+ throws IOException {
+ synchronized (mAccessoryHandleMapLock) {
+ AccessoryHandle currentHandle = mAccessoryHandleMap.get(accessory);
+
+ if (currentHandle == null) {
+ throw new IllegalStateException(
+ "No handle has been initialised for this accessory!");
+ }
+
+ AccessoryHandle modifiedHandle = getModifiedHandleForClosingStream(
+ closingInputStream, currentHandle);
+ if (!modifiedHandle.isOpen()) {
+ //close handle and remove accessory handle pair from map
+ modifiedHandle.getPfd().close();
+ mAccessoryHandleMap.remove(accessory);
+ } else {
+ mAccessoryHandleMap.put(accessory, modifiedHandle);
+ }
+ }
+ }
+
+ private AccessoryHandle getModifiedHandleForClosingStream(boolean closingInputStream,
+ @NonNull AccessoryHandle currentHandle) {
+ if (!currentHandle.isInputStreamOpened() && closingInputStream) {
+ throw new IllegalStateException(
+ "Attempting to close an input stream that has not been opened "
+ + "for this accessory!");
+ }
+
+ if (!currentHandle.isOutputStreamOpened() && !closingInputStream) {
+ throw new IllegalStateException(
+ "Attempting to close an output stream that has not been opened "
+ + "for this accessory!");
+ }
+
+ boolean isInputStreamOpened = !closingInputStream && currentHandle.isInputStreamOpened();
+ boolean isOutputStreamOpened = closingInputStream && currentHandle.isOutputStreamOpened();
+
+ return new AccessoryHandle(
+ currentHandle.getPfd(), isInputStreamOpened, isOutputStreamOpened);
+ }
+
+ /**
+ * An InputStream you can create on a UsbAccessory, which will
+ * take care of calling {@link ParcelFileDescriptor#close
+ * ParcelFileDescriptor.close()} for you when the stream is closed.
+ */
+ private class AccessoryAutoCloseInputStream extends FileInputStream {
+
+ private final ParcelFileDescriptor mPfd;
+ private final UsbAccessory mAccessory;
+
+ AccessoryAutoCloseInputStream(UsbAccessory accessory, ParcelFileDescriptor pfd) {
+ super(pfd.getFileDescriptor());
+ this.mAccessory = accessory;
+ this.mPfd = pfd;
+ }
+
+ @Override
+ public void close() throws IOException {
+ /* TODO(b/377850642) : Ensure the stream is closed even if client does not
+ explicitly close the stream to avoid corrupt FDs*/
+ super.close();
+ closeHandleForAccessory(mAccessory, true);
+ }
+
+
+ @Override
+ public int read() throws IOException {
+ final int result = super.read();
+ checkError(result);
+ return result;
+ }
+
+ @Override
+ public int read(byte[] b) throws IOException {
+ final int result = super.read(b);
+ checkError(result);
+ return result;
+ }
+
+ @Override
+ public int read(byte[] b, int off, int len) throws IOException {
+ final int result = super.read(b, off, len);
+ checkError(result);
+ return result;
+ }
+
+ private void checkError(int result) throws IOException {
+ if (result == -1 && mPfd.canDetectErrors()) {
+ mPfd.checkError();
+ }
+ }
+ }
+
+ /**
+ * An OutputStream you can create on a UsbAccessory, which will
+ * take care of calling {@link ParcelFileDescriptor#close
+ * ParcelFileDescriptor.close()} for you when the stream is closed.
+ */
+ private class AccessoryAutoCloseOutputStream extends FileOutputStream {
+ private final UsbAccessory mAccessory;
+
+ AccessoryAutoCloseOutputStream(UsbAccessory accessory, ParcelFileDescriptor pfd) {
+ super(pfd.getFileDescriptor());
+ mAccessory = accessory;
+ }
+
+ @Override
+ public void close() throws IOException {
+ /* TODO(b/377850642) : Ensure the stream is closed even if client does not
+ explicitly close the stream to avoid corrupt FDs*/
+ super.close();
+ closeHandleForAccessory(mAccessory, false);
+ }
+ }
+
+ /**
+ * Holds file descriptor and marks whether input and output streams have been opened for it.
+ */
+ private static class AccessoryHandle {
+ private final ParcelFileDescriptor mPfd;
+ private final boolean mInputStreamOpened;
+ private final boolean mOutputStreamOpened;
+ AccessoryHandle(ParcelFileDescriptor parcelFileDescriptor,
+ boolean inputStreamOpened, boolean outputStreamOpened) {
+ mPfd = parcelFileDescriptor;
+ mInputStreamOpened = inputStreamOpened;
+ mOutputStreamOpened = outputStreamOpened;
+ }
+
+ public ParcelFileDescriptor getPfd() {
+ return mPfd;
+ }
+
+ public boolean isInputStreamOpened() {
+ return mInputStreamOpened;
+ }
+
+ public boolean isOutputStreamOpened() {
+ return mOutputStreamOpened;
+ }
+
+ public boolean isOpen() {
+ return (mInputStreamOpened || mOutputStreamOpened);
+ }
+ }
+
private final Context mContext;
private final IUsbManager mService;
private final Object mDisplayPortListenersLock = new Object();
@@ -831,6 +1046,11 @@ public class UsbManager {
@GuardedBy("mDisplayPortListenersLock")
private DisplayPortAltModeInfoDispatchingListener mDisplayPortServiceListener;
+ private final Object mAccessoryHandleMapLock = new Object();
+ @GuardedBy("mAccessoryHandleMapLock")
+ private ArrayMap mAccessoryHandleMap;
+
+
/**
* @hide
*/
@@ -922,6 +1142,10 @@ public class UsbManager {
* data of a USB transfer should be read at once. If only a partial request is read the rest of
* the transfer is dropped.
*
+ * It is strongly recommended to use newer methods instead of this method,
+ * since this method may provide sub-optimal performance on some devices.
+ * This method could potentially face interim performance degradation as well.
+ *
* @param accessory the USB accessory to open
* @return file descriptor, or null if the accessory could not be opened.
*/
@@ -934,6 +1158,49 @@ public class UsbManager {
}
}
+ /**
+ * Opens an input stream for reading from the USB accessory.
+ * If accessory is not open at this point, accessory will first be opened.
+ *
If data is read from the created {@link java.io.InputStream} all
+ * data of a USB transfer should be read at once. If only a partial request is read, the rest of
+ * the transfer is dropped.
+ *
The caller is responsible for ensuring that the returned stream is closed.
+ *
+ * @param accessory the USB accessory to open an input stream for
+ * @return input stream to read from given USB accessory
+ */
+ @FlaggedApi(Flags.FLAG_ENABLE_ACCESSORY_STREAM_API)
+ @RequiresFeature(PackageManager.FEATURE_USB_ACCESSORY)
+ public @NonNull InputStream openAccessoryInputStream(@NonNull UsbAccessory accessory) {
+ try {
+ return new AccessoryAutoCloseInputStream(accessory,
+ openHandleForAccessory(accessory, true).getPfd());
+
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Opens an output stream for writing to the USB accessory.
+ * If accessory is not open at this point, accessory will first be opened.
+ *
The caller is responsible for ensuring that the returned stream is closed.
+ *
+ * @param accessory the USB accessory to open an output stream for
+ * @return output stream to write to given USB accessory
+ */
+ @FlaggedApi(Flags.FLAG_ENABLE_ACCESSORY_STREAM_API)
+ @RequiresFeature(PackageManager.FEATURE_USB_ACCESSORY)
+ public @NonNull OutputStream openAccessoryOutputStream(@NonNull UsbAccessory accessory) {
+ try {
+ return new AccessoryAutoCloseOutputStream(accessory,
+ openHandleForAccessory(accessory, false).getPfd());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+
+ }
+
/**
* Gets the functionfs control file descriptor for the given function, with
* the usb descriptors and strings already written. The file descriptor is used
@@ -1293,7 +1560,7 @@ public class UsbManager {
*
* This function returns the current USB bandwidth through USB Gadget HAL.
* It should be used when Android device is in USB peripheral mode and
- * connects to a USB host. If USB state is not configued, API will return
+ * connects to a USB host. If USB state is not configured, API will return
* {@value #USB_DATA_TRANSFER_RATE_UNKNOWN}. In addition, the unit of the
* return value is Mbps.
*
diff --git a/core/java/android/hardware/usb/flags/usb_framework_flags.aconfig b/core/java/android/hardware/usb/flags/usb_framework_flags.aconfig
index 3b7a9e95c52177d04e1f4545dc67c2169f315e98..b719a7c6daacede3ffcb0ec684417324d179c161 100644
--- a/core/java/android/hardware/usb/flags/usb_framework_flags.aconfig
+++ b/core/java/android/hardware/usb/flags/usb_framework_flags.aconfig
@@ -31,3 +31,11 @@ flag {
description: "Feature flag to enable exposing usb speed system api"
bug: "373653182"
}
+
+flag {
+ name: "enable_accessory_stream_api"
+ is_exported: true
+ namespace: "usb"
+ description: "Feature flag to enable stream APIs for Accessory mode"
+ bug: "369356693"
+}
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 8c3f0ef080392109c4e015d0a7ff22e37ee9f0d1..dadb5c386b76965ccdc41ef1f896c7fc3474e0e2 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -55,6 +55,7 @@ import static android.view.inputmethod.ConnectionlessHandwritingCallback.CONNECT
import static android.view.inputmethod.ConnectionlessHandwritingCallback.CONNECTIONLESS_HANDWRITING_ERROR_OTHER;
import static android.view.inputmethod.ConnectionlessHandwritingCallback.CONNECTIONLESS_HANDWRITING_ERROR_UNSUPPORTED;
import static android.view.inputmethod.Flags.FLAG_CONNECTIONLESS_HANDWRITING;
+import static android.view.inputmethod.Flags.FLAG_IME_SWITCHER_REVAMP_API;
import static android.view.inputmethod.Flags.ctrlShiftShortcut;
import static android.view.inputmethod.Flags.predictiveBackIme;
@@ -3436,7 +3437,7 @@ public class InputMethodService extends AbstractInputMethodService {
initialize();
mInlineSuggestionSessionController.notifyOnStartInput(
editorInfo == null ? null : editorInfo.packageName,
- editorInfo == null ? null : editorInfo.autofillId);
+ editorInfo == null ? null : editorInfo.getAutofillId());
if (DEBUG) Log.v(TAG, "CALL: onStartInput");
onStartInput(editorInfo, restarting);
if (mDecorViewVisible) {
@@ -4391,6 +4392,39 @@ public class InputMethodService extends AbstractInputMethodService {
return mNavigationBarController.isShown();
}
+ /**
+ * Called when the requested visibility of a custom IME Switcher button changes.
+ *
+ * When the system provides an IME navigation bar, it may decide to show an IME Switcher
+ * button inside this bar. However, the IME can request hiding the bar provided by the system
+ * with {@code getWindowInsetsController().hide(captionBar())} (the IME navigation bar provides
+ * {@link Type#captionBar() captionBar} insets to the IME window). If the request is successful,
+ * then it becomes the IME's responsibility to provide a custom IME Switcher button in its
+ * input view, with equivalent functionality.
+ *
+ * This custom button is only requested to be visible when the system provides the IME
+ * navigation bar, both the bar and the IME Switcher button inside it should be visible,
+ * but the IME successfully requested to hide the bar. This does not depend on the current
+ * visibility of the IME. It could be called with {@code true} while the IME is hidden, in
+ * which case the IME should prepare to show the button as soon as the IME itself is shown.
+ *
+ * This is only called when the requested visibility changes. The default value is
+ * {@code false} and as such, this will not be called initially if the resulting value is
+ * {@code false}.
+ *
+ * This can be called at any time after {@link #onCreate}, even if the IME is not currently
+ * visible. However, this is not guaranteed to be called before the IME is shown, as it depends
+ * on when the IME requested hiding the IME navigation bar. If the request is sent during
+ * the showing flow (e.g. during {@link #onStartInputView}), this will be called shortly after
+ * {@link #onWindowShown}, but before the first IME frame is drawn.
+ *
+ * @param visible whether the button is requested visible or not.
+ */
+ @FlaggedApi(FLAG_IME_SWITCHER_REVAMP_API)
+ public void onCustomImeSwitcherButtonRequestedVisible(boolean visible) {
+ // Intentionally empty
+ }
+
/**
* Called when the IME switch button was clicked from the client. Depending on the number of
* enabled IME subtypes, this will either switch to the next IME/subtype, or show the input
diff --git a/core/java/android/inputmethodservice/NavigationBarController.java b/core/java/android/inputmethodservice/NavigationBarController.java
index b08454dd7f8fc5a938c7530436e454c8b19c939c..38be8d9f772df1eee3a362f913a3205d4cfbee46 100644
--- a/core/java/android/inputmethodservice/NavigationBarController.java
+++ b/core/java/android/inputmethodservice/NavigationBarController.java
@@ -41,6 +41,7 @@ import android.view.WindowInsets;
import android.view.WindowInsetsController.Appearance;
import android.view.animation.Interpolator;
import android.view.animation.PathInterpolator;
+import android.view.inputmethod.Flags;
import android.view.inputmethod.InputMethodManager;
import android.widget.FrameLayout;
@@ -178,6 +179,9 @@ final class NavigationBarController {
private boolean mDrawLegacyNavigationBarBackground;
+ /** Whether a custom IME Switcher button should be visible. */
+ private boolean mCustomImeSwitcherVisible;
+
private final Rect mTempRect = new Rect();
private final int[] mTempPos = new int[2];
@@ -265,6 +269,7 @@ final class NavigationBarController {
// IME navigation bar.
boolean visible = insets.isVisible(captionBar());
mNavigationBarFrame.setVisibility(visible ? View.VISIBLE : View.GONE);
+ checkCustomImeSwitcherVisibility();
}
return view.onApplyWindowInsets(insets);
});
@@ -491,6 +496,8 @@ final class NavigationBarController {
mShouldShowImeSwitcherWhenImeIsShown;
mShouldShowImeSwitcherWhenImeIsShown = shouldShowImeSwitcherWhenImeIsShown;
+ checkCustomImeSwitcherVisibility();
+
mService.mWindow.getWindow().getDecorView().getWindowInsetsController()
.setImeCaptionBarInsetsHeight(getImeCaptionBarHeight(imeDrawsImeNavBar));
@@ -616,12 +623,33 @@ final class NavigationBarController {
&& mNavigationBarFrame.getVisibility() == View.VISIBLE;
}
+ /**
+ * Checks if a custom IME Switcher button should be visible, and notifies the IME when this
+ * state changes. This can only be {@code true} if three conditions are met:
+ *
+ * The IME should draw the IME navigation bar.
+ * The IME Switcher button should be visible when the IME is visible.
+ * The IME navigation bar should be visible, but was requested hidden by the IME.
+ */
+ private void checkCustomImeSwitcherVisibility() {
+ if (!Flags.imeSwitcherRevampApi()) {
+ return;
+ }
+ final boolean visible = mImeDrawsImeNavBar && mShouldShowImeSwitcherWhenImeIsShown
+ && mNavigationBarFrame != null && !isShown();
+ if (visible != mCustomImeSwitcherVisible) {
+ mCustomImeSwitcherVisible = visible;
+ mService.onCustomImeSwitcherButtonRequestedVisible(mCustomImeSwitcherVisible);
+ }
+ }
+
@Override
public String toDebugString() {
return "{mImeDrawsImeNavBar=" + mImeDrawsImeNavBar
+ " mNavigationBarFrame=" + mNavigationBarFrame
+ " mShouldShowImeSwitcherWhenImeIsShown="
+ mShouldShowImeSwitcherWhenImeIsShown
+ + " mCustomImeSwitcherVisible=" + mCustomImeSwitcherVisible
+ " mAppearance=0x" + Integer.toHexString(mAppearance)
+ " mDarkIntensity=" + mDarkIntensity
+ " mDrawLegacyNavigationBarBackground=" + mDrawLegacyNavigationBarBackground
diff --git a/core/java/android/net/vcn/VcnFrameworkInitializer.java b/core/java/android/net/ConnectivityFrameworkInitializerBaklava.java
similarity index 87%
rename from core/java/android/net/vcn/VcnFrameworkInitializer.java
rename to core/java/android/net/ConnectivityFrameworkInitializerBaklava.java
index 8cb213b306beae5e58b5984ceab1634cac315a9e..1f0fa92d79769a4d40ea548bfdab5ae9c4c66a39 100644
--- a/core/java/android/net/vcn/VcnFrameworkInitializer.java
+++ b/core/java/android/net/ConnectivityFrameworkInitializerBaklava.java
@@ -14,15 +14,21 @@
* limitations under the License.
*/
-package android.net.vcn;
+package android.net;
+import static android.net.vcn.Flags.FLAG_MAINLINE_VCN_MODULE_API;
+
+import android.annotation.FlaggedApi;
import android.annotation.Nullable;
+import android.annotation.SystemApi;
import android.app.SystemServiceRegistry;
import android.compat.Compatibility;
import android.compat.annotation.ChangeId;
import android.compat.annotation.EnabledSince;
import android.content.Context;
import android.content.pm.PackageManager;
+import android.net.vcn.IVcnManagementService;
+import android.net.vcn.VcnManager;
import android.os.Build;
import android.os.SystemProperties;
@@ -31,8 +37,9 @@ import android.os.SystemProperties;
*
* @hide
*/
-// TODO: Expose it as @SystemApi(client = MODULE_LIBRARIES)
-public final class VcnFrameworkInitializer {
+@FlaggedApi(FLAG_MAINLINE_VCN_MODULE_API)
+@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+public final class ConnectivityFrameworkInitializerBaklava {
/**
* Starting with {@link VANILLA_ICE_CREAM}, Telephony feature flags (e.g. {@link
* PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}) are being checked before returning managers
@@ -55,7 +62,7 @@ public final class VcnFrameworkInitializer {
*/
private static final int VENDOR_API_FOR_ANDROID_V = 202404;
- private VcnFrameworkInitializer() {}
+ private ConnectivityFrameworkInitializerBaklava() {}
// Suppressing AndroidFrameworkCompatChange because we're querying vendor
// partition SDK level, not application's target SDK version (which BTW we
@@ -86,7 +93,10 @@ public final class VcnFrameworkInitializer {
*
* @throws IllegalStateException if this is called anywhere besides {@link
* SystemServiceRegistry}.
+ * @hide
*/
+ @FlaggedApi(FLAG_MAINLINE_VCN_MODULE_API)
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public static void registerServiceWrappers() {
SystemServiceRegistry.registerContextAwareService(
VcnManager.VCN_MANAGEMENT_SERVICE_STRING,
diff --git a/core/java/android/net/vcn/VcnGatewayConnectionConfig.java b/core/java/android/net/vcn/VcnGatewayConnectionConfig.java
index af93c964a8baaf89aed3542d3f304ce18b1b1e45..3219ce81c25691e78e266534a5b526b2a71fee3e 100644
--- a/core/java/android/net/vcn/VcnGatewayConnectionConfig.java
+++ b/core/java/android/net/vcn/VcnGatewayConnectionConfig.java
@@ -16,6 +16,7 @@
package android.net.vcn;
import static android.net.ipsec.ike.IkeSessionParams.IKE_OPTION_MOBIKE;
+import static android.net.vcn.Flags.FLAG_MAINLINE_VCN_MODULE_API;
import static android.net.vcn.Flags.FLAG_SAFE_MODE_CONFIG;
import static android.net.vcn.VcnUnderlyingNetworkTemplate.MATCH_REQUIRED;
@@ -82,7 +83,15 @@ import java.util.concurrent.TimeUnit;
*
*/
public final class VcnGatewayConnectionConfig {
- /** @hide */
+ /**
+ * Minimum NAT timeout not set.
+ *
+ * When the timeout is not set, the device will automatically choose a keepalive interval and
+ * may reduce the keepalive frequency for power-optimization.
+ */
+ @FlaggedApi(FLAG_MAINLINE_VCN_MODULE_API)
+ // This constant does not represent a minimum value. It indicates the value is not configured.
+ @SuppressLint("MinMaxConstant")
public static final int MIN_UDP_PORT_4500_NAT_TIMEOUT_UNSET = -1;
/** @hide */
@@ -773,7 +782,7 @@ public final class VcnGatewayConnectionConfig {
*
* @param minUdpPort4500NatTimeoutSeconds the maximum keepalive timeout supported by the VCN
* Gateway Connection, generally the minimum duration a NAT mapping is cached on the VCN
- * Gateway.
+ * Gateway; or {@link MIN_UDP_PORT_4500_NAT_TIMEOUT_UNSET} to clear this value.
* @return this {@link Builder} instance, for chaining
*/
@NonNull
@@ -781,8 +790,10 @@ public final class VcnGatewayConnectionConfig {
@IntRange(from = MIN_UDP_PORT_4500_NAT_TIMEOUT_SECONDS)
int minUdpPort4500NatTimeoutSeconds) {
Preconditions.checkArgument(
- minUdpPort4500NatTimeoutSeconds >= MIN_UDP_PORT_4500_NAT_TIMEOUT_SECONDS,
- "Timeout must be at least 120s");
+ minUdpPort4500NatTimeoutSeconds == MIN_UDP_PORT_4500_NAT_TIMEOUT_UNSET
+ || minUdpPort4500NatTimeoutSeconds
+ >= MIN_UDP_PORT_4500_NAT_TIMEOUT_SECONDS,
+ "Timeout must be at least 120s or MIN_UDP_PORT_4500_NAT_TIMEOUT_UNSET");
mMinUdpPort4500NatTimeoutSeconds = minUdpPort4500NatTimeoutSeconds;
return this;
diff --git a/core/java/android/net/vcn/VcnTransportInfo.java b/core/java/android/net/vcn/VcnTransportInfo.java
index 1fc91eea313880414abab20ebcde8354c964ab1a..3638429f33fba9ee512dbfd777ec37b89da7ddec 100644
--- a/core/java/android/net/vcn/VcnTransportInfo.java
+++ b/core/java/android/net/vcn/VcnTransportInfo.java
@@ -17,13 +17,16 @@
package android.net.vcn;
import static android.net.NetworkCapabilities.REDACT_FOR_NETWORK_SETTINGS;
+import static android.net.vcn.Flags.FLAG_MAINLINE_VCN_MODULE_API;
import static android.net.vcn.VcnGatewayConnectionConfig.MIN_UDP_PORT_4500_NAT_TIMEOUT_SECONDS;
import static android.net.vcn.VcnGatewayConnectionConfig.MIN_UDP_PORT_4500_NAT_TIMEOUT_UNSET;
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+import android.annotation.FlaggedApi;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SystemApi;
import android.net.NetworkCapabilities;
import android.net.TransportInfo;
import android.net.wifi.WifiInfo;
@@ -52,23 +55,29 @@ import java.util.Objects;
* @hide
*/
// TODO: Do not store WifiInfo and subscription ID in VcnTransportInfo anymore
-public class VcnTransportInfo implements TransportInfo, Parcelable {
+@FlaggedApi(FLAG_MAINLINE_VCN_MODULE_API)
+@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+public final class VcnTransportInfo implements TransportInfo, Parcelable {
@Nullable private final WifiInfo mWifiInfo;
private final int mSubId;
private final int mMinUdpPort4500NatTimeoutSeconds;
+ /** @hide */
public VcnTransportInfo(@NonNull WifiInfo wifiInfo) {
this(wifiInfo, INVALID_SUBSCRIPTION_ID, MIN_UDP_PORT_4500_NAT_TIMEOUT_UNSET);
}
+ /** @hide */
public VcnTransportInfo(@NonNull WifiInfo wifiInfo, int minUdpPort4500NatTimeoutSeconds) {
this(wifiInfo, INVALID_SUBSCRIPTION_ID, minUdpPort4500NatTimeoutSeconds);
}
+ /** @hide */
public VcnTransportInfo(int subId) {
this(null /* wifiInfo */, subId, MIN_UDP_PORT_4500_NAT_TIMEOUT_UNSET);
}
+ /** @hide */
public VcnTransportInfo(int subId, int minUdpPort4500NatTimeoutSeconds) {
this(null /* wifiInfo */, subId, minUdpPort4500NatTimeoutSeconds);
}
@@ -86,6 +95,7 @@ public class VcnTransportInfo implements TransportInfo, Parcelable {
*
If the underlying Network for the associated VCN is Cellular, returns null.
*
* @return the WifiInfo if there is an underlying WiFi connection, else null.
+ * @hide
*/
@Nullable
public WifiInfo getWifiInfo() {
@@ -100,17 +110,27 @@ public class VcnTransportInfo implements TransportInfo, Parcelable {
*
* @return the Subscription ID if a cellular underlying Network is present, else {@link
* android.telephony.SubscriptionManager#INVALID_SUBSCRIPTION_ID}.
+ * @hide
*/
public int getSubId() {
return mSubId;
}
/**
- * Get the VCN provided UDP port 4500 NAT timeout
+ * Get the minimum duration that the VCN Gateway guarantees to preserve a NAT mapping.
*
- * @return the UDP 4500 NAT timeout, or
+ *
To ensure uninterrupted connectivity, the device must send keepalive packets before the
+ * timeout. Failure to do so may result in the mapping being cleared and connection termination.
+ * This value is used as a power-optimization hint for other IKEv2/IPsec use cases (e.g. VPNs,
+ * or IWLAN) to reduce the necessary keepalive frequency, thus conserving power and data.
+ *
+ * @return the minimum duration that the VCN Gateway guarantees to preserve a NAT mapping, or
* VcnGatewayConnectionConfig.MIN_UDP_PORT_4500_NAT_TIMEOUT_UNSET if not set.
+ * @see VcnGatewayConnectionConfig.Builder#setMinUdpPort4500NatTimeoutSeconds(int)
+ * @hide
*/
+ @FlaggedApi(FLAG_MAINLINE_VCN_MODULE_API)
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public int getMinUdpPort4500NatTimeoutSeconds() {
return mMinUdpPort4500NatTimeoutSeconds;
}
@@ -129,12 +149,21 @@ public class VcnTransportInfo implements TransportInfo, Parcelable {
&& mMinUdpPort4500NatTimeoutSeconds == that.mMinUdpPort4500NatTimeoutSeconds;
}
- /** {@inheritDoc} */
+ /**
+ * {@inheritDoc}
+ *
+ * @hide
+ */
+ @FlaggedApi(FLAG_MAINLINE_VCN_MODULE_API)
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
@Override
public int describeContents() {
return 0;
}
+ /** @hide */
+ @FlaggedApi(FLAG_MAINLINE_VCN_MODULE_API)
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
@Override
@NonNull
public TransportInfo makeCopy(long redactions) {
@@ -149,6 +178,9 @@ public class VcnTransportInfo implements TransportInfo, Parcelable {
mMinUdpPort4500NatTimeoutSeconds);
}
+ /** @hide */
+ @FlaggedApi(FLAG_MAINLINE_VCN_MODULE_API)
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
@Override
public long getApplicableRedactions() {
long redactions = REDACT_FOR_NETWORK_SETTINGS;
@@ -161,7 +193,13 @@ public class VcnTransportInfo implements TransportInfo, Parcelable {
return redactions;
}
- /** {@inheritDoc} */
+ /**
+ * {@inheritDoc}
+ *
+ * @hide
+ */
+ @FlaggedApi(FLAG_MAINLINE_VCN_MODULE_API)
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeInt(mSubId);
@@ -174,7 +212,13 @@ public class VcnTransportInfo implements TransportInfo, Parcelable {
return "VcnTransportInfo { mWifiInfo = " + mWifiInfo + ", mSubId = " + mSubId + " }";
}
- /** Implement the Parcelable interface */
+ /**
+ * Implement the Parcelable interface
+ *
+ * @hide
+ */
+ @FlaggedApi(FLAG_MAINLINE_VCN_MODULE_API)
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public static final @NonNull Creator CREATOR =
new Creator() {
public VcnTransportInfo createFromParcel(Parcel in) {
@@ -201,37 +245,63 @@ public class VcnTransportInfo implements TransportInfo, Parcelable {
}
};
- /** This class can be used to construct a {@link VcnTransportInfo}. */
+ /**
+ * This class can be used to construct a {@link VcnTransportInfo}.
+ *
+ * @hide
+ */
+ @FlaggedApi(FLAG_MAINLINE_VCN_MODULE_API)
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public static final class Builder {
private int mMinUdpPort4500NatTimeoutSeconds = MIN_UDP_PORT_4500_NAT_TIMEOUT_UNSET;
- /** Construct Builder */
+ /**
+ * Construct Builder
+ *
+ * @hide
+ */
+ @FlaggedApi(FLAG_MAINLINE_VCN_MODULE_API)
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public Builder() {}
/**
- * Sets the maximum supported IKEv2/IPsec NATT keepalive timeout.
+ * Set the minimum duration that the VCN Gateway guarantees to preserve a NAT mapping.
*
* This is used as a power-optimization hint for other IKEv2/IPsec use cases (e.g. VPNs,
* or IWLAN) to reduce the necessary keepalive frequency, thus conserving power and data.
*
- * @param minUdpPort4500NatTimeoutSeconds the maximum keepalive timeout supported by the VCN
- * Gateway Connection, generally the minimum duration a NAT mapping is cached on the VCN
- * Gateway.
+ * @param minUdpPort4500NatTimeoutSeconds the minimum duration that the VCN Gateway
+ * guarantees to preserve a NAT mapping, or {@link MIN_UDP_PORT_4500_NAT_TIMEOUT_UNSET}
+ * to clear this value. To ensure uninterrupted connectivity, the device must send
+ * keepalive packets within this interval. Failure to do so may result in the mapping
+ * being cleared and connection termination.
* @return this {@link Builder} instance, for chaining
+ * @see VcnGatewayConnectionConfig.Builder#setMinUdpPort4500NatTimeoutSeconds(int)
+ * @hide
*/
+ @FlaggedApi(FLAG_MAINLINE_VCN_MODULE_API)
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
@NonNull
public Builder setMinUdpPort4500NatTimeoutSeconds(
@IntRange(from = MIN_UDP_PORT_4500_NAT_TIMEOUT_SECONDS)
int minUdpPort4500NatTimeoutSeconds) {
Preconditions.checkArgument(
- minUdpPort4500NatTimeoutSeconds >= MIN_UDP_PORT_4500_NAT_TIMEOUT_SECONDS,
- "Timeout must be at least 120s");
+ minUdpPort4500NatTimeoutSeconds == MIN_UDP_PORT_4500_NAT_TIMEOUT_UNSET
+ || minUdpPort4500NatTimeoutSeconds
+ >= MIN_UDP_PORT_4500_NAT_TIMEOUT_SECONDS,
+ "Timeout must be at least 120s or MIN_UDP_PORT_4500_NAT_TIMEOUT_UNSET");
mMinUdpPort4500NatTimeoutSeconds = minUdpPort4500NatTimeoutSeconds;
return Builder.this;
}
- /** Build a VcnTransportInfo instance */
+ /**
+ * Build a VcnTransportInfo instance
+ *
+ * @hide
+ */
+ @FlaggedApi(FLAG_MAINLINE_VCN_MODULE_API)
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
@NonNull
public VcnTransportInfo build() {
return new VcnTransportInfo(
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 102bdd0b625c9d81ae0cd94d0be695f081905d16..c2e9260879a8ea87e49b38c30984929964a4279d 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -32,6 +32,7 @@ import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.ravenwood.annotation.RavenwoodKeepWholeClass;
import android.sdk.Flags;
+import android.sysprop.BackportedFixesProperties;
import android.sysprop.DeviceProperties;
import android.sysprop.SocProperties;
import android.sysprop.TelephonyProperties;
@@ -1612,12 +1613,25 @@ public class Build {
* is not applicable on this device,
* otherwise {@link #BACKPORTED_FIX_STATUS_UNKNOWN}.
*/
-
@FlaggedApi(android.os.Flags.FLAG_API_FOR_BACKPORTED_FIXES)
public static @BackportedFixStatus int getBackportedFixStatus(long id) {
- // TODO: b/308461809 - query aliases from system prop
- // TODO: b/372518979 - use backported fix datastore.
- return BACKPORTED_FIX_STATUS_UNKNOWN;
+ if (id <= 0 || id > 1023) {
+ return BACKPORTED_FIX_STATUS_UNKNOWN;
+ }
+ return isBitSet(BackportedFixesProperties.alias_bitset(), (int) id)
+ ? BACKPORTED_FIX_STATUS_FIXED : BACKPORTED_FIX_STATUS_UNKNOWN;
+ }
+
+ private static boolean isBitSet(List bitsetLongArray, int bitIndex) {
+ // Because java.util.BitSet is not threadsafe do the calculations here instead.
+ if (bitIndex < 0) {
+ return false;
+ }
+ int arrayIndex = bitIndex >> 6;
+ if (bitsetLongArray.size() <= arrayIndex) {
+ return false;
+ }
+ return (bitsetLongArray.get(arrayIndex) & (1L << bitIndex)) != 0;
}
/**
diff --git a/core/java/android/os/Bundle.java b/core/java/android/os/Bundle.java
index c18fb0c38b8279c072499b3381f6e1c5c1db4679..05bd10b053fe92096c1760a61eca1e5676b5e6a2 100644
--- a/core/java/android/os/Bundle.java
+++ b/core/java/android/os/Bundle.java
@@ -18,10 +18,12 @@ package android.os;
import static java.util.Objects.requireNonNull;
+import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
+import android.annotation.SystemApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.util.ArrayMap;
import android.util.Size;
@@ -72,16 +74,18 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable {
/**
* Status when the Bundle can assert that the underlying Parcel DOES NOT contain
* Binder object(s).
- *
* @hide
*/
+ @FlaggedApi(Flags.FLAG_ENABLE_HAS_BINDERS)
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public static final int STATUS_BINDERS_NOT_PRESENT = 0;
/**
* Status when the Bundle can assert that there are Binder object(s) in the Parcel.
- *
* @hide
*/
+ @FlaggedApi(Flags.FLAG_ENABLE_HAS_BINDERS)
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public static final int STATUS_BINDERS_PRESENT = 1;
/**
@@ -94,9 +98,10 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable {
* object to the Bundle but it is not possible to assert this fact unless the Bundle is written
* to a Parcel.
*
- *
* @hide
*/
+ @FlaggedApi(Flags.FLAG_ENABLE_HAS_BINDERS)
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public static final int STATUS_BINDERS_UNKNOWN = 2;
/** @hide */
@@ -281,7 +286,7 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable {
}
/** {@hide} */
- public void setIsIntentExtra() {
+ public void enableTokenVerification() {
mFlags |= FLAG_VERIFY_TOKENS_PRESENT;
}
@@ -417,6 +422,8 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable {
* Returns a status indicating whether the bundle contains any parcelled Binder objects.
* @hide
*/
+ @FlaggedApi(Flags.FLAG_ENABLE_HAS_BINDERS)
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public @HasBinderStatus int hasBinders() {
if ((mFlags & FLAG_HAS_BINDERS_KNOWN) != 0) {
if ((mFlags & FLAG_HAS_BINDERS) != 0) {
diff --git a/core/java/android/os/CombinedMessageQueue/MessageQueue.java b/core/java/android/os/CombinedMessageQueue/MessageQueue.java
index 69bd6685bcac24bd770e917ecb793be8aed2f829..036ccd84a600dd40fad8ebce3f11e65a593b7be9 100644
--- a/core/java/android/os/CombinedMessageQueue/MessageQueue.java
+++ b/core/java/android/os/CombinedMessageQueue/MessageQueue.java
@@ -19,6 +19,8 @@ package android.os;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.TestApi;
+import android.app.ActivityThread;
+import android.app.Instrumentation;
import android.compat.annotation.UnsupportedAppUsage;
import android.os.Process;
import android.os.UserHandle;
@@ -110,11 +112,39 @@ public final class MessageQueue {
private native static void nativeSetFileDescriptorEvents(long ptr, int fd, int events);
MessageQueue(boolean quitAllowed) {
+ // Concurrent mode modifies behavior that is observable via reflection and is commonly used
+ // by tests.
+ // For now, we limit it to system processes to avoid breaking apps and their tests.
mUseConcurrent = UserHandle.isCore(Process.myUid());
+ // Even then, we don't use it if instrumentation is loaded as it breaks some
+ // platform tests.
+ final Instrumentation instrumentation = getInstrumentation();
+ mUseConcurrent &= instrumentation == null || !instrumentation.isInstrumenting();
+ // We can lift this restriction in the future after we've made it possible for test authors
+ // to test Looper and MessageQueue without resorting to reflection.
+
+ // Holdback study.
+ if (mUseConcurrent && Flags.messageQueueForceLegacy()) {
+ mUseConcurrent = false;
+ }
+
mQuitAllowed = quitAllowed;
mPtr = nativeInit();
}
+ @android.ravenwood.annotation.RavenwoodReplace(blockedBy = ActivityThread.class)
+ private static Instrumentation getInstrumentation() {
+ final ActivityThread activityThread = ActivityThread.currentActivityThread();
+ if (activityThread != null) {
+ return activityThread.getInstrumentation();
+ }
+ return null;
+ }
+
+ private static Instrumentation getInstrumentation$ravenwood() {
+ return null; // Instrumentation not supported on Ravenwood yet.
+ }
+
@Override
protected void finalize() throws Throwable {
try {
diff --git a/core/java/android/os/CpuHeadroomParams.java b/core/java/android/os/CpuHeadroomParams.java
new file mode 100644
index 0000000000000000000000000000000000000000..f0d4f7d8737fadf080c20e929853ee8c4bd7fcb4
--- /dev/null
+++ b/core/java/android/os/CpuHeadroomParams.java
@@ -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 android.os;
+
+import android.annotation.FlaggedApi;
+import android.annotation.IntDef;
+import android.os.health.SystemHealthManager;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Headroom request params used by {@link SystemHealthManager#getCpuHeadroom(CpuHeadroomParams)}.
+ */
+@FlaggedApi(Flags.FLAG_CPU_GPU_HEADROOMS)
+public final class CpuHeadroomParams {
+ final CpuHeadroomParamsInternal mInternal;
+
+ public CpuHeadroomParams() {
+ mInternal = new CpuHeadroomParamsInternal();
+ }
+
+ /** @hide */
+ @IntDef(flag = false, prefix = {"CPU_HEADROOM_CALCULATION_TYPE_"}, value = {
+ CPU_HEADROOM_CALCULATION_TYPE_MIN, // 0
+ CPU_HEADROOM_CALCULATION_TYPE_AVERAGE, // 1
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface CpuHeadroomCalculationType {
+ }
+
+ /**
+ * Calculates the headroom based on minimum value over a device-defined window.
+ */
+ public static final int CPU_HEADROOM_CALCULATION_TYPE_MIN = 0;
+
+ /**
+ * Calculates the headroom based on average value over a device-defined window.
+ */
+ public static final int CPU_HEADROOM_CALCULATION_TYPE_AVERAGE = 1;
+
+ /**
+ * Sets the headroom calculation type.
+ *
+ *
+ * @throws IllegalArgumentException if the type is invalid.
+ */
+ public void setCalculationType(@CpuHeadroomCalculationType int calculationType) {
+ switch (calculationType) {
+ case CPU_HEADROOM_CALCULATION_TYPE_MIN:
+ case CPU_HEADROOM_CALCULATION_TYPE_AVERAGE:
+ mInternal.calculationType = (byte) calculationType;
+ return;
+ }
+ throw new IllegalArgumentException("Invalid calculation type: " + calculationType);
+ }
+
+ /**
+ * Gets the headroom calculation type.
+ * Default to {@link #CPU_HEADROOM_CALCULATION_TYPE_MIN} if not set.
+ */
+ public @CpuHeadroomCalculationType int getCalculationType() {
+ @CpuHeadroomCalculationType int validatedType = switch ((int) mInternal.calculationType) {
+ case CPU_HEADROOM_CALCULATION_TYPE_MIN, CPU_HEADROOM_CALCULATION_TYPE_AVERAGE ->
+ mInternal.calculationType;
+ default -> CPU_HEADROOM_CALCULATION_TYPE_MIN;
+ };
+ return validatedType;
+ }
+
+ /**
+ * @hide
+ */
+ public CpuHeadroomParamsInternal getInternal() {
+ return mInternal;
+ }
+}
diff --git a/core/java/android/os/CpuHeadroomParamsInternal.aidl b/core/java/android/os/CpuHeadroomParamsInternal.aidl
new file mode 100644
index 0000000000000000000000000000000000000000..6cc4699a809e1705bed50fd3cb663e832177dbd0
--- /dev/null
+++ b/core/java/android/os/CpuHeadroomParamsInternal.aidl
@@ -0,0 +1,31 @@
+/*
+ * 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.os;
+
+import android.hardware.power.CpuHeadroomParams;
+
+/**
+ * Changes should be synced with match function of HintManagerService#CpuHeadroomCacheItem.
+ * {@hide}
+ */
+@JavaDerive(equals = true, toString = true)
+parcelable CpuHeadroomParamsInternal {
+ boolean usesDeviceHeadroom = false;
+ CpuHeadroomParams.CalculationType calculationType = CpuHeadroomParams.CalculationType.MIN;
+ CpuHeadroomParams.SelectionType selectionType = CpuHeadroomParams.SelectionType.ALL;
+}
+
diff --git a/core/java/android/os/GpuHeadroomParams.java b/core/java/android/os/GpuHeadroomParams.java
new file mode 100644
index 0000000000000000000000000000000000000000..efb2a28ad2b56350a6eb9a35e6ef1f466617180b
--- /dev/null
+++ b/core/java/android/os/GpuHeadroomParams.java
@@ -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 android.os;
+
+import android.annotation.FlaggedApi;
+import android.annotation.IntDef;
+import android.os.health.SystemHealthManager;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Headroom request params used by {@link SystemHealthManager#getGpuHeadroom(GpuHeadroomParams)}.
+ */
+@FlaggedApi(Flags.FLAG_CPU_GPU_HEADROOMS)
+public final class GpuHeadroomParams {
+ final GpuHeadroomParamsInternal mInternal;
+
+ public GpuHeadroomParams() {
+ mInternal = new GpuHeadroomParamsInternal();
+ }
+
+ /** @hide */
+ @IntDef(flag = false, prefix = {"GPU_HEADROOM_CALCULATION_TYPE_"}, value = {
+ GPU_HEADROOM_CALCULATION_TYPE_MIN, // 0
+ GPU_HEADROOM_CALCULATION_TYPE_AVERAGE, // 1
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface GpuHeadroomCalculationType {
+ }
+
+ /**
+ * Calculates the headroom based on minimum value over a device-defined window.
+ */
+ public static final int GPU_HEADROOM_CALCULATION_TYPE_MIN = 0;
+
+ /**
+ * Calculates the headroom based on average value over a device-defined window.
+ */
+ public static final int GPU_HEADROOM_CALCULATION_TYPE_AVERAGE = 1;
+
+ /**
+ * Sets the headroom calculation type.
+ *
+ *
+ * @throws IllegalArgumentException if the type is invalid.
+ */
+ public void setCalculationType(@GpuHeadroomCalculationType int calculationType) {
+ switch (calculationType) {
+ case GPU_HEADROOM_CALCULATION_TYPE_MIN:
+ case GPU_HEADROOM_CALCULATION_TYPE_AVERAGE:
+ mInternal.calculationType = (byte) calculationType;
+ return;
+ }
+ throw new IllegalArgumentException("Invalid calculation type: " + calculationType);
+ }
+
+ /**
+ * Gets the headroom calculation type.
+ * Default to {@link #GPU_HEADROOM_CALCULATION_TYPE_MIN} if not set.
+ */
+ public @GpuHeadroomCalculationType int getCalculationType() {
+ @GpuHeadroomCalculationType int validatedType = switch ((int) mInternal.calculationType) {
+ case GPU_HEADROOM_CALCULATION_TYPE_MIN, GPU_HEADROOM_CALCULATION_TYPE_AVERAGE ->
+ mInternal.calculationType;
+ default -> GPU_HEADROOM_CALCULATION_TYPE_MIN;
+ };
+ return validatedType;
+ }
+
+ /**
+ * @hide
+ */
+ public GpuHeadroomParamsInternal getInternal() {
+ return mInternal;
+ }
+}
diff --git a/core/java/android/os/GpuHeadroomParamsInternal.aidl b/core/java/android/os/GpuHeadroomParamsInternal.aidl
new file mode 100644
index 0000000000000000000000000000000000000000..20309e7673f20b37b41dd3b1cfb55572ebee0c9f
--- /dev/null
+++ b/core/java/android/os/GpuHeadroomParamsInternal.aidl
@@ -0,0 +1,28 @@
+/*
+ * 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.os;
+
+import android.hardware.power.GpuHeadroomParams;
+
+/**
+ * Changes should be synced with match function of HintManagerService#GpuHeadroomCacheItem.
+ * {@hide}
+ */
+@JavaDerive(equals = true, toString = true)
+parcelable GpuHeadroomParamsInternal {
+ GpuHeadroomParams.CalculationType calculationType = GpuHeadroomParams.CalculationType.MIN;
+}
diff --git a/core/java/android/os/IHintManager.aidl b/core/java/android/os/IHintManager.aidl
index 73cdd5682f31fba7781abca6c9b362a0b6e3e5c3..33120556339f42a4f31db42e0df62b63d58062e9 100644
--- a/core/java/android/os/IHintManager.aidl
+++ b/core/java/android/os/IHintManager.aidl
@@ -17,6 +17,8 @@
package android.os;
+import android.os.CpuHeadroomParamsInternal;
+import android.os.GpuHeadroomParamsInternal;
import android.os.IHintSession;
import android.hardware.power.ChannelConfig;
import android.hardware.power.SessionConfig;
@@ -50,4 +52,8 @@ interface IHintManager {
*/
@nullable ChannelConfig getSessionChannel(in IBinder token);
oneway void closeSessionChannel();
+ float[] getCpuHeadroom(in CpuHeadroomParamsInternal params);
+ long getCpuHeadroomMinIntervalMillis();
+ float getGpuHeadroom(in GpuHeadroomParamsInternal params);
+ long getGpuHeadroomMinIntervalMillis();
}
diff --git a/core/java/android/os/OWNERS b/core/java/android/os/OWNERS
index 590ddb404b63a545fbe28522ecac5a982142cce6..e63b6648a9efd6bd3e592abb7f3f4f2fc988f6fb 100644
--- a/core/java/android/os/OWNERS
+++ b/core/java/android/os/OWNERS
@@ -78,6 +78,9 @@ per-file PatternMatcher* = file:/PACKAGE_MANAGER_OWNERS
# PermissionEnforcer
per-file PermissionEnforcer.java = tweek@google.com, brufino@google.com
+# RemoteCallbackList
+per-file RemoteCallbackList.java = shayba@google.com
+
# ART
per-file ArtModuleServiceManager.java = file:platform/art:/OWNERS
@@ -125,3 +128,6 @@ per-file StatsServiceManager.java = file:/services/core/java/com/android/server/
# Dropbox
per-file DropBoxManager* = mwachens@google.com
+
+# Flags
+per-file flags.aconfig = file:/FF_LEADS_OWNERS
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index f7285523c01a96b21addb2f9b623ffcb895f59bf..bf7116d6a05bc8564e7c15238e169f8599059545 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -1371,7 +1371,6 @@ public final class Parcel {
writeInt(N);
if (DEBUG_ARRAY_MAP) {
RuntimeException here = new RuntimeException("here");
- here.fillInStackTrace();
Log.d(TAG, "Writing " + N + " ArrayMap entries", here);
}
int startPos;
diff --git a/core/java/android/os/PowerManagerInternal.java b/core/java/android/os/PowerManagerInternal.java
index 29ccb85c0babbe6ed86e80373fd2d1110de5c976..9435f4d59a2c96dd17a713d5e5f73a893d088d21 100644
--- a/core/java/android/os/PowerManagerInternal.java
+++ b/core/java/android/os/PowerManagerInternal.java
@@ -97,18 +97,6 @@ public abstract class PowerManagerInternal {
return wakefulness == WAKEFULNESS_AWAKE || wakefulness == WAKEFULNESS_DREAMING;
}
- /**
- * Used by the window manager to override the screen brightness based on the
- * current foreground activity.
- *
- * This method must only be called by the window manager.
- *
- * @param brightness The overridden brightness, or Float.NaN to disable the override.
- * @param tag Source identifier of the app window that requests the override.
- */
- public abstract void setScreenBrightnessOverrideFromWindowManager(
- float brightness, CharSequence tag);
-
/**
* Used by the window manager to override the user activity timeout based on the
* current foreground activity. It can only be used to make the timeout shorter
diff --git a/core/java/android/os/RemoteCallbackList.java b/core/java/android/os/RemoteCallbackList.java
index 01b1e5e113326bf0f4fab63661efafa5179101d2..91c482faf7d753cb4581e6e5166c7b70bc535f61 100644
--- a/core/java/android/os/RemoteCallbackList.java
+++ b/core/java/android/os/RemoteCallbackList.java
@@ -194,15 +194,27 @@ public class RemoteCallbackList {
}
}
- public void maybeSubscribeToFrozenCallback() throws RemoteException {
+ void maybeSubscribeToFrozenCallback() throws RemoteException {
if (mFrozenCalleePolicy != FROZEN_CALLEE_POLICY_UNSET) {
- mBinder.addFrozenStateChangeCallback(this);
+ try {
+ mBinder.addFrozenStateChangeCallback(this);
+ } catch (UnsupportedOperationException e) {
+ // The kernel does not support frozen notifications. In this case we want to
+ // silently fall back to FROZEN_CALLEE_POLICY_UNSET. This is done by simply
+ // ignoring the error and moving on. mCurrentState would always be
+ // STATE_UNFROZEN and all callbacks are invoked immediately.
+ }
}
}
- public void maybeUnsubscribeFromFrozenCallback() {
+ void maybeUnsubscribeFromFrozenCallback() {
if (mFrozenCalleePolicy != FROZEN_CALLEE_POLICY_UNSET) {
- mBinder.removeFrozenStateChangeCallback(this);
+ try {
+ mBinder.removeFrozenStateChangeCallback(this);
+ } catch (UnsupportedOperationException e) {
+ // The kernel does not support frozen notifications. Ignore the error and move
+ // on.
+ }
}
}
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 4bc8fe0a974cd80faf2791ff44139cc305868b39..5a53bc1552b84ce43a1316c8205ffd423029b457 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -3928,9 +3928,9 @@ public class UserManager {
final int callingUid = Binder.getCallingUid();
final int processUid = Process.myUid();
- if (Build.isDebuggable() && callingUid != processUid) {
- Log.w(TAG, "Uid " + processUid + " is fetching a copy of UserProperties on"
- + " behalf of callingUid " + callingUid + ". Possibly"
+ if (processUid == Process.SYSTEM_UID && callingUid != processUid) {
+ Log.w(TAG, "The System (uid " + processUid + ") is fetching a copy of"
+ + " UserProperties on behalf of callingUid " + callingUid + ". Possibly"
+ " it should carefully first clearCallingIdentity or perhaps use"
+ " UserManagerInternal.getUserProperties() instead?",
new Throwable());
@@ -5308,7 +5308,13 @@ public class UserManager {
Manifest.permission.MANAGE_USERS,
Manifest.permission.CREATE_USERS,
Manifest.permission.QUERY_USERS}, conditional = true)
+ @CachedProperty(api = "user_manager_user_data")
public List getProfiles(@UserIdInt int userId) {
+ if (android.multiuser.Flags.cacheProfilesReadOnly()) {
+ return UserManagerCache.getProfiles(
+ (Integer userIdentifier) -> mService.getProfiles(userIdentifier, false),
+ userId);
+ }
try {
return mService.getProfiles(userId, false /* enabledOnly */);
} catch (RemoteException re) {
@@ -6483,6 +6489,19 @@ public class UserManager {
}
}
+ /**
+ * This method is used to invalidate caches, when UserManagerService.mUsers
+ * {@link UserManagerService.UserData} is modified, including changes to {@link UserInfo}.
+ * In practice we determine modification by when that data is persisted, or scheduled to be
+ * presisted, to xml.
+ * @hide
+ */
+ public static final void invalidateCacheOnUserDataChanged() {
+ if (android.multiuser.Flags.cacheProfilesReadOnly()) {
+ UserManagerCache.invalidateProfiles();
+ }
+ }
+
/**
* Returns a serial number on this device for a given userId. User handles can be recycled
* when deleting and creating users, but serial numbers are not reused until the device is
diff --git a/core/java/android/os/VibrationEffect.java b/core/java/android/os/VibrationEffect.java
index 0cffd9f990fd70be485094a115ec57cafe2c808f..f6bc3894be4bad0f9d14cd634e209694149edc39 100644
--- a/core/java/android/os/VibrationEffect.java
+++ b/core/java/android/os/VibrationEffect.java
@@ -41,6 +41,7 @@ import android.os.vibrator.PwleSegment;
import android.os.vibrator.RampSegment;
import android.os.vibrator.StepSegment;
import android.os.vibrator.VibrationEffectSegment;
+import android.os.vibrator.VibratorEnvelopeEffectInfo;
import android.os.vibrator.VibratorFrequencyProfileLegacy;
import android.util.MathUtils;
@@ -1483,6 +1484,15 @@ public abstract class VibrationEffect implements Parcelable {
public @interface PrimitiveType {
}
+ /** @hide */
+ @IntDef(prefix = { "DELAY_TYPE_" }, value = {
+ DELAY_TYPE_PAUSE,
+ DELAY_TYPE_RELATIVE_START_OFFSET,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface DelayType {
+ }
+
/**
* Exception thrown when adding an element to a {@link Composition} that already ends in an
* indefinitely repeating effect.
@@ -1541,6 +1551,53 @@ public abstract class VibrationEffect implements Parcelable {
// Internally this maps to the HAL constant CompositePrimitive::LOW_TICK
public static final int PRIMITIVE_LOW_TICK = 8;
+ /**
+ * The delay represents a pause in the composition between the end of the previous primitive
+ * and the beginning of the next one.
+ *
+ * The primitive will start after the requested pause after the last primitive ended.
+ * The actual time the primitive will be played depends on the previous primitive's actual
+ * duration on the device hardware. This enables the combination of primitives to create
+ * more complex effects based on how close to each other they'll play. Here is an example:
+ *
+ *
+ * VibrationEffect popEffect = VibrationEffect.startComposition()
+ * .addPrimitive(PRIMITIVE_QUICK_RISE)
+ * .addPrimitive(PRIMITIVE_CLICK, 0.7, 50, DELAY_TYPE_PAUSE)
+ * .compose()
+ *
+ */
+ @FlaggedApi(Flags.FLAG_PRIMITIVE_COMPOSITION_ABSOLUTE_DELAY)
+ public static final int DELAY_TYPE_PAUSE = 0;
+
+ /**
+ * The delay represents an offset before starting this primitive, relative to the start
+ * time of the previous primitive in the composition.
+ *
+ * The primitive will start at the requested fixed time after the last primitive started,
+ * independently of that primitive's actual duration on the device hardware. This enables
+ * precise timings of primitives within a composition, ensuring they'll be played at the
+ * desired intervals. Here is an example:
+ *
+ *
+ * VibrationEffect.startComposition()
+ * .addPrimitive(PRIMITIVE_CLICK, 1.0)
+ * .addPrimitive(PRIMITIVE_TICK, 1.0, 20, DELAY_TYPE_RELATIVE_START_OFFSET)
+ * .addPrimitive(PRIMITIVE_THUD, 1.0, 80, DELAY_TYPE_RELATIVE_START_OFFSET)
+ * .compose()
+ *
+ *
+ * Will be performed on the device as follows:
+ *
+ *
+ * 0ms 20ms 100ms
+ * PRIMITIVE_CLICK---PRIMITIVE_TICK-----------PRIMITIVE_THUD
+ *
+ *
+ * A primitive will be dropped from the composition if it overlaps with previous ones.
+ */
+ @FlaggedApi(Flags.FLAG_PRIMITIVE_COMPOSITION_ABSOLUTE_DELAY)
+ public static final int DELAY_TYPE_RELATIVE_START_OFFSET = 1;
private final ArrayList mSegments = new ArrayList<>();
private int mRepeatIndex = -1;
@@ -1665,7 +1722,26 @@ public abstract class VibrationEffect implements Parcelable {
@NonNull
public Composition addPrimitive(@PrimitiveType int primitiveId,
@FloatRange(from = 0f, to = 1f) float scale, @IntRange(from = 0) int delay) {
- PrimitiveSegment primitive = new PrimitiveSegment(primitiveId, scale, delay);
+ return addPrimitive(primitiveId, scale, delay, PrimitiveSegment.DEFAULT_DELAY_TYPE);
+ }
+
+ /**
+ * Add a haptic primitive to the end of the current composition.
+ *
+ * @param primitiveId The primitive to add
+ * @param scale The scale to apply to the intensity of the primitive.
+ * @param delay The amount of time in milliseconds to wait before playing this primitive,
+ * as defined by the given {@code delayType}.
+ * @param delayType The type of delay to be applied, e.g. a pause between last primitive and
+ * this one or a start offset.
+ * @return This {@link Composition} object to enable adding multiple elements in one chain.
+ */
+ @FlaggedApi(Flags.FLAG_PRIMITIVE_COMPOSITION_ABSOLUTE_DELAY)
+ @NonNull
+ public Composition addPrimitive(@PrimitiveType int primitiveId,
+ @FloatRange(from = 0f, to = 1f) float scale, @IntRange(from = 0) int delay,
+ @DelayType int delayType) {
+ PrimitiveSegment primitive = new PrimitiveSegment(primitiveId, scale, delay, delayType);
primitive.validate();
return addSegment(primitive);
}
@@ -1733,52 +1809,20 @@ public abstract class VibrationEffect implements Parcelable {
default -> Integer.toString(id);
};
}
- }
-
- /**
- * Start building a waveform vibration.
- *
- * The waveform envelope builder offers more flexibility for creating waveform effects,
- * allowing control over vibration amplitude and frequency via smooth transitions between
- * values. The waveform will start the first transition from the vibrator off state, using
- * the same frequency of the first control point. To provide a different initial vibration
- * frequency, use {@link #startWaveformEnvelope(float)}.
- *
- *
Note: To check whether waveform envelope effects are supported, use
- * {@link Vibrator#areEnvelopeEffectsSupported()}.
- *
- * @see VibrationEffect.WaveformEnvelopeBuilder
- */
- @FlaggedApi(Flags.FLAG_NORMALIZED_PWLE_EFFECTS)
- @NonNull
- public static VibrationEffect.WaveformEnvelopeBuilder startWaveformEnvelope() {
- return new WaveformEnvelopeBuilder();
- }
- /**
- * Start building a waveform vibration with an initial frequency.
- *
- *
The waveform envelope builder offers more flexibility for creating waveform effects,
- * allowing control over vibration amplitude and frequency via smooth transitions between
- * values.
- *
- *
This is the same as {@link #startWaveformEnvelope()}, but the waveform will start
- * vibrating at given frequency, in hertz, while it transitions to the new amplitude and
- * frequency of the first control point.
- *
- *
Note: To check whether waveform envelope effects are supported, use
- * {@link Vibrator#areEnvelopeEffectsSupported()}.
- *
- * @param initialFrequencyHz The starting frequency of the vibration, in hertz. Must be greater
- * than zero.
- *
- * @see VibrationEffect.WaveformEnvelopeBuilder
- */
- @FlaggedApi(Flags.FLAG_NORMALIZED_PWLE_EFFECTS)
- @NonNull
- public static VibrationEffect.WaveformEnvelopeBuilder startWaveformEnvelope(
- @FloatRange(from = 0) float initialFrequencyHz) {
- return new WaveformEnvelopeBuilder(initialFrequencyHz);
+ /**
+ * Convert the delay type to a human readable string for debugging.
+ * @param type The delay type to convert
+ * @return The delay type in a human readable format.
+ * @hide
+ */
+ public static String delayTypeToString(@DelayType int type) {
+ return switch (type) {
+ case DELAY_TYPE_PAUSE -> "PAUSE";
+ case DELAY_TYPE_RELATIVE_START_OFFSET -> "START_OFFSET";
+ default -> Integer.toString(type);
+ };
+ }
}
/**
@@ -1792,7 +1836,7 @@ public abstract class VibrationEffect implements Parcelable {
* 100ms, holds that state for 200ms, and then ramps back down over 100ms:
*
*
{@code
- * VibrationEffect effect = VibrationEffect.startWaveformEnvelope()
+ * VibrationEffect effect = new VibrationEffect.WaveformEnvelopeBuilder()
* .addControlPoint(1.0f, 120f, 100)
* .addControlPoint(1.0f, 120f, 200)
* .addControlPoint(0.0f, 120f, 100)
@@ -1819,27 +1863,55 @@ public abstract class VibrationEffect implements Parcelable {
*
* You can use the following APIs to obtain these limits:
*
- * - Maximum envelope control points: {@link Vibrator#getMaxEnvelopeEffectSize()}
+ * - Maximum envelope control points: {@link VibratorEnvelopeEffectInfo#getMaxSize()}
*
- Minimum control point duration:
- * {@link Vibrator#getMinEnvelopeEffectControlPointDurationMillis()}
+ * {@link VibratorEnvelopeEffectInfo#getMinControlPointDurationMillis()}
* - Maximum control point duration:
- * {@link Vibrator#getMaxEnvelopeEffectControlPointDurationMillis()}
- * - Maximum total effect duration: {@link Vibrator#getMaxEnvelopeEffectDurationMillis()}
+ * {@link VibratorEnvelopeEffectInfo#getMaxControlPointDurationMillis()}
+ * - Maximum total effect duration: {@link VibratorEnvelopeEffectInfo#getMaxDurationMillis()}
*
- *
- * @see VibrationEffect#startWaveformEnvelope()
*/
@FlaggedApi(Flags.FLAG_NORMALIZED_PWLE_EFFECTS)
public static final class WaveformEnvelopeBuilder {
private ArrayList mSegments = new ArrayList<>();
private float mLastAmplitude = 0f;
- private float mLastFrequencyHz = 0f;
+ private float mLastFrequencyHz = Float.NaN;
- private WaveformEnvelopeBuilder() {}
+ public WaveformEnvelopeBuilder() {}
- private WaveformEnvelopeBuilder(float initialFrequency) {
- mLastFrequencyHz = initialFrequency;
+ /**
+ * Sets the initial frequency for the waveform in Hertz.
+ *
+ * The effect will start vibrating at this frequency when it transitions to the
+ * amplitude and frequency defined by the first control point.
+ *
+ *
The frequency must be greater than zero and within the supported range. To determine
+ * the supported range, use {@link Vibrator#getFrequencyProfile()}. Creating
+ * effects using frequencies outside this range will result in the vibration not playing.
+ *
+ * @param initialFrequencyHz The starting frequency of the vibration, in Hz. Must be
+ * greater than zero.
+ */
+ @FlaggedApi(Flags.FLAG_NORMALIZED_PWLE_EFFECTS)
+ @SuppressWarnings("MissingGetterMatchingBuilder")// No getter to initial frequency once set.
+ @NonNull
+ public WaveformEnvelopeBuilder setInitialFrequencyHz(
+ @FloatRange(from = 0) float initialFrequencyHz) {
+
+ if (mSegments.isEmpty()) {
+ mLastFrequencyHz = initialFrequencyHz;
+ } else {
+ PwleSegment firstSegment = mSegments.getFirst();
+ mSegments.set(0, new PwleSegment(
+ firstSegment.getStartAmplitude(),
+ firstSegment.getEndAmplitude(),
+ initialFrequencyHz, // Update start frequency
+ firstSegment.getEndFrequencyHz(),
+ (int) firstSegment.getDuration()));
+ }
+
+ return this;
}
/**
@@ -1850,15 +1922,13 @@ public abstract class VibrationEffect implements Parcelable {
* perceived intensity. It's determined by the actuator response curve.
*
*
Frequency must be greater than zero and within the supported range. To determine
- * the supported range, use {@link Vibrator#getFrequencyProfile()}. This method returns a
- * {@link android.os.vibrator.VibratorFrequencyProfile} object, which contains the
- * minimum and maximum frequencies, among other frequency-related information. Creating
+ * the supported range, use {@link Vibrator#getFrequencyProfile()}. Creating
* effects using frequencies outside this range will result in the vibration not playing.
*
*
Time specifies the duration (in milliseconds) for the vibrator to smoothly transition
* from the previous control point to this new one. It must be greater than zero. To
* transition as quickly as possible, use
- * {@link Vibrator#getMinEnvelopeEffectControlPointDurationMillis()}.
+ * {@link VibratorEnvelopeEffectInfo#getMinControlPointDurationMillis()}.
*
* @param amplitude The amplitude value between 0 and 1, inclusive. 0 represents the
* vibrator being off, and 1 represents the maximum achievable amplitude
@@ -1873,7 +1943,7 @@ public abstract class VibrationEffect implements Parcelable {
@FloatRange(from = 0, to = 1) float amplitude,
@FloatRange(from = 0) float frequencyHz, int timeMillis) {
- if (mLastFrequencyHz == 0) {
+ if (Float.isNaN(mLastFrequencyHz)) {
mLastFrequencyHz = frequencyHz;
}
@@ -1894,6 +1964,7 @@ public abstract class VibrationEffect implements Parcelable {
* calling this method again.
*
* @return The {@link VibrationEffect} resulting from the list of control points.
+ * @throws IllegalStateException if no control points were added to the builder.
*/
@FlaggedApi(Flags.FLAG_NORMALIZED_PWLE_EFFECTS)
@NonNull
diff --git a/core/java/android/os/Vibrator.java b/core/java/android/os/Vibrator.java
index 53f8a9267499340ac7ee551bbac438fcd02c362c..86209140ce51c30ef7c72380c3169147fa51d4da 100644
--- a/core/java/android/os/Vibrator.java
+++ b/core/java/android/os/Vibrator.java
@@ -35,6 +35,7 @@ import android.media.AudioAttributes;
import android.os.vibrator.Flags;
import android.os.vibrator.VendorVibrationSession;
import android.os.vibrator.VibrationConfig;
+import android.os.vibrator.VibratorEnvelopeEffectInfo;
import android.os.vibrator.VibratorFrequencyProfile;
import android.os.vibrator.VibratorFrequencyProfileLegacy;
import android.util.Log;
@@ -137,6 +138,9 @@ public abstract class Vibrator {
@Nullable
private volatile VibrationConfig mVibrationConfig;
+ private VibratorFrequencyProfile mVibratorFrequencyProfile;
+ private VibratorEnvelopeEffectInfo mVibratorEnvelopeEffectInfo;
+
/**
* @hide to prevent subclassing from outside of the framework
*/
@@ -351,7 +355,11 @@ public abstract class Vibrator {
return null;
}
- return new VibratorFrequencyProfile(frequencyProfile);
+ if (mVibratorFrequencyProfile == null) {
+ mVibratorFrequencyProfile = new VibratorFrequencyProfile(frequencyProfile);
+ }
+
+ return mVibratorFrequencyProfile;
}
/**
@@ -383,70 +391,28 @@ public abstract class Vibrator {
}
/**
- * Retrieves the maximum duration supported for an envelope effect, in milliseconds.
- *
- *
If the device supports envelope effects (check {@link #areEnvelopeEffectsSupported}),
- * this value will be positive. Devices with envelope effects capabilities guarantees a
- * maximum duration equivalent to the product of {@link #getMaxEnvelopeEffectSize()} and
- * {@link #getMaxEnvelopeEffectControlPointDurationMillis()}. If the device does not support
- * envelope effects, this method will return 0.
- *
- * @return The maximum duration (in milliseconds) allowed for an envelope effect, or 0 if
- * envelope effects are not supported.
- */
- @FlaggedApi(Flags.FLAG_NORMALIZED_PWLE_EFFECTS)
- public int getMaxEnvelopeEffectDurationMillis() {
- return getInfo().getMaxEnvelopeEffectDurationMillis();
- }
-
- /**
- * Retrieves the maximum number of control points supported for an envelope effect.
- *
- *
If the device supports envelope effects (check {@link #areEnvelopeEffectsSupported}),
- * this value will be positive. Devices with envelope effects capabilities guarantee support
- * for a minimum of 16 control points. If the device does not support envelope effects,
- * this method will return 0.
+ * Retrieves the vibrator's capabilities and limitations for envelope effects.
*
- * @return the maximum number of control points allowed for an envelope effect, or 0 if
- * envelope effects are not supported.
- */
- @FlaggedApi(Flags.FLAG_NORMALIZED_PWLE_EFFECTS)
- public int getMaxEnvelopeEffectSize() {
- return getInfo().getMaxEnvelopeEffectSize();
- }
-
- /**
- * Retrieves the minimum duration supported between two control points within an envelope
- * effect, in milliseconds.
+ *
These parameters can be used with {@link VibrationEffect.WaveformEnvelopeBuilder}
+ * to create custom envelope effects.
*
- *
If the device supports envelope effects (check {@link #areEnvelopeEffectsSupported}),
- * this value will be positive. Devices with envelope effects capabilities guarantee
- * support for durations down to at least 20 milliseconds. If the device does
- * not support envelope effects, this method will return 0.
+ * @return The vibrator's envelope effect information, or null if not supported. If this
+ * vibrator is a composite of multiple physical devices then this will return a profile
+ * supported in all devices, or null if the intersection is empty or not available.
*
- * @return the minimum allowed duration between two control points in an envelope effect,
- * or 0 if envelope effects are not supported.
+ * @see VibrationEffect.WaveformEnvelopeBuilder
*/
@FlaggedApi(Flags.FLAG_NORMALIZED_PWLE_EFFECTS)
- public int getMinEnvelopeEffectControlPointDurationMillis() {
- return getInfo().getMinEnvelopeEffectControlPointDurationMillis();
- }
+ @NonNull
+ public VibratorEnvelopeEffectInfo getEnvelopeEffectInfo() {
+ if (mVibratorEnvelopeEffectInfo == null) {
+ mVibratorEnvelopeEffectInfo = new VibratorEnvelopeEffectInfo(
+ getInfo().getMaxEnvelopeEffectSize(),
+ getInfo().getMinEnvelopeEffectControlPointDurationMillis(),
+ getInfo().getMaxEnvelopeEffectControlPointDurationMillis());
+ }
- /**
- * Retrieves the maximum duration supported between two control points within an envelope
- * effect, in milliseconds.
- *
- *
If the device supports envelope effects (check {@link #areEnvelopeEffectsSupported}),
- * this value will be positive. Devices with envelope effects capabilities guarantee support
- * for durations up to at least 1 second. If the device does not support envelope effects,
- * this method will return 0.
- *
- * @return the maximum allowed duration between two control points in an envelope effect,
- * or 0 if envelope effects are not supported.
- */
- @FlaggedApi(Flags.FLAG_NORMALIZED_PWLE_EFFECTS)
- public int getMaxEnvelopeEffectControlPointDurationMillis() {
- return getInfo().getMaxEnvelopeEffectControlPointDurationMillis();
+ return mVibratorEnvelopeEffectInfo;
}
/**
diff --git a/core/java/android/os/VibratorInfo.java b/core/java/android/os/VibratorInfo.java
index 9dec8673f0192e649cbf8e987a08fcc698c12bb4..84325a4ac70b1cb7a4bfb2a5a88d777452318d63 100644
--- a/core/java/android/os/VibratorInfo.java
+++ b/core/java/android/os/VibratorInfo.java
@@ -121,7 +121,7 @@ public class VibratorInfo implements Parcelable {
* @param qFactor The vibrator quality factor.
* @param frequencyProfileLegacy The description of the vibrator supported frequencies and max
* amplitude mappings.
- * @param frequencyProfile The description of the vibrator supported frequencies and
+ * @param frequencyProfile The description of the vibrator supported frequencies and
* output acceleration mappings.
* @param maxEnvelopeEffectSize The maximum number of control points supported for an
* envelope effect.
diff --git a/core/java/android/os/WorkSource.java b/core/java/android/os/WorkSource.java
index 6d4e28403908bea64b4180f85d0091e81886760e..517418a717fb041ee6448118b657ffa4f0f4130c 100644
--- a/core/java/android/os/WorkSource.java
+++ b/core/java/android/os/WorkSource.java
@@ -1011,13 +1011,7 @@ public class WorkSource implements Parcelable {
return mTags.length > 0 ? mTags[0] : null;
}
- // TODO: The following three trivial getters are purely for testing and will be removed
- // once we have higher level logic in place, e.g for serializing this WorkChain to a proto,
- // diffing it etc.
-
-
/** @hide */
- @VisibleForTesting
public int[] getUids() {
int[] uids = new int[mSize];
System.arraycopy(mUids, 0, uids, 0, mSize);
@@ -1025,7 +1019,6 @@ public class WorkSource implements Parcelable {
}
/** @hide */
- @VisibleForTesting
public String[] getTags() {
String[] tags = new String[mSize];
System.arraycopy(mTags, 0, tags, 0, mSize);
@@ -1033,7 +1026,6 @@ public class WorkSource implements Parcelable {
}
/** @hide */
- @VisibleForTesting
public int getSize() {
return mSize;
}
diff --git a/core/java/android/os/flags.aconfig b/core/java/android/os/flags.aconfig
index d9db28e0b3c3885fb96263125f3e9449f54298e3..9b1bf057b81574654ec1e193be7eb79a36df77e7 100644
--- a/core/java/android/os/flags.aconfig
+++ b/core/java/android/os/flags.aconfig
@@ -3,6 +3,15 @@ container: "system"
container: "system"
# keep-sorted start block=yes newline_separated=yes
+flag {
+ # Holdback study for concurrent MessageQueue.
+ # Do not promote beyond trunkfood.
+ namespace: "system_performance"
+ name: "message_queue_force_legacy"
+ description: "Whether to holdback concurrent MessageQueue (force legacy)."
+ bug: "336880969"
+}
+
flag {
name: "adpf_gpu_report_actual_work_duration"
is_exported: true
@@ -65,6 +74,14 @@ flag {
bug: "315894228"
}
+flag {
+ name: "adpf_use_load_hints"
+ namespace: "game"
+ description: "Guards use of the ADPF public load hints behind a readonly flag"
+ is_fixed_read_only: true
+ bug: "367803904"
+}
+
flag {
name: "allow_consentless_bugreport_delegated_consent"
namespace: "crumpet"
@@ -147,6 +164,13 @@ flag {
bug: "361157077"
}
+flag {
+ name: "cpu_gpu_headrooms"
+ namespace: "game"
+ description: "Feature flag for adding CPU/GPU headroom API"
+ bug: "346604998"
+}
+
flag {
name: "disallow_cellular_null_ciphers_restriction"
namespace: "cellular_security"
@@ -178,6 +202,17 @@ flag {
bug: "366598445"
}
+flag {
+ name: "material_colors_10_2024"
+ namespace: "systemui"
+ description: "Adding new Material Tokens as of October 2024"
+ bug: "376195115"
+ is_exported: true
+ metadata {
+ purpose: PURPOSE_FEATURE
+ }
+}
+
flag {
name: "message_queue_tail_tracking"
namespace: "system_performance"
@@ -251,6 +286,15 @@ flag {
bug: "377557749"
}
+flag {
+ namespace: "system_performance"
+ name: "enable_has_binders"
+ is_exported: true
+ description: "Add hasBinders to Public API under a flag."
+ is_fixed_read_only: true
+ bug: "330345513"
+}
+
flag {
namespace: "system_performance"
name: "perfetto_sdk_tracing"
diff --git a/core/java/android/os/health/SystemHealthManager.java b/core/java/android/os/health/SystemHealthManager.java
index deabfed365a6a4a5e5573de2a13badeabdc11f8b..4db9bc333e2bff9a872edf3a02fd018cdfcfa673 100644
--- a/core/java/android/os/health/SystemHealthManager.java
+++ b/core/java/android/os/health/SystemHealthManager.java
@@ -17,6 +17,7 @@
package android.os.health;
import android.annotation.FlaggedApi;
+import android.annotation.FloatRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemService;
@@ -25,6 +26,11 @@ import android.content.Context;
import android.os.BatteryStats;
import android.os.Build;
import android.os.Bundle;
+import android.os.CpuHeadroomParams;
+import android.os.CpuHeadroomParamsInternal;
+import android.os.GpuHeadroomParams;
+import android.os.GpuHeadroomParamsInternal;
+import android.os.IHintManager;
import android.os.IPowerStatsService;
import android.os.OutcomeReceiver;
import android.os.PowerMonitor;
@@ -68,6 +74,8 @@ public class SystemHealthManager {
private final IBatteryStats mBatteryStats;
@Nullable
private final IPowerStatsService mPowerStats;
+ @Nullable
+ private final IHintManager mHintManager;
private List mPowerMonitorsInfo;
private final Object mPowerMonitorsLock = new Object();
private static final long TAKE_UID_SNAPSHOT_TIMEOUT_MILLIS = 10_000;
@@ -88,14 +96,111 @@ public class SystemHealthManager {
public SystemHealthManager() {
this(IBatteryStats.Stub.asInterface(ServiceManager.getService(BatteryStats.SERVICE_NAME)),
IPowerStatsService.Stub.asInterface(
- ServiceManager.getService(Context.POWER_STATS_SERVICE)));
+ ServiceManager.getService(Context.POWER_STATS_SERVICE)),
+ IHintManager.Stub.asInterface(
+ ServiceManager.getService(Context.PERFORMANCE_HINT_SERVICE)));
}
/** {@hide} */
public SystemHealthManager(@NonNull IBatteryStats batteryStats,
- @Nullable IPowerStatsService powerStats) {
+ @Nullable IPowerStatsService powerStats, @Nullable IHintManager hintManager) {
mBatteryStats = batteryStats;
mPowerStats = powerStats;
+ mHintManager = hintManager;
+ }
+
+ /**
+ * Provides an estimate of global available CPU headroom of the calling thread.
+ *
+ *
+ * @param params params to customize the CPU headroom calculation, null to use default params.
+ * @return a single value a {@code Float.NaN} if it's temporarily unavailable.
+ * A valid value is ranged from [0, 100], where 0 indicates no more CPU resources can be
+ * granted.
+ * @throws UnsupportedOperationException if the API is unsupported or the request params can't
+ * be served.
+ */
+ @FlaggedApi(android.os.Flags.FLAG_CPU_GPU_HEADROOMS)
+ public @FloatRange(from = 0f, to = 100f) float getCpuHeadroom(
+ @Nullable CpuHeadroomParams params) {
+ if (mHintManager == null) {
+ throw new UnsupportedOperationException();
+ }
+ try {
+ return mHintManager.getCpuHeadroom(
+ params != null ? params.getInternal() : new CpuHeadroomParamsInternal())[0];
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
+
+
+
+ /**
+ * Provides an estimate of global available GPU headroom of the device.
+ *
+ *
+ * @param params params to customize the GPU headroom calculation, null to use default params.
+ * @return a single value headroom or a {@code Float.NaN} if it's temporarily unavailable.
+ * A valid value is ranged from [0, 100], where 0 indicates no more GPU resources can be
+ * granted.
+ * @throws UnsupportedOperationException if the API is unsupported or the request params can't
+ * be served.
+ */
+ @FlaggedApi(android.os.Flags.FLAG_CPU_GPU_HEADROOMS)
+ public @FloatRange(from = 0f, to = 100f) float getGpuHeadroom(
+ @Nullable GpuHeadroomParams params) {
+ if (mHintManager == null) {
+ throw new UnsupportedOperationException();
+ }
+ try {
+ return mHintManager.getGpuHeadroom(
+ params != null ? params.getInternal() : new GpuHeadroomParamsInternal());
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Minimum polling interval for calling {@link #getCpuHeadroom(CpuHeadroomParams)} in
+ * milliseconds.
+ *
+ * The {@link #getCpuHeadroom(CpuHeadroomParams)} API may return cached result if called more
+ * frequent than the interval.
+ *
+ * @throws UnsupportedOperationException if the API is unsupported.
+ */
+ @FlaggedApi(android.os.Flags.FLAG_CPU_GPU_HEADROOMS)
+ public long getCpuHeadroomMinIntervalMillis() {
+ if (mHintManager == null) {
+ throw new UnsupportedOperationException();
+ }
+ try {
+ return mHintManager.getCpuHeadroomMinIntervalMillis();
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Minimum polling interval for calling {@link #getGpuHeadroom(GpuHeadroomParams)} in
+ * milliseconds.
+ *
+ * The {@link #getGpuHeadroom(GpuHeadroomParams)} API may return cached result if called more
+ * frequent than the interval.
+ *
+ * @throws UnsupportedOperationException if the API is unsupported.
+ */
+ @FlaggedApi(android.os.Flags.FLAG_CPU_GPU_HEADROOMS)
+ public long getGpuHeadroomMinIntervalMillis() {
+ if (mHintManager == null) {
+ throw new UnsupportedOperationException();
+ }
+ try {
+ return mHintManager.getGpuHeadroomMinIntervalMillis();
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
}
/**
@@ -261,7 +366,7 @@ public class SystemHealthManager {
mPowerMonitorsInfo = result;
}
if (executor != null) {
- executor.execute(()-> onResult.accept(result));
+ executor.execute(() -> onResult.accept(result));
} else {
onResult.accept(result);
}
diff --git a/core/java/android/os/vibrator/PrimitiveSegment.java b/core/java/android/os/vibrator/PrimitiveSegment.java
index 91653edd1ba57b0a56db570e9f366fec4ef3a3f8..889d735c1d39d5e440cc192548872022325b32a7 100644
--- a/core/java/android/os/vibrator/PrimitiveSegment.java
+++ b/core/java/android/os/vibrator/PrimitiveSegment.java
@@ -26,6 +26,7 @@ import android.os.VibratorInfo;
import com.android.internal.util.Preconditions;
+import java.util.Locale;
import java.util.Objects;
/**
@@ -43,19 +44,29 @@ public final class PrimitiveSegment extends VibrationEffectSegment {
/** @hide */
public static final int DEFAULT_DELAY_MILLIS = 0;
+ /** @hide */
+ public static final int DEFAULT_DELAY_TYPE = VibrationEffect.Composition.DELAY_TYPE_PAUSE;
+
private final int mPrimitiveId;
private final float mScale;
private final int mDelay;
+ private final int mDelayType;
PrimitiveSegment(@NonNull Parcel in) {
- this(in.readInt(), in.readFloat(), in.readInt());
+ this(in.readInt(), in.readFloat(), in.readInt(), in.readInt());
}
/** @hide */
public PrimitiveSegment(int id, float scale, int delay) {
+ this(id, scale, delay, DEFAULT_DELAY_TYPE);
+ }
+
+ /** @hide */
+ public PrimitiveSegment(int id, float scale, int delay, int delayType) {
mPrimitiveId = id;
mScale = scale;
mDelay = delay;
+ mDelayType = delayType;
}
public int getPrimitiveId() {
@@ -70,6 +81,11 @@ public final class PrimitiveSegment extends VibrationEffectSegment {
return mDelay;
}
+ /** @hide */
+ public int getDelayType() {
+ return mDelayType;
+ }
+
@Override
public long getDuration() {
return -1;
@@ -112,8 +128,7 @@ public final class PrimitiveSegment extends VibrationEffectSegment {
if (Float.compare(mScale, newScale) == 0) {
return this;
}
-
- return new PrimitiveSegment(mPrimitiveId, newScale, mDelay);
+ return new PrimitiveSegment(mPrimitiveId, newScale, mDelay, mDelayType);
}
/** @hide */
@@ -124,8 +139,7 @@ public final class PrimitiveSegment extends VibrationEffectSegment {
if (Float.compare(mScale, newScale) == 0) {
return this;
}
-
- return new PrimitiveSegment(mPrimitiveId, newScale, mDelay);
+ return new PrimitiveSegment(mPrimitiveId, newScale, mDelay, mDelayType);
}
/** @hide */
@@ -142,6 +156,7 @@ public final class PrimitiveSegment extends VibrationEffectSegment {
VibrationEffect.Composition.PRIMITIVE_LOW_TICK, "primitiveId");
Preconditions.checkArgumentInRange(mScale, 0f, 1f, "scale");
VibrationEffectSegment.checkDurationArgument(mDelay, "delay");
+ Preconditions.checkArgument(isValidDelayType(mDelayType), "delayType");
}
@Override
@@ -150,6 +165,7 @@ public final class PrimitiveSegment extends VibrationEffectSegment {
dest.writeInt(mPrimitiveId);
dest.writeFloat(mScale);
dest.writeInt(mDelay);
+ dest.writeInt(mDelayType);
}
@Override
@@ -163,14 +179,16 @@ public final class PrimitiveSegment extends VibrationEffectSegment {
+ "primitive=" + VibrationEffect.Composition.primitiveToString(mPrimitiveId)
+ ", scale=" + mScale
+ ", delay=" + mDelay
+ + ", delayType=" + VibrationEffect.Composition.delayTypeToString(mDelayType)
+ '}';
}
/** @hide */
@Override
public String toDebugString() {
- return String.format("Primitive=%s(scale=%.2f, delay=%dms)",
- VibrationEffect.Composition.primitiveToString(mPrimitiveId), mScale, mDelay);
+ return String.format(Locale.ROOT, "Primitive=%s(scale=%.2f, %s=%dms)",
+ VibrationEffect.Composition.primitiveToString(mPrimitiveId), mScale,
+ toDelayTypeDebugString(mDelayType), mDelay);
}
@Override
@@ -180,12 +198,28 @@ public final class PrimitiveSegment extends VibrationEffectSegment {
PrimitiveSegment that = (PrimitiveSegment) o;
return mPrimitiveId == that.mPrimitiveId
&& Float.compare(that.mScale, mScale) == 0
- && mDelay == that.mDelay;
+ && mDelay == that.mDelay
+ && mDelayType == that.mDelayType;
}
@Override
public int hashCode() {
- return Objects.hash(mPrimitiveId, mScale, mDelay);
+ return Objects.hash(mPrimitiveId, mScale, mDelay, mDelayType);
+ }
+
+ private static boolean isValidDelayType(int delayType) {
+ return switch (delayType) {
+ case VibrationEffect.Composition.DELAY_TYPE_PAUSE,
+ VibrationEffect.Composition.DELAY_TYPE_RELATIVE_START_OFFSET -> true;
+ default -> false;
+ };
+ }
+
+ private static String toDelayTypeDebugString(int delayType) {
+ return switch (delayType) {
+ case VibrationEffect.Composition.DELAY_TYPE_RELATIVE_START_OFFSET -> "startOffset";
+ default -> "pause";
+ };
}
@NonNull
diff --git a/core/java/android/os/vibrator/VibratorEnvelopeEffectInfo.java b/core/java/android/os/vibrator/VibratorEnvelopeEffectInfo.java
new file mode 100644
index 0000000000000000000000000000000000000000..afaab55f4ed470ff0ec79f48d4abcb1aae1b0fbe
--- /dev/null
+++ b/core/java/android/os/vibrator/VibratorEnvelopeEffectInfo.java
@@ -0,0 +1,197 @@
+/*
+ * 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.os.vibrator;
+
+import android.annotation.FlaggedApi;
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.VibrationEffect;
+
+import java.util.Objects;
+
+/**
+ * Provides information about the vibrator hardware capabilities and limitations regarding
+ * waveform envelope effects. This includes:
+ *
+ * - Maximum number of control points supported.
+ *
- Minimum and maximum duration for individual segments.
+ *
- Maximum total duration for an envelope effect.
+ *
+ *
+ * This information can be used to help construct waveform envelope effects with
+ * {@link VibrationEffect.WaveformEnvelopeBuilder}. When designing these effects, it is also
+ * recommended to check the {@link VibratorFrequencyProfile} for information about the supported
+ * frequency range and the vibrator's output response.
+ *
+ * @see VibrationEffect.WaveformEnvelopeBuilder
+ * @see VibratorFrequencyProfile
+ */
+@FlaggedApi(Flags.FLAG_NORMALIZED_PWLE_EFFECTS)
+public final class VibratorEnvelopeEffectInfo implements Parcelable {
+ private final int mMaxSize;
+ private final long mMinControlPointDurationMillis;
+ private final long mMaxControlPointDurationMillis;
+
+ VibratorEnvelopeEffectInfo(Parcel in) {
+ mMaxSize = in.readInt();
+ mMinControlPointDurationMillis = in.readLong();
+ mMaxControlPointDurationMillis = in.readLong();
+ }
+
+ /**
+ * Default constructor.
+ *
+ * @param maxSize The maximum number of control points supported for an
+ * envelope effect.
+ * @param minControlPointDurationMillis The minimum duration supported between two control
+ * points within an envelope effect.
+ * @param maxControlPointDurationMillis The maximum duration supported between two control
+ * points within an envelope effect.
+ * @hide
+ */
+ public VibratorEnvelopeEffectInfo(int maxSize,
+ long minControlPointDurationMillis,
+ long maxControlPointDurationMillis) {
+ mMaxSize = maxSize;
+ mMinControlPointDurationMillis = minControlPointDurationMillis;
+ mMaxControlPointDurationMillis = maxControlPointDurationMillis;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeInt(mMaxSize);
+ dest.writeLong(mMinControlPointDurationMillis);
+ dest.writeLong(mMaxControlPointDurationMillis);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof VibratorEnvelopeEffectInfo)) {
+ return false;
+ }
+ VibratorEnvelopeEffectInfo other = (VibratorEnvelopeEffectInfo) o;
+ return mMaxSize == other.mMaxSize
+ && mMinControlPointDurationMillis == other.mMinControlPointDurationMillis
+ && mMaxControlPointDurationMillis == other.mMaxControlPointDurationMillis;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mMaxSize,
+ mMinControlPointDurationMillis,
+ mMaxControlPointDurationMillis);
+ }
+
+ @Override
+ public String toString() {
+ return "VibratorEnvelopeEffectInfo{"
+ + ", mMaxSize=" + mMaxSize
+ + ", mMinControlPointDurationMillis=" + mMinControlPointDurationMillis
+ + ", mMaxControlPointDurationMillis=" + mMaxControlPointDurationMillis
+ + '}';
+ }
+
+ @NonNull
+ public static final Creator CREATOR =
+ new Creator() {
+ @Override
+ public VibratorEnvelopeEffectInfo createFromParcel(Parcel in) {
+ return new VibratorEnvelopeEffectInfo(in);
+ }
+
+ @Override
+ public VibratorEnvelopeEffectInfo[] newArray(int size) {
+ return new VibratorEnvelopeEffectInfo[size];
+ }
+ };
+
+ /**
+ * Retrieves the maximum duration supported for an envelope effect, in milliseconds.
+ *
+ * If the device supports envelope effects
+ * (check {@link android.os.VibratorInfo#areEnvelopeEffectsSupported}), this value will be
+ * positive. Devices with envelope effects capabilities guarantees a maximum duration
+ * equivalent to the product of {@link #getMaxSize()} and
+ * {@link #getMaxControlPointDurationMillis()}. If the device does not support
+ * envelope effects, this method will return 0.
+ *
+ * @return The maximum duration (in milliseconds) allowed for an envelope effect, or 0 if
+ * envelope effects are not supported.
+ */
+ public long getMaxDurationMillis() {
+ return mMaxSize * mMaxControlPointDurationMillis;
+ }
+
+ /**
+ * Retrieves the maximum number of control points supported for an envelope effect.
+ *
+ *
If the device supports envelope effects
+ * (check {@link android.os.VibratorInfo#areEnvelopeEffectsSupported}), this value will be
+ * positive. Devices with envelope effects capabilities guarantee support for a minimum of
+ * 16 control points. If the device does not support envelope effects, this method will
+ * return 0.
+ *
+ * @return the maximum number of control points allowed for an envelope effect, or 0 if
+ * envelope effects are not supported.
+ */
+ public int getMaxSize() {
+ return mMaxSize;
+ }
+
+ /**
+ * Retrieves the minimum duration supported between two control points within an envelope
+ * effect, in milliseconds.
+ *
+ *
If the device supports envelope effects
+ * (check {@link android.os.VibratorInfo#areEnvelopeEffectsSupported}), this value will be
+ * positive. Devices with envelope effects capabilities guarantee support for durations down
+ * to at least 20 milliseconds. If the device does not support envelope effects,
+ * this method will return 0.
+ *
+ * @return the minimum allowed duration between two control points in an envelope effect,
+ * or 0 if envelope effects are not supported.
+ */
+ public long getMinControlPointDurationMillis() {
+ return mMinControlPointDurationMillis;
+ }
+
+ /**
+ * Retrieves the maximum duration supported between two control points within an envelope
+ * effect, in milliseconds.
+ *
+ *
If the device supports envelope effects
+ * (check {@link android.os.VibratorInfo#areEnvelopeEffectsSupported}), this value will be
+ * positive. Devices with envelope effects capabilities guarantee support for durations up to
+ * at least 1 second. If the device does not support envelope effects, this method
+ * will return 0.
+ *
+ * @return the maximum allowed duration between two control points in an envelope effect,
+ * or 0 if envelope effects are not supported.
+ */
+ public long getMaxControlPointDurationMillis() {
+ return mMaxControlPointDurationMillis;
+ }
+}
diff --git a/core/java/android/permission/flags.aconfig b/core/java/android/permission/flags.aconfig
index 60a0ae3f107dc044529c594bf9ac5f0a4dba5a2f..0a35fe3995318d505d6ea18f006d506d92e89fd2 100644
--- a/core/java/android/permission/flags.aconfig
+++ b/core/java/android/permission/flags.aconfig
@@ -284,7 +284,7 @@ flag {
is_fixed_read_only: true
is_exported: true
namespace: "android_health_services"
- description: "This fixed read-only flag is used to enable replacing permission BODY_SENSORS (and BODY_SENSORS_BACKGROUND) with granular health permission READ_HEART_RATE (and READ_HEALTH_DATA_IN_BACKGROUND)"
+ description: "Enables replacement of BODY_SENSORS/BODY_SENSORS_BACKGROUND permissions with granular health permissions READ_HEART_RATE, READ_SKIN_TEMPERATURE, READ_OXYGEN_SATURATION, and READ_HEALTH_DATA_IN_BACKGROUND"
bug: "364638912"
}
@@ -299,24 +299,6 @@ flag {
}
}
-flag {
- name: "platform_skin_temperature_enabled"
- is_fixed_read_only: true
- is_exported: true
- namespace: "android_health_services"
- description: "This fixed read-only flag is used to enable platform support for Skin Temperature."
- bug: "369872443"
-}
-
-flag {
- name: "platform_oxygen_saturation_enabled"
- is_fixed_read_only: true
- is_exported: true
- namespace: "android_health_services"
- description: "This fixed read-only flag is used to enable platform support for Oxygen Saturation (SpO2)."
- bug: "369873227"
-}
-
flag {
name: "allow_host_permission_dialogs_on_virtual_devices"
is_exported: true
@@ -386,3 +368,44 @@ flag {
description: "This fixed read-only flag is used to enable new ranging permission for all ranging use cases."
bug: "370977414"
}
+
+flag {
+ name: "system_selection_toolbar_enabled"
+ namespace: "permissions"
+ description: "Enables the system selection toolbar feature."
+ bug: "363318732"
+}
+
+flag {
+ name: "use_system_selection_toolbar_in_sysui"
+ namespace: "permissions"
+ description: "Uses the SysUi process to host the SelectionToolbarRenderService."
+ bug: "363318732"
+}
+
+flag{
+ name: "note_op_batching_enabled"
+ is_fixed_read_only: true
+ is_exported: true
+ namespace: "permissions"
+ description: "Batch noteOperations on the client to reduce binder call volume"
+ bug: "366013082"
+}
+
+flag {
+ name: "supervision_role_permission_update_enabled"
+ is_fixed_read_only: true
+ is_exported: true
+ namespace: "supervision"
+ description: "This flag is used to enable all the remaining permissions required to the supervision role"
+ bug: "367333883"
+}
+
+flag {
+ name: "permission_request_short_circuit_enabled"
+ is_fixed_read_only: true
+ is_exported: true
+ namespace: "permissions"
+ description: "This flag is used to short circuit the request for permananently denied permissions"
+ bug: "378923900"
+}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index ef351719ea70b5d290651fb9f594b27077c662aa..a35c9c1cd4ece87f7553eb9364c9ca965f6f0298 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1216,6 +1216,69 @@ public final class Settings {
public static final String ACTION_REGIONAL_PREFERENCES_SETTINGS =
"android.settings.REGIONAL_PREFERENCES_SETTINGS";
+ /**
+ * Activity Action: Show screen for allowing the region configuration.
+ *
+ * Input: Nothing.
+ *
+ * Output: Nothing.
+ */
+ @FlaggedApi(Flags.FLAG_SYSTEM_REGIONAL_PREFERENCES_API_ENABLED)
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_REGION_SETTINGS =
+ "android.settings.REGION_SETTINGS";
+
+ /**
+ * Activity Action: Show first day of week configuration settings.
+ *
+ * Input: Nothing.
+ *
+ * Output: Nothing.
+ */
+ @FlaggedApi(Flags.FLAG_SYSTEM_REGIONAL_PREFERENCES_API_ENABLED)
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_FIRST_DAY_OF_WEEK_SETTINGS =
+ "android.settings.FIRST_DAY_OF_WEEK_SETTINGS";
+
+ /**
+ * Activity Action: Show temperature unit configuration settings.
+ *
+ * Input: Nothing.
+ *
+ * Output: Nothing.
+ */
+ @FlaggedApi(Flags.FLAG_SYSTEM_REGIONAL_PREFERENCES_API_ENABLED)
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_TEMPERATURE_UNIT_SETTINGS =
+ "android.settings.TEMPERATURE_UNIT_SETTINGS";
+
+ /**
+ * Activity Action: Show numbering system configuration settings.
+ *
+ * In some cases, a matching Activity may not exist, so ensure you
+ * safeguard against this.
+ *
+ * Input: Nothing.
+ *
+ * Output: Nothing.
+ */
+ @FlaggedApi(Flags.FLAG_SYSTEM_REGIONAL_PREFERENCES_API_ENABLED)
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_NUMBERING_SYSTEM_SETTINGS =
+ "android.settings.NUMBERING_SYSTEM_SETTINGS";
+
+ /**
+ * Activity Action: Show measurement system configuration settings.
+ *
+ * Input: Nothing.
+ *
+ * Output: Nothing.
+ */
+ @FlaggedApi(Flags.FLAG_SYSTEM_REGIONAL_PREFERENCES_API_ENABLED)
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_MEASUREMENT_SYSTEM_SETTINGS =
+ "android.settings.MEASUREMENT_SYSTEM_SETTINGS";
+
/**
* Activity Action: Show settings to allow configuration of lockscreen.
*
@@ -6332,27 +6395,6 @@ public final class Settings {
public static final String SCREEN_FLASH_NOTIFICATION_COLOR =
"screen_flash_notification_color_global";
-
- /**
- * A semi-colon separated list of Bluetooth hearing devices' local ambient volume.
- * Each entry is encoded as a key=value list, separated by commas. Ex:
- *
- * "addr=XX:XX:XX:00:11,ambient=20,group_ambient=30;addr=XX:XX:XX:00:22,ambient=50"
- *
- * The following keys are supported:
- *
- * addr (String)
- * ambient (int)
- * group_ambient (int)
- * control_expanded (boolean)
- *
- *
- * Each entry must contains "addr" attribute, otherwise it'll be ignored.
- * @hide
- */
- public static final String HEARING_DEVICE_LOCAL_AMBIENT_VOLUME =
- "hearing_device_local_ambient_volume";
-
/**
* IMPORTANT: If you add a new public settings you also have to add it to
* PUBLIC_SETTINGS below. If the new setting is hidden you have to add
@@ -6497,7 +6539,6 @@ public final class Settings {
PRIVATE_SETTINGS.add(DEFAULT_DEVICE_FONT_SCALE);
PRIVATE_SETTINGS.add(MOUSE_REVERSE_VERTICAL_SCROLLING);
PRIVATE_SETTINGS.add(MOUSE_SWAP_PRIMARY_BUTTON);
- PRIVATE_SETTINGS.add(HEARING_DEVICE_LOCAL_AMBIENT_VOLUME);
}
/**
@@ -18074,6 +18115,44 @@ public final class Settings {
*/
public static final String ONE_HANDED_KEYGUARD_SIDE = "one_handed_keyguard_side";
+ /**
+ * A semi-colon separated list of Bluetooth hearing devices' local ambient volume data.
+ * Each entry is encoded as a key=value list, separated by commas. Ex:
+ *
+ * "addr=XX:XX:XX:00:11,ambient=20,group_ambient=30;addr=XX:XX:XX:00:22,ambient=50"
+ *
+ * The following keys are supported:
+ *
+ * addr (String)
+ * ambient (int)
+ * group_ambient (int)
+ * control_expanded (boolean)
+ *
+ *
+ * Each entry must contains "addr" attribute, otherwise it'll be ignored.
+ * @hide
+ */
+ public static final String HEARING_DEVICE_LOCAL_AMBIENT_VOLUME =
+ "hearing_device_local_ambient_volume";
+
+ /**
+ * A semi-colon separated list of Bluetooth hearing devices' notification data.
+ * Each entry is encoded as a key=value list, separated by commas. Ex:
+ *
+ * "addr=XX:XX:XX:00:11,input_changes=1"
+ *
+ * The following keys are supported:
+ *
+ * addr (String)
+ * input_changes (boolean)
+ *
+ *
+ * Each entry must contains "addr" attribute, otherwise it'll be ignored.
+ * @hide
+ */
+ public static final String HEARING_DEVICE_LOCAL_NOTIFICATION =
+ "hearing_device_local_notification";
+
/**
* Global settings that shouldn't be persisted.
*
diff --git a/core/java/android/provider/flags.aconfig b/core/java/android/provider/flags.aconfig
index 4c636735b5ce2335544d7f7d4192e1a0f1b9d279..fff53637485bf2244ee98eaf0dd249fbcd500b5a 100644
--- a/core/java/android/provider/flags.aconfig
+++ b/core/java/android/provider/flags.aconfig
@@ -63,3 +63,11 @@ flag {
purpose: PURPOSE_BUGFIX
}
}
+
+flag {
+ name: "system_regional_preferences_api_enabled"
+ is_exported: true
+ namespace: "globalintl"
+ description: "Feature flag for regional preferences APIs"
+ bug: "370379000"
+}
diff --git a/core/java/android/security/advancedprotection/AdvancedProtectionManager.java b/core/java/android/security/advancedprotection/AdvancedProtectionManager.java
index 6f3e3d8f0d3b940379815d32a2109cddf98803c7..9fe0dda136d1744441d65104cff1b906968037ba 100644
--- a/core/java/android/security/advancedprotection/AdvancedProtectionManager.java
+++ b/core/java/android/security/advancedprotection/AdvancedProtectionManager.java
@@ -16,20 +16,30 @@
package android.security.advancedprotection;
+import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+
import android.Manifest;
import android.annotation.CallbackExecutor;
import android.annotation.FlaggedApi;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.RequiresPermission;
+import android.annotation.SdkConstant;
+import android.annotation.StringDef;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.content.Context;
+import android.content.Intent;
import android.os.Binder;
import android.os.RemoteException;
import android.security.Flags;
import android.util.Log;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.List;
+import java.util.Objects;
+import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
@@ -45,6 +55,139 @@ import java.util.concurrent.Executor;
public final class AdvancedProtectionManager {
private static final String TAG = "AdvancedProtectionMgr";
+ /**
+ * Advanced Protection's identifier for setting policies or restrictions in DevicePolicyManager.
+ *
+ * @hide */
+ public static final String ADVANCED_PROTECTION_SYSTEM_ENTITY =
+ "android.security.advancedprotection";
+
+ /**
+ * Feature identifier for disallowing 2G.
+ *
+ * @hide */
+ @SystemApi
+ public static final String FEATURE_ID_DISALLOW_CELLULAR_2G =
+ "android.security.advancedprotection.feature_disallow_2g";
+
+ /**
+ * Feature identifier for disallowing install of unknown sources.
+ *
+ * @hide */
+ @SystemApi
+ public static final String FEATURE_ID_DISALLOW_INSTALL_UNKNOWN_SOURCES =
+ "android.security.advancedprotection.feature_disallow_install_unknown_sources";
+
+ /**
+ * Feature identifier for disallowing USB.
+ *
+ * @hide */
+ @SystemApi
+ public static final String FEATURE_ID_DISALLOW_USB =
+ "android.security.advancedprotection.feature_disallow_usb";
+
+ /**
+ * Feature identifier for disallowing WEP.
+ *
+ * @hide */
+ @SystemApi
+ public static final String FEATURE_ID_DISALLOW_WEP =
+ "android.security.advancedprotection.feature_disallow_wep";
+
+ /**
+ * Feature identifier for enabling MTE.
+ *
+ * @hide */
+ @SystemApi
+ public static final String FEATURE_ID_ENABLE_MTE =
+ "android.security.advancedprotection.feature_enable_mte";
+
+ /** @hide */
+ @StringDef(prefix = { "FEATURE_ID_" }, value = {
+ FEATURE_ID_DISALLOW_CELLULAR_2G,
+ FEATURE_ID_DISALLOW_INSTALL_UNKNOWN_SOURCES,
+ FEATURE_ID_DISALLOW_USB,
+ FEATURE_ID_DISALLOW_WEP,
+ FEATURE_ID_ENABLE_MTE,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface FeatureId {}
+
+ private static final Set ALL_FEATURE_IDS = Set.of(
+ FEATURE_ID_DISALLOW_CELLULAR_2G,
+ FEATURE_ID_DISALLOW_INSTALL_UNKNOWN_SOURCES,
+ FEATURE_ID_DISALLOW_USB,
+ FEATURE_ID_DISALLOW_WEP,
+ FEATURE_ID_ENABLE_MTE);
+
+ /**
+ * Activity Action: Show a dialog with disabled by advanced protection message.
+ * If a user action or a setting toggle is disabled by advanced protection, this dialog can
+ * be triggered to let the user know about this.
+ *
+ * Input:
+ *
{@link #EXTRA_SUPPORT_DIALOG_FEATURE}: The feature identifier.
+ *
{@link #EXTRA_SUPPORT_DIALOG_TYPE}: The type of the action.
+ *
+ * Output: Nothing.
+ *
+ * @hide */
+ @SystemApi
+ @SdkConstant(SdkConstant.SdkConstantType.ACTIVITY_INTENT_ACTION)
+ @FlaggedApi(android.security.Flags.FLAG_AAPM_API)
+ public static final String ACTION_SHOW_ADVANCED_PROTECTION_SUPPORT_DIALOG =
+ "android.security.advancedprotection.action.SHOW_ADVANCED_PROTECTION_SUPPORT_DIALOG";
+
+ /**
+ * A string extra used with {@link #createSupportIntent} to identify the feature that needs to
+ * show a support dialog explaining it was disabled by advanced protection.
+ *
+ * @hide */
+ @FeatureId
+ @SystemApi
+ public static final String EXTRA_SUPPORT_DIALOG_FEATURE =
+ "android.security.advancedprotection.extra.SUPPORT_DIALOG_FEATURE";
+
+ /**
+ * A string extra used with {@link #createSupportIntent} to identify the type of the action that
+ * needs to be explained in the support dialog.
+ *
+ * @hide */
+ @SupportDialogType
+ @SystemApi
+ public static final String EXTRA_SUPPORT_DIALOG_TYPE =
+ "android.security.advancedprotection.extra.SUPPORT_DIALOG_TYPE";
+
+ /**
+ * Type for {@link #EXTRA_SUPPORT_DIALOG_TYPE} indicating a user performed an action that was
+ * blocked by advanced protection.
+ *
+ * @hide */
+ @SystemApi
+ public static final String SUPPORT_DIALOG_TYPE_BLOCKED_INTERACTION =
+ "android.security.advancedprotection.type_blocked_interaction";
+
+ /**
+ * Type for {@link #EXTRA_SUPPORT_DIALOG_TYPE} indicating a user pressed on a setting toggle
+ * that was disabled by advanced protection.
+ *
+ * @hide */
+ @SystemApi
+ public static final String SUPPORT_DIALOG_TYPE_DISABLED_SETTING =
+ "android.security.advancedprotection.type_disabled_setting";
+
+ /** @hide */
+ @StringDef(prefix = { "SUPPORT_DIALOG_TYPE_" }, value = {
+ SUPPORT_DIALOG_TYPE_BLOCKED_INTERACTION,
+ SUPPORT_DIALOG_TYPE_DISABLED_SETTING,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface SupportDialogType {}
+
+ private static final Set ALL_SUPPORT_DIALOG_TYPES = Set.of(
+ SUPPORT_DIALOG_TYPE_BLOCKED_INTERACTION,
+ SUPPORT_DIALOG_TYPE_DISABLED_SETTING);
+
private final ConcurrentHashMap
mCallbackMap = new ConcurrentHashMap<>();
@@ -163,6 +306,43 @@ public final class AdvancedProtectionManager {
}
}
+ /**
+ * Called by a feature to display a support dialog when a feature was disabled by advanced
+ * protection. This returns an intent that can be used with
+ * {@link Context#startActivity(Intent)} to display the dialog.
+ *
+ * Note that this method doesn't check if the feature is actually disabled, i.e. this method
+ * will always return an intent.
+ *
+ * @param featureId The feature identifier.
+ * @param type The type of the feature describing the action that needs to be explained
+ * in the dialog or null for default explanation.
+ * @return Intent An intent to be used to start the dialog-activity that explains a feature was
+ * disabled by advanced protection.
+ * @hide
+ */
+ @SystemApi
+ public @NonNull Intent createSupportIntent(@NonNull @FeatureId String featureId,
+ @Nullable @SupportDialogType String type) {
+ Objects.requireNonNull(featureId);
+ if (!ALL_FEATURE_IDS.contains(featureId)) {
+ throw new IllegalArgumentException(featureId + " is not a valid feature ID. See"
+ + " FEATURE_ID_* APIs.");
+ }
+ if (type != null && !ALL_SUPPORT_DIALOG_TYPES.contains(type)) {
+ throw new IllegalArgumentException(type + " is not a valid type. See"
+ + " SUPPORT_DIALOG_TYPE_* APIs.");
+ }
+
+ Intent intent = new Intent(ACTION_SHOW_ADVANCED_PROTECTION_SUPPORT_DIALOG);
+ intent.setFlags(FLAG_ACTIVITY_NEW_TASK);
+ intent.putExtra(EXTRA_SUPPORT_DIALOG_FEATURE, featureId);
+ if (type != null) {
+ intent.putExtra(EXTRA_SUPPORT_DIALOG_TYPE, type);
+ }
+ return intent;
+ }
+
/**
* A callback class for monitoring changes to Advanced Protection state
*
diff --git a/core/java/android/security/flags.aconfig b/core/java/android/security/flags.aconfig
index 7cb0ffcfcc721f89885ab7b16739f60b264730f0..09004b3dcf0328512cc800c3b7005df9309f6e5c 100644
--- a/core/java/android/security/flags.aconfig
+++ b/core/java/android/security/flags.aconfig
@@ -109,11 +109,19 @@ flag {
flag {
name: "afl_api"
- namespace: "platform_security"
+ namespace: "hardware_backed_security"
description: "AFL feature"
bug: "365994454"
}
+flag {
+ name: "protect_device_config_flags"
+ namespace: "psap_ai"
+ description: "Feature flag to limit adb shell to allowlisted flags"
+ bug: "364083026"
+ is_fixed_read_only: true
+}
+
flag {
name: "keystore_grant_api"
namespace: "hardware_backed_security"
diff --git a/core/java/android/security/forensic/ForensicEvent.java b/core/java/android/security/forensic/ForensicEvent.java
index 90906edcc636a2aa36070d49cae279731daebb22..3d908cca150c288e5a3e68387a23f88d9d5cc995 100644
--- a/core/java/android/security/forensic/ForensicEvent.java
+++ b/core/java/android/security/forensic/ForensicEvent.java
@@ -17,13 +17,17 @@
package android.security.forensic;
import android.annotation.FlaggedApi;
+import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.app.admin.ConnectEvent;
+import android.app.admin.DnsEvent;
+import android.app.admin.SecurityLog.SecurityEvent;
import android.os.Parcel;
import android.os.Parcelable;
import android.security.Flags;
-import android.util.ArrayMap;
-import java.util.Map;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
/**
* A class that represents a forensic event.
@@ -33,11 +37,24 @@ import java.util.Map;
public final class ForensicEvent implements Parcelable {
private static final String TAG = "ForensicEvent";
- @NonNull
- private final String mType;
+ public static final int SECURITY_EVENT = 0;
+ public static final int NETWORK_EVENT_DNS = 1;
+ public static final int NETWORK_EVENT_CONNECT = 2;
- @NonNull
- private final Map mKeyValuePairs;
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({
+ ForensicEvent.SECURITY_EVENT,
+ ForensicEvent.NETWORK_EVENT_DNS,
+ ForensicEvent.NETWORK_EVENT_CONNECT,
+ })
+ public @interface EventType {}
+
+ @NonNull @EventType private final int mType;
+
+ private final SecurityEvent mSecurityEvent;
+ private final DnsEvent mNetworkEventDns;
+ private final ConnectEvent mNetworkEventConnect;
public static final @NonNull Parcelable.Creator CREATOR =
new Parcelable.Creator<>() {
@@ -50,30 +67,99 @@ public final class ForensicEvent implements Parcelable {
}
};
- public ForensicEvent(@NonNull String type, @NonNull Map keyValuePairs) {
- mType = type;
- mKeyValuePairs = keyValuePairs;
+ public ForensicEvent(@NonNull SecurityEvent securityEvent) {
+ mType = SECURITY_EVENT;
+ mSecurityEvent = securityEvent;
+ mNetworkEventDns = null;
+ mNetworkEventConnect = null;
+ }
+
+ public ForensicEvent(@NonNull DnsEvent dnsEvent) {
+ mType = NETWORK_EVENT_DNS;
+ mNetworkEventDns = dnsEvent;
+ mSecurityEvent = null;
+ mNetworkEventConnect = null;
+ }
+
+ public ForensicEvent(@NonNull ConnectEvent connectEvent) {
+ mType = NETWORK_EVENT_CONNECT;
+ mNetworkEventConnect = connectEvent;
+ mSecurityEvent = null;
+ mNetworkEventDns = null;
}
private ForensicEvent(@NonNull Parcel in) {
- mType = in.readString();
- mKeyValuePairs = new ArrayMap<>(in.readInt());
- in.readMap(mKeyValuePairs, getClass().getClassLoader(), String.class, String.class);
+ mType = in.readInt();
+ switch (mType) {
+ case SECURITY_EVENT:
+ mSecurityEvent = SecurityEvent.CREATOR.createFromParcel(in);
+ mNetworkEventDns = null;
+ mNetworkEventConnect = null;
+ break;
+ case NETWORK_EVENT_DNS:
+ mNetworkEventDns = DnsEvent.CREATOR.createFromParcel(in);
+ mSecurityEvent = null;
+ mNetworkEventConnect = null;
+ break;
+ case NETWORK_EVENT_CONNECT:
+ mNetworkEventConnect = ConnectEvent.CREATOR.createFromParcel(in);
+ mSecurityEvent = null;
+ mNetworkEventDns = null;
+ break;
+ default:
+ throw new IllegalArgumentException("Invalid event type: " + mType);
+ }
}
- public String getType() {
+ /** Returns the type of the forensic event. */
+ @NonNull
+ public @EventType int getType() {
return mType;
}
- public Map getKeyValuePairs() {
- return mKeyValuePairs;
+ /** Returns the SecurityEvent object. */
+ @NonNull
+ public SecurityEvent getSecurityEvent() {
+ if (mType == SECURITY_EVENT) {
+ return mSecurityEvent;
+ }
+ throw new IllegalArgumentException("Event type is not security event: " + mType);
+ }
+
+ /** Returns the DnsEvent object. */
+ @NonNull
+ public DnsEvent getDnsEvent() {
+ if (mType == NETWORK_EVENT_DNS) {
+ return mNetworkEventDns;
+ }
+ throw new IllegalArgumentException("Event type is not network DNS event: " + mType);
+ }
+
+ /** Returns the ConnectEvent object. */
+ @NonNull
+ public ConnectEvent getConnectEvent() {
+ if (mType == NETWORK_EVENT_CONNECT) {
+ return mNetworkEventConnect;
+ }
+ throw new IllegalArgumentException("Event type is not network connect event: " + mType);
}
@Override
public void writeToParcel(@NonNull Parcel out, int flags) {
- out.writeString(mType);
- out.writeInt(mKeyValuePairs.size());
- out.writeMap(mKeyValuePairs);
+ out.writeInt(mType);
+ switch (mType) {
+ case SECURITY_EVENT:
+ out.writeParcelable(mSecurityEvent, flags);
+ break;
+ case NETWORK_EVENT_DNS:
+ out.writeParcelable(mNetworkEventDns, flags);
+ break;
+ case NETWORK_EVENT_CONNECT:
+ out.writeParcelable(mNetworkEventConnect, flags);
+ break;
+ default:
+ throw new IllegalArgumentException("Invalid event type: " + mType);
+ }
}
@FlaggedApi(Flags.FLAG_AFL_API)
@@ -86,7 +172,6 @@ public final class ForensicEvent implements Parcelable {
public String toString() {
return "ForensicEvent{"
+ "mType=" + mType
- + ", mKeyValuePairs=" + mKeyValuePairs
+ '}';
}
}
diff --git a/core/java/android/security/forensic/ForensicManager.java b/core/java/android/security/forensic/ForensicManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..9126182eda7b32cc70631c7e902de78f8088c585
--- /dev/null
+++ b/core/java/android/security/forensic/ForensicManager.java
@@ -0,0 +1,276 @@
+/*
+ * 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.security.forensic;
+
+import static android.Manifest.permission.MANAGE_FORENSIC_STATE;
+import static android.Manifest.permission.READ_FORENSIC_STATE;
+
+import android.annotation.CallbackExecutor;
+import android.annotation.FlaggedApi;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
+import android.annotation.SystemService;
+import android.content.Context;
+import android.os.RemoteException;
+import android.security.Flags;
+import android.util.Log;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.util.Objects;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Executor;
+import java.util.function.Consumer;
+
+/**
+ * ForensicManager manages the forensic logging on Android devices.
+ * Upon user consent, forensic logging collects various device events for
+ * off-device investigation of potential device compromise.
+ *
+ * Forensic logging can either be enabled ({@link #STATE_ENABLED}
+ * or disabled ({@link #STATE_DISABLED}).
+ *
+ * The Forensic logs will be transferred to
+ * {@link android.security.forensic.ForensicEventTransport}.
+ *
+ * @hide
+ */
+@SystemApi
+@FlaggedApi(Flags.FLAG_AFL_API)
+@SystemService(Context.FORENSIC_SERVICE)
+public class ForensicManager {
+ private static final String TAG = "ForensicManager";
+
+ /** @hide */
+ @Target(ElementType.TYPE_USE)
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = { "STATE_" }, value = {
+ STATE_UNKNOWN,
+ STATE_DISABLED,
+ STATE_ENABLED
+ })
+ public @interface ForensicState {}
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = { "ERROR_" }, value = {
+ ERROR_UNKNOWN,
+ ERROR_PERMISSION_DENIED,
+ ERROR_TRANSPORT_UNAVAILABLE,
+ ERROR_DATA_SOURCE_UNAVAILABLE
+ })
+ public @interface ForensicError {}
+
+ /**
+ * Indicates an unknown state
+ */
+ public static final int STATE_UNKNOWN = IForensicServiceStateCallback.State.UNKNOWN;
+
+ /**
+ * Indicates an state that the forensic is turned off.
+ */
+ public static final int STATE_DISABLED = IForensicServiceStateCallback.State.DISABLED;
+
+ /**
+ * Indicates an state that the forensic is turned on.
+ */
+ public static final int STATE_ENABLED = IForensicServiceStateCallback.State.ENABLED;
+
+ /**
+ * Indicates an unknown error
+ */
+ public static final int ERROR_UNKNOWN = IForensicServiceCommandCallback.ErrorCode.UNKNOWN;
+
+ /**
+ * Indicates an error due to insufficient access rights.
+ */
+ public static final int ERROR_PERMISSION_DENIED =
+ IForensicServiceCommandCallback.ErrorCode.PERMISSION_DENIED;
+
+ /**
+ * Indicates an error due to unavailability of the forensic event transport.
+ */
+ public static final int ERROR_TRANSPORT_UNAVAILABLE =
+ IForensicServiceCommandCallback.ErrorCode.TRANSPORT_UNAVAILABLE;
+
+ /**
+ * Indicates an error due to unavailability of the data source.
+ */
+ public static final int ERROR_DATA_SOURCE_UNAVAILABLE =
+ IForensicServiceCommandCallback.ErrorCode.DATA_SOURCE_UNAVAILABLE;
+
+
+ private final IForensicService mService;
+
+ private final ConcurrentHashMap, IForensicServiceStateCallback>
+ mStateCallbacks = new ConcurrentHashMap<>();
+
+ /**
+ * Constructor
+ *
+ * @param service A valid instance of IForensicService.
+ * @hide
+ */
+ public ForensicManager(IForensicService service) {
+ mService = service;
+ }
+
+ /**
+ * Add a callback to monitor the state of the ForensicService.
+ *
+ * @param executor The executor through which the callback should be invoked.
+ * @param callback The callback for state change.
+ * Once the callback is registered, the callback will be called
+ * to reflect the init state.
+ * The callback can be registered only once.
+ */
+ @RequiresPermission(READ_FORENSIC_STATE)
+ public void addStateCallback(@NonNull @CallbackExecutor Executor executor,
+ @NonNull @ForensicState Consumer callback) {
+ Objects.requireNonNull(executor);
+ Objects.requireNonNull(callback);
+
+ if (mStateCallbacks.get(callback) != null) {
+ Log.d(TAG, "addStateCallback callback already present");
+ return;
+ }
+
+ final IForensicServiceStateCallback wrappedCallback =
+ new IForensicServiceStateCallback.Stub() {
+ @Override
+ public void onStateChange(int state) {
+ executor.execute(() -> callback.accept(state));
+ }
+ };
+ try {
+ mService.addStateCallback(wrappedCallback);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+
+ mStateCallbacks.put(callback, wrappedCallback);
+ }
+
+ /**
+ * Remove a callback to monitor the state of the ForensicService.
+ *
+ * @param callback The callback to remove.
+ */
+ @RequiresPermission(READ_FORENSIC_STATE)
+ public void removeStateCallback(@NonNull Consumer<@ForensicState Integer> callback) {
+ Objects.requireNonNull(callback);
+ if (!mStateCallbacks.containsKey(callback)) {
+ Log.d(TAG, "removeStateCallback callback not present");
+ return;
+ }
+
+ IForensicServiceStateCallback wrappedCallback = mStateCallbacks.get(callback);
+
+ try {
+ mService.removeStateCallback(wrappedCallback);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+
+ mStateCallbacks.remove(callback);
+ }
+
+ /**
+ * Enable forensic logging.
+ * If successful, ForensicService will transition to {@link #STATE_ENABLED} state.
+ *
+ * When forensic logging is enabled, various device events will be collected and
+ * sent over to the registered {@link android.security.forensic.ForensicEventTransport}.
+ *
+ * @param executor The executor through which the callback should be invoked.
+ * @param callback The callback for the command result.
+ */
+ @RequiresPermission(MANAGE_FORENSIC_STATE)
+ public void enable(@NonNull @CallbackExecutor Executor executor,
+ @NonNull CommandCallback callback) {
+ Objects.requireNonNull(executor);
+ Objects.requireNonNull(callback);
+ try {
+ mService.enable(new IForensicServiceCommandCallback.Stub() {
+ @Override
+ public void onSuccess() {
+ executor.execute(callback::onSuccess);
+ }
+
+ @Override
+ public void onFailure(int error) {
+ executor.execute(() -> callback.onFailure(error));
+ }
+ });
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Disable forensic logging.
+ * If successful, ForensicService will transition to {@link #STATE_DISABLED}.
+ *
+ * When forensic logging is disabled, device events will no longer be collected.
+ * Any events that have been collected but not yet sent to ForensicEventTransport
+ * will be transferred as a final batch.
+ *
+ * @param executor The executor through which the callback should be invoked.
+ * @param callback The callback for the command result.
+ */
+ @RequiresPermission(MANAGE_FORENSIC_STATE)
+ public void disable(@NonNull @CallbackExecutor Executor executor,
+ @NonNull CommandCallback callback) {
+ Objects.requireNonNull(executor);
+ Objects.requireNonNull(callback);
+ try {
+ mService.disable(new IForensicServiceCommandCallback.Stub() {
+ @Override
+ public void onSuccess() {
+ executor.execute(callback::onSuccess);
+ }
+
+ @Override
+ public void onFailure(int error) {
+ executor.execute(() -> callback.onFailure(error));
+ }
+ });
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Callback used in {@link #enable} and {@link #disable} to indicate the result of the command.
+ */
+ public interface CommandCallback {
+ /**
+ * Called when command succeeds.
+ */
+ void onSuccess();
+
+ /**
+ * Called when command fails.
+ * @param error The error number.
+ */
+ void onFailure(@ForensicError int error);
+ }
+}
diff --git a/core/java/android/security/forensic/IBackupTransport.aidl b/core/java/android/security/forensic/IForensicEventTransport.aidl
similarity index 96%
rename from core/java/android/security/forensic/IBackupTransport.aidl
rename to core/java/android/security/forensic/IForensicEventTransport.aidl
index c2cbc83ba1b33bc6d552b22b9e5a52ec5299bb95..80e78eb9cf4948fae76a78ae1daf8ae0c98c8ef1 100644
--- a/core/java/android/security/forensic/IBackupTransport.aidl
+++ b/core/java/android/security/forensic/IForensicEventTransport.aidl
@@ -20,7 +20,7 @@ import android.security.forensic.ForensicEvent;
import com.android.internal.infra.AndroidFuture;
/** {@hide} */
-oneway interface IBackupTransport {
+oneway interface IForensicEventTransport {
/**
* Initialize the server side.
*/
diff --git a/core/java/android/security/forensic/IForensicService.aidl b/core/java/android/security/forensic/IForensicService.aidl
index a944b18cb26da4203925491c8eafec4e6d32024b..8039b264f0e5be7b9f943a2689243cc551328461 100644
--- a/core/java/android/security/forensic/IForensicService.aidl
+++ b/core/java/android/security/forensic/IForensicService.aidl
@@ -24,9 +24,12 @@ import android.security.forensic.IForensicServiceStateCallback;
* @hide
*/
interface IForensicService {
- void monitorState(IForensicServiceStateCallback callback);
- void makeVisible(IForensicServiceCommandCallback callback);
- void makeInvisible(IForensicServiceCommandCallback callback);
+ @EnforcePermission("READ_FORENSIC_STATE")
+ void addStateCallback(IForensicServiceStateCallback callback);
+ @EnforcePermission("READ_FORENSIC_STATE")
+ void removeStateCallback(IForensicServiceStateCallback callback);
+ @EnforcePermission("MANAGE_FORENSIC_STATE")
void enable(IForensicServiceCommandCallback callback);
+ @EnforcePermission("MANAGE_FORENSIC_STATE")
void disable(IForensicServiceCommandCallback callback);
}
diff --git a/core/java/android/security/forensic/IForensicServiceCommandCallback.aidl b/core/java/android/security/forensic/IForensicServiceCommandCallback.aidl
index 7fa0c7f726905f9dec5273a162709f98b0c7f613..6d1456ea04261d6d4fffd82f7811a17296e79529 100644
--- a/core/java/android/security/forensic/IForensicServiceCommandCallback.aidl
+++ b/core/java/android/security/forensic/IForensicServiceCommandCallback.aidl
@@ -25,8 +25,8 @@ package android.security.forensic;
UNKNOWN = 0,
PERMISSION_DENIED = 1,
INVALID_STATE_TRANSITION = 2,
- BACKUP_TRANSPORT_UNAVAILABLE = 3,
- DATA_SOURCE_UNAVAILABLE = 3,
+ TRANSPORT_UNAVAILABLE = 3,
+ DATA_SOURCE_UNAVAILABLE = 4,
}
void onSuccess();
void onFailure(ErrorCode error);
diff --git a/core/java/android/security/forensic/IForensicServiceStateCallback.aidl b/core/java/android/security/forensic/IForensicServiceStateCallback.aidl
index 0cda35083ffde9bd374474e6e34057c5c7a2dc8a..1b68c7b14bcac647a552cb0690f8cc9f8dabf973 100644
--- a/core/java/android/security/forensic/IForensicServiceStateCallback.aidl
+++ b/core/java/android/security/forensic/IForensicServiceStateCallback.aidl
@@ -23,9 +23,8 @@ package android.security.forensic;
@Backing(type="int")
enum State{
UNKNOWN = 0,
- INVISIBLE = 1,
- VISIBLE = 2,
- ENABLED = 3,
+ DISABLED = 1,
+ ENABLED = 2,
}
void onStateChange(State state);
}
diff --git a/core/java/android/security/responsible_apis_flags.aconfig b/core/java/android/security/responsible_apis_flags.aconfig
index 66e1f38621ae737eb658f3e0da69b24a6565199c..6c92991ceff6a4c8bca980c58ac7ac4a7077c4c6 100644
--- a/core/java/android/security/responsible_apis_flags.aconfig
+++ b/core/java/android/security/responsible_apis_flags.aconfig
@@ -103,3 +103,10 @@ flag {
description: "Applies intentMatchingFlags while matching intents to application components"
bug: "364354494"
}
+
+flag {
+ name: "aapm_feature_disable_install_unknown_sources"
+ namespace: "responsible_apis"
+ description: "Android Advanced Protection Mode Feature: Disable Install Unknown Sources"
+ bug: "369361373"
+}
diff --git a/core/java/android/service/autofill/FillEventHistory.java b/core/java/android/service/autofill/FillEventHistory.java
index 98dda1031eff258b517dadb4ad24cd850f110fdd..14a14e69f208531f91ff44ff4d07f4b01fc68c76 100644
--- a/core/java/android/service/autofill/FillEventHistory.java
+++ b/core/java/android/service/autofill/FillEventHistory.java
@@ -16,8 +16,10 @@
package android.service.autofill;
+import static android.service.autofill.Flags.FLAG_AUTOFILL_W_METRICS;
import static android.view.autofill.Helper.sVerbose;
+import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -63,14 +65,21 @@ public final class FillEventHistory implements Parcelable {
private static final String TAG = "FillEventHistory";
/**
- * Not in parcel. The ID of the autofill session that created the {@link FillResponse}.
+ * The ID of the autofill session that created the {@link FillResponse}.
+ *
+ * TODO: add this to the parcel.
*/
private final int mSessionId;
@Nullable private final Bundle mClientState;
@Nullable List mEvents;
- /** @hide */
+ /**
+ * Returns the unique identifier of this FillEventHistory.
+ *
+ * This is used to differentiate individual FillEventHistory.
+ */
+ @FlaggedApi(FLAG_AUTOFILL_W_METRICS)
public int getSessionId() {
return mSessionId;
}
@@ -283,6 +292,13 @@ public final class FillEventHistory implements Parcelable {
/** All fields matched contents of datasets. */
public static final int NO_SAVE_UI_REASON_DATASET_MATCH = 6;
+ /**
+ * Credential Manager is invoked instead of Autofill. When that happens, Save Dialog cannot
+ * be shown, and this will be populated in
+ */
+ @FlaggedApi(FLAG_AUTOFILL_W_METRICS)
+ public static final int NO_SAVE_UI_REASON_USING_CREDMAN = 7;
+
/** @hide */
@IntDef(prefix = { "NO_SAVE_UI_REASON_" }, value = {
NO_SAVE_UI_REASON_NONE,
@@ -310,11 +326,20 @@ public final class FillEventHistory implements Parcelable {
public static final int UI_TYPE_DIALOG = 3;
/**
- * The autofill suggestion is shown os a credman bottom sheet
- * @hide
+ * The autofill suggestion is shown os a credman bottom sheet
+ *
+ *
Note, this was introduced as bottom sheet even though it applies to all credman UI
+ * types. Instead of exposing this directly to the public, the generic UI_TYPE_CREDMAN is
+ * introduced with the same number.
+ *
+ * @hide
*/
public static final int UI_TYPE_CREDMAN_BOTTOM_SHEET = 4;
+ /** Credential Manager suggestions are shown instead of Autofill suggestion */
+ @FlaggedApi(FLAG_AUTOFILL_W_METRICS)
+ public static final int UI_TYPE_CREDMAN = 4;
+
/** @hide */
@IntDef(prefix = { "UI_TYPE_" }, value = {
UI_TYPE_UNKNOWN,
@@ -359,6 +384,13 @@ public final class FillEventHistory implements Parcelable {
return mEventType;
}
+ /** Gets the {@code AutofillId} that's focused at the time of action */
+ @FlaggedApi(FLAG_AUTOFILL_W_METRICS)
+ @Nullable
+ public AutofillId getFocusedId() {
+ return null;
+ }
+
/**
* Returns the id of dataset the id was on.
*
@@ -390,6 +422,17 @@ public final class FillEventHistory implements Parcelable {
: new ArraySet<>(mSelectedDatasetIds);
}
+ /**
+ * Returns which datasets were shown to the user.
+ *
+ *
Note: Only set on events of type {@link #TYPE_DATASETS_SHOWN}.
+ */
+ @FlaggedApi(FLAG_AUTOFILL_W_METRICS)
+ @NonNull
+ public Set getShownDatasetIds() {
+ return Collections.emptySet();
+ }
+
/**
* Returns which datasets were NOT selected by the user.
*
diff --git a/core/java/android/service/autofill/FillRequest.java b/core/java/android/service/autofill/FillRequest.java
index ca20801852f1b73fec58c172716ed570c407edf6..be4629ab8178370b1254a46ec06313cf4620ba65 100644
--- a/core/java/android/service/autofill/FillRequest.java
+++ b/core/java/android/service/autofill/FillRequest.java
@@ -16,6 +16,9 @@
package android.service.autofill;
+import static android.service.autofill.Flags.FLAG_FILL_DIALOG_IMPROVEMENTS;
+
+import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -100,7 +103,12 @@ public final class FillRequest implements Parcelable {
/**
* Indicates the request supports fill dialog presentation for the fields, the
* system will send the request when the activity just started.
+ *
+ * @deprecated All requests would support fill dialog by default.
+ * Presence of this flag isn't needed.
*/
+ @FlaggedApi(FLAG_FILL_DIALOG_IMPROVEMENTS)
+ @Deprecated
public static final @RequestFlags int FLAG_SUPPORTS_FILL_DIALOG = 0x40;
/**
@@ -588,10 +596,10 @@ public final class FillRequest implements Parcelable {
};
@DataClass.Generated(
- time = 1701010178309L,
+ time = 1730991738865L,
codegenVersion = "1.0.23",
sourceFile = "frameworks/base/core/java/android/service/autofill/FillRequest.java",
- inputSignatures = "public static final @android.service.autofill.FillRequest.RequestFlags int FLAG_MANUAL_REQUEST\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_COMPATIBILITY_MODE_REQUEST\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_PASSWORD_INPUT_TYPE\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_VIEW_NOT_FOCUSED\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_SUPPORTS_FILL_DIALOG\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_IME_SHOWING\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_RESET_FILL_DIALOG_STATE\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_PCC_DETECTION\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_SCREEN_HAS_CREDMAN_FIELD\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_VIEW_REQUESTS_CREDMAN_SERVICE\npublic static final int INVALID_REQUEST_ID\nprivate final int mId\nprivate final @android.annotation.NonNull java.util.List mFillContexts\nprivate final @android.annotation.NonNull java.util.List mHints\nprivate final @android.annotation.Nullable android.os.Bundle mClientState\nprivate final @android.service.autofill.FillRequest.RequestFlags int mFlags\nprivate final @android.annotation.Nullable android.view.inputmethod.InlineSuggestionsRequest mInlineSuggestionsRequest\nprivate final @android.annotation.Nullable android.content.IntentSender mDelayedFillIntentSender\nprivate void onConstructed()\nclass FillRequest extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genHiddenConstructor=true, genHiddenConstDefs=true)")
+ inputSignatures = "public static final @android.service.autofill.FillRequest.RequestFlags int FLAG_MANUAL_REQUEST\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_COMPATIBILITY_MODE_REQUEST\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_PASSWORD_INPUT_TYPE\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_VIEW_NOT_FOCUSED\npublic static final @android.annotation.FlaggedApi @java.lang.Deprecated @android.service.autofill.FillRequest.RequestFlags int FLAG_SUPPORTS_FILL_DIALOG\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_IME_SHOWING\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_RESET_FILL_DIALOG_STATE\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_PCC_DETECTION\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_SCREEN_HAS_CREDMAN_FIELD\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_VIEW_REQUESTS_CREDMAN_SERVICE\npublic static final int INVALID_REQUEST_ID\nprivate final int mId\nprivate final @android.annotation.NonNull java.util.List mFillContexts\nprivate final @android.annotation.NonNull java.util.List mHints\nprivate final @android.annotation.Nullable android.os.Bundle mClientState\nprivate final @android.service.autofill.FillRequest.RequestFlags int mFlags\nprivate final @android.annotation.Nullable android.view.inputmethod.InlineSuggestionsRequest mInlineSuggestionsRequest\nprivate final @android.annotation.Nullable android.content.IntentSender mDelayedFillIntentSender\nprivate void onConstructed()\nclass FillRequest extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genHiddenConstructor=true, genHiddenConstDefs=true)")
@Deprecated
private void __metadata() {}
diff --git a/core/java/android/service/notification/INotificationListener.aidl b/core/java/android/service/notification/INotificationListener.aidl
index b384b66bf6807c3a29b13429f97e18573b6ec9cb..54710488cd6735cd0db5e5023ad50ee7f32404e9 100644
--- a/core/java/android/service/notification/INotificationListener.aidl
+++ b/core/java/android/service/notification/INotificationListener.aidl
@@ -34,10 +34,14 @@ oneway interface INotificationListener
void onListenerConnected(in NotificationRankingUpdate update);
void onNotificationPosted(in IStatusBarNotificationHolder notificationHolder,
in NotificationRankingUpdate update);
+ void onNotificationPostedFull(in StatusBarNotification sbn,
+ in NotificationRankingUpdate update);
void onStatusBarIconsBehaviorChanged(boolean hideSilentStatusIcons);
// stats only for assistant
void onNotificationRemoved(in IStatusBarNotificationHolder notificationHolder,
in NotificationRankingUpdate update, in NotificationStats stats, int reason);
+ void onNotificationRemovedFull(in StatusBarNotification sbn,
+ in NotificationRankingUpdate update, in NotificationStats stats, int reason);
void onNotificationRankingUpdate(in NotificationRankingUpdate update);
void onListenerHintsChanged(int hints);
void onInterruptionFilterChanged(int interruptionFilter);
@@ -48,7 +52,9 @@ oneway interface INotificationListener
// assistants only
void onNotificationEnqueuedWithChannel(in IStatusBarNotificationHolder notificationHolder, in NotificationChannel channel, in NotificationRankingUpdate update);
+ void onNotificationEnqueuedWithChannelFull(in StatusBarNotification sbn, in NotificationChannel channel, in NotificationRankingUpdate update);
void onNotificationSnoozedUntilContext(in IStatusBarNotificationHolder notificationHolder, String snoozeCriterionId);
+ void onNotificationSnoozedUntilContextFull(in StatusBarNotification sbn, String snoozeCriterionId);
void onNotificationsSeen(in List keys);
void onPanelRevealed(int items);
void onPanelHidden();
diff --git a/core/java/android/service/notification/NotificationAssistantService.java b/core/java/android/service/notification/NotificationAssistantService.java
index 091b25ab77ceb0663f1520265ae091b86c98c678..0a9276c34bfd1aa94cf45db9666749509a00cece 100644
--- a/core/java/android/service/notification/NotificationAssistantService.java
+++ b/core/java/android/service/notification/NotificationAssistantService.java
@@ -423,7 +423,12 @@ public abstract class NotificationAssistantService extends NotificationListenerS
+ "Error receiving StatusBarNotification");
return;
}
+ onNotificationEnqueuedWithChannelFull(sbn, channel, update);
+ }
+ @Override
+ public void onNotificationEnqueuedWithChannelFull(StatusBarNotification sbn,
+ NotificationChannel channel, NotificationRankingUpdate update) {
applyUpdateLocked(update);
SomeArgs args = SomeArgs.obtain();
args.arg1 = sbn;
@@ -447,7 +452,12 @@ public abstract class NotificationAssistantService extends NotificationListenerS
Log.w(TAG, "onNotificationSnoozed: Error receiving StatusBarNotification");
return;
}
+ onNotificationSnoozedUntilContextFull(sbn, snoozeCriterionId);
+ }
+ @Override
+ public void onNotificationSnoozedUntilContextFull(
+ StatusBarNotification sbn, String snoozeCriterionId) {
SomeArgs args = SomeArgs.obtain();
args.arg1 = sbn;
args.arg2 = snoozeCriterionId;
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index a8ab2115d97f7e1d216c2a38de153dbacafaa5c1..5d0ec73a024bb9da12c8bc8d283f8da53fa5ef55 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -1490,7 +1490,12 @@ public abstract class NotificationListenerService extends Service {
Log.w(TAG, "onNotificationPosted: Error receiving StatusBarNotification");
return;
}
+ onNotificationPostedFull(sbn, update);
+ }
+ @Override
+ public void onNotificationPostedFull(StatusBarNotification sbn,
+ NotificationRankingUpdate update) {
try {
// convert icon metadata to legacy format for older clients
createLegacyIconExtras(sbn.getNotification());
@@ -1518,7 +1523,6 @@ public abstract class NotificationListenerService extends Service {
mRankingMap).sendToTarget();
}
}
-
}
@Override
@@ -1531,6 +1535,12 @@ public abstract class NotificationListenerService extends Service {
Log.w(TAG, "onNotificationRemoved: Error receiving StatusBarNotification", e);
return;
}
+ onNotificationRemovedFull(sbn, update, stats, reason);
+ }
+
+ @Override
+ public void onNotificationRemovedFull(StatusBarNotification sbn,
+ NotificationRankingUpdate update, NotificationStats stats, int reason) {
if (sbn == null) {
Log.w(TAG, "onNotificationRemoved: Error receiving StatusBarNotification");
return;
@@ -1591,6 +1601,14 @@ public abstract class NotificationListenerService extends Service {
// no-op in the listener
}
+ @Override
+ public void onNotificationEnqueuedWithChannelFull(
+ StatusBarNotification sbn, NotificationChannel channel,
+ NotificationRankingUpdate update)
+ throws RemoteException {
+ // no-op in the listener
+ }
+
@Override
public void onNotificationsSeen(List keys)
throws RemoteException {
@@ -1620,6 +1638,13 @@ public abstract class NotificationListenerService extends Service {
// no-op in the listener
}
+ @Override
+ public void onNotificationSnoozedUntilContextFull(
+ StatusBarNotification sbn, String snoozeCriterionId)
+ throws RemoteException {
+ // no-op in the listener
+ }
+
@Override
public void onNotificationExpansionChanged(
String key, boolean isUserAction, boolean isExpanded) {
@@ -1688,8 +1713,6 @@ public abstract class NotificationListenerService extends Service {
Bundle feedback) {
// no-op in the listener
}
-
-
}
/**
diff --git a/core/java/android/service/quickaccesswallet/IQuickAccessWalletService.aidl b/core/java/android/service/quickaccesswallet/IQuickAccessWalletService.aidl
index 0dca78d890a5109bf9f5698272b4bfba468aa155..03e27b866b7a4a01a514bebafac85da0b58aa1bc 100644
--- a/core/java/android/service/quickaccesswallet/IQuickAccessWalletService.aidl
+++ b/core/java/android/service/quickaccesswallet/IQuickAccessWalletService.aidl
@@ -43,4 +43,6 @@ interface IQuickAccessWalletService {
oneway void unregisterWalletServiceEventListener(in WalletServiceEventListenerRequest request);
// Request to get a PendingIntent to launch an activity from which the user can manage their cards.
oneway void onTargetActivityIntentRequested(in IQuickAccessWalletServiceCallbacks callbacks);
+ // Request to get a PendingIntent to launch an activity, triggered when the user performs a gesture.
+ oneway void onGestureTargetActivityIntentRequested(in IQuickAccessWalletServiceCallbacks callbacks);
}
\ No newline at end of file
diff --git a/core/java/android/service/quickaccesswallet/IQuickAccessWalletServiceCallbacks.aidl b/core/java/android/service/quickaccesswallet/IQuickAccessWalletServiceCallbacks.aidl
index 1b69ca12da3a19b1f8293944ac7a7a0cf7e2936a..61d7fd1f526c36a967826625d52345dbd5ff61ac 100644
--- a/core/java/android/service/quickaccesswallet/IQuickAccessWalletServiceCallbacks.aidl
+++ b/core/java/android/service/quickaccesswallet/IQuickAccessWalletServiceCallbacks.aidl
@@ -37,4 +37,6 @@ interface IQuickAccessWalletServiceCallbacks {
oneway void onWalletServiceEvent(in WalletServiceEvent event);
// Called in response to onTargetActivityIntentRequested. May only be called once per request.
oneway void onTargetActivityPendingIntentReceived(in PendingIntent pendingIntent);
+ //Called in response to onGesturePendingIntent
+ oneway void onGestureTargetActivityPendingIntentReceived(in PendingIntent pendingIntent);
}
\ No newline at end of file
diff --git a/core/java/android/service/quickaccesswallet/QuickAccessWalletClient.java b/core/java/android/service/quickaccesswallet/QuickAccessWalletClient.java
index faa5b2fe3488508511c45df8aaf41c1508bce72c..b5251db4e5397be1def83e35ff06ea57ddb998a6 100644
--- a/core/java/android/service/quickaccesswallet/QuickAccessWalletClient.java
+++ b/core/java/android/service/quickaccesswallet/QuickAccessWalletClient.java
@@ -17,6 +17,7 @@
package android.service.quickaccesswallet;
import android.annotation.CallbackExecutor;
+import android.annotation.FlaggedApi;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
@@ -180,6 +181,23 @@ public interface QuickAccessWalletClient extends Closeable {
void onWalletPendingIntentRetrieved(@Nullable PendingIntent walletPendingIntent);
}
+ /**
+ * Gets the {@link PendingIntent} provided by QuickAccessWalletService to be sent when the user
+ * launches Wallet via gesture.
+ */
+ @FlaggedApi(Flags.FLAG_LAUNCH_WALLET_OPTION_ON_POWER_DOUBLE_TAP)
+ void getGestureTargetActivityPendingIntent(
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull GesturePendingIntentCallback gesturePendingIntentCallback);
+
+ /** Callback interface for getGesturePendingIntent. */
+ @FlaggedApi(Flags.FLAG_LAUNCH_WALLET_OPTION_ON_POWER_DOUBLE_TAP)
+ interface GesturePendingIntentCallback {
+ /** Callback method for getGesturePendingIntent */
+ @FlaggedApi(Flags.FLAG_LAUNCH_WALLET_OPTION_ON_POWER_DOUBLE_TAP)
+ void onGesturePendingIntentRetrieved(@Nullable PendingIntent pendingIntent);
+ }
+
/**
* The manifest entry for the QuickAccessWalletService may also publish information about the
* activity that hosts the Wallet view. This is typically the home screen of the Wallet
diff --git a/core/java/android/service/quickaccesswallet/QuickAccessWalletClientImpl.java b/core/java/android/service/quickaccesswallet/QuickAccessWalletClientImpl.java
index a59f026c41820eb4d1febe2eef174c7f20a934bc..97a4beff633fdf8e832cfc7355e386aad2fcb620 100644
--- a/core/java/android/service/quickaccesswallet/QuickAccessWalletClientImpl.java
+++ b/core/java/android/service/quickaccesswallet/QuickAccessWalletClientImpl.java
@@ -266,6 +266,34 @@ public class QuickAccessWalletClientImpl implements QuickAccessWalletClient, Ser
});
}
+ @Override
+ public void getGestureTargetActivityPendingIntent(
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull GesturePendingIntentCallback gesturePendingIntentCallback) {
+ BaseCallbacks callbacks =
+ new BaseCallbacks() {
+ @Override
+ public void onGestureTargetActivityPendingIntentReceived(
+ PendingIntent pendingIntent) {
+ if (!Flags.launchWalletOptionOnPowerDoubleTap()) {
+ return;
+ }
+ executor.execute(
+ () ->
+ gesturePendingIntentCallback
+ .onGesturePendingIntentRetrieved(pendingIntent));
+ }
+ };
+
+ executeApiCall(
+ new ApiCaller("getGestureTargetActivityPendingIntent") {
+ @Override
+ void performApiCall(IQuickAccessWalletService service) throws RemoteException {
+ service.onGestureTargetActivityIntentRequested(callbacks);
+ }
+ });
+ }
+
@Override
@Nullable
public Intent createWalletSettingsIntent() {
@@ -506,5 +534,9 @@ public class QuickAccessWalletClientImpl implements QuickAccessWalletClient, Ser
public void onTargetActivityPendingIntentReceived(PendingIntent pendingIntent) {
throw new IllegalStateException();
}
+
+ public void onGestureTargetActivityPendingIntentReceived(PendingIntent pendingIntent) {
+ throw new IllegalStateException();
+ }
}
}
diff --git a/core/java/android/service/quickaccesswallet/QuickAccessWalletService.java b/core/java/android/service/quickaccesswallet/QuickAccessWalletService.java
index 36fa21c19d273f45ac3c448f5779a273a2e5caf6..90136ae00f6a87ca3b0f8b3f347ae96f92242ff6 100644
--- a/core/java/android/service/quickaccesswallet/QuickAccessWalletService.java
+++ b/core/java/android/service/quickaccesswallet/QuickAccessWalletService.java
@@ -16,6 +16,9 @@
package android.service.quickaccesswallet;
+import static android.service.quickaccesswallet.Flags.launchWalletOptionOnPowerDoubleTap;
+
+import android.annotation.FlaggedApi;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SdkConstant;
@@ -247,6 +250,19 @@ public abstract class QuickAccessWalletService extends Service {
callbacks));
}
+ @FlaggedApi(Flags.FLAG_LAUNCH_WALLET_OPTION_ON_POWER_DOUBLE_TAP)
+ @Override
+ public void onGestureTargetActivityIntentRequested(
+ @NonNull IQuickAccessWalletServiceCallbacks callbacks) {
+ if (launchWalletOptionOnPowerDoubleTap()) {
+ mHandler.post(
+ () ->
+ QuickAccessWalletService.this
+ .onGestureTargetActivityIntentRequestedInternal(
+ callbacks));
+ }
+ }
+
public void registerWalletServiceEventListener(
@NonNull WalletServiceEventListenerRequest request,
@NonNull IQuickAccessWalletServiceCallbacks callback) {
@@ -275,6 +291,20 @@ public abstract class QuickAccessWalletService extends Service {
}
}
+ private void onGestureTargetActivityIntentRequestedInternal(
+ IQuickAccessWalletServiceCallbacks callbacks) {
+ if (!Flags.launchWalletOptionOnPowerDoubleTap()) {
+ return;
+ }
+
+ try {
+ callbacks.onGestureTargetActivityPendingIntentReceived(
+ getGestureTargetActivityPendingIntent());
+ } catch (RemoteException e) {
+ Log.w(TAG, "Error", e);
+ }
+ }
+
@Override
@Nullable
public IBinder onBind(@NonNull Intent intent) {
@@ -349,6 +379,18 @@ public abstract class QuickAccessWalletService extends Service {
return null;
}
+ /**
+ * Specify a {@link PendingIntent} to be launched on user gesture.
+ *
+ * The pending intent will be sent when the user performs a gesture to open Wallet.
+ * The pending intent should launch an activity.
+ */
+ @Nullable
+ @FlaggedApi(Flags.FLAG_LAUNCH_WALLET_OPTION_ON_POWER_DOUBLE_TAP)
+ public PendingIntent getGestureTargetActivityPendingIntent() {
+ return null;
+ }
+
private void sendWalletServiceEventInternal(WalletServiceEvent serviceEvent) {
if (mEventListener == null) {
Log.i(TAG, "No dismiss listener registered");
diff --git a/core/java/android/service/quickaccesswallet/flags.aconfig b/core/java/android/service/quickaccesswallet/flags.aconfig
new file mode 100644
index 0000000000000000000000000000000000000000..75a93091eec3433afbbb5b6d3984f9fda039650f
--- /dev/null
+++ b/core/java/android/service/quickaccesswallet/flags.aconfig
@@ -0,0 +1,9 @@
+package: "android.service.quickaccesswallet"
+container: "system"
+
+flag {
+ name: "launch_wallet_option_on_power_double_tap"
+ namespace: "wallet_integration"
+ description: "Option to launch the Wallet app on double-tap of the power button"
+ bug: "378469025"
+}
\ No newline at end of file
diff --git a/core/java/android/telephony/PhoneStateListener.java b/core/java/android/telephony/PhoneStateListener.java
index 1df3b433275488ca2d536f79cf8a70b57d3cacfa..c16a510ed7297f8b16810a8b620cb61a3c86858d 100644
--- a/core/java/android/telephony/PhoneStateListener.java
+++ b/core/java/android/telephony/PhoneStateListener.java
@@ -1712,6 +1712,15 @@ public class PhoneStateListener {
@NonNull NtnSignalStrength ntnSignalStrength) {
// not supported on the deprecated interface - Use TelephonyCallback instead
}
+
+ public final void onSecurityAlgorithmsChanged(SecurityAlgorithmUpdate update) {
+ // not supported on the deprecated interface - Use TelephonyCallback instead
+ }
+
+ public final void onCellularIdentifierDisclosedChanged(
+ CellularIdentifierDisclosure disclosure) {
+ // not supported on the deprecated interface - Use TelephonyCallback instead
+ }
}
private void log(String s) {
diff --git a/core/java/android/telephony/SubscriptionPlan.java b/core/java/android/telephony/SubscriptionPlan.java
index 7b48a16c2227be881a8b8d3b9de65f2419479e20..4c59a8589df228e826ee142c3bbd9624418bb8ff 100644
--- a/core/java/android/telephony/SubscriptionPlan.java
+++ b/core/java/android/telephony/SubscriptionPlan.java
@@ -18,6 +18,7 @@ package android.telephony;
import android.annotation.BytesLong;
import android.annotation.CurrentTimeMillisLong;
+import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -28,6 +29,7 @@ import android.telephony.Annotation.NetworkType;
import android.util.Range;
import android.util.RecurrenceRule;
+import com.android.internal.telephony.flags.Flags;
import com.android.internal.util.Preconditions;
import java.lang.annotation.Retention;
@@ -83,6 +85,33 @@ public final class SubscriptionPlan implements Parcelable {
/** Value indicating a timestamp is unknown. */
public static final long TIME_UNKNOWN = -1;
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = { "SUBSCRIPTION_STATUS_" }, value = {
+ SUBSCRIPTION_STATUS_UNKNOWN,
+ SUBSCRIPTION_STATUS_ACTIVE,
+ SUBSCRIPTION_STATUS_INACTIVE,
+ SUBSCRIPTION_STATUS_TRIAL,
+ SUBSCRIPTION_STATUS_SUSPENDED
+ })
+ public @interface SubscriptionStatus {}
+
+ /** Subscription status is unknown. */
+ @FlaggedApi(Flags.FLAG_SUBSCRIPTION_PLAN_ALLOW_STATUS_AND_END_DATE)
+ public static final int SUBSCRIPTION_STATUS_UNKNOWN = 0;
+ /** Subscription is active. */
+ @FlaggedApi(Flags.FLAG_SUBSCRIPTION_PLAN_ALLOW_STATUS_AND_END_DATE)
+ public static final int SUBSCRIPTION_STATUS_ACTIVE = 1;
+ /** Subscription is inactive. */
+ @FlaggedApi(Flags.FLAG_SUBSCRIPTION_PLAN_ALLOW_STATUS_AND_END_DATE)
+ public static final int SUBSCRIPTION_STATUS_INACTIVE = 2;
+ /** Subscription is in a trial period. */
+ @FlaggedApi(Flags.FLAG_SUBSCRIPTION_PLAN_ALLOW_STATUS_AND_END_DATE)
+ public static final int SUBSCRIPTION_STATUS_TRIAL = 3;
+ /** Subscription is suspended. */
+ @FlaggedApi(Flags.FLAG_SUBSCRIPTION_PLAN_ALLOW_STATUS_AND_END_DATE)
+ public static final int SUBSCRIPTION_STATUS_SUSPENDED = 4;
+
private final RecurrenceRule cycleRule;
private CharSequence title;
private CharSequence summary;
@@ -91,6 +120,7 @@ public final class SubscriptionPlan implements Parcelable {
private long dataUsageBytes = BYTES_UNKNOWN;
private long dataUsageTime = TIME_UNKNOWN;
private @NetworkType int[] networkTypes;
+ private int mSubscriptionStatus = SUBSCRIPTION_STATUS_UNKNOWN;
private SubscriptionPlan(RecurrenceRule cycleRule) {
this.cycleRule = Preconditions.checkNotNull(cycleRule);
@@ -107,6 +137,7 @@ public final class SubscriptionPlan implements Parcelable {
dataUsageBytes = source.readLong();
dataUsageTime = source.readLong();
networkTypes = source.createIntArray();
+ mSubscriptionStatus = source.readInt();
}
@Override
@@ -124,6 +155,7 @@ public final class SubscriptionPlan implements Parcelable {
dest.writeLong(dataUsageBytes);
dest.writeLong(dataUsageTime);
dest.writeIntArray(networkTypes);
+ dest.writeInt(mSubscriptionStatus);
}
@Override
@@ -137,13 +169,14 @@ public final class SubscriptionPlan implements Parcelable {
.append(" dataUsageBytes=").append(dataUsageBytes)
.append(" dataUsageTime=").append(dataUsageTime)
.append(" networkTypes=").append(Arrays.toString(networkTypes))
+ .append(" subscriptionStatus=").append(mSubscriptionStatus)
.append("}").toString();
}
@Override
public int hashCode() {
return Objects.hash(cycleRule, title, summary, dataLimitBytes, dataLimitBehavior,
- dataUsageBytes, dataUsageTime, Arrays.hashCode(networkTypes));
+ dataUsageBytes, dataUsageTime, Arrays.hashCode(networkTypes), mSubscriptionStatus);
}
@Override
@@ -157,7 +190,8 @@ public final class SubscriptionPlan implements Parcelable {
&& dataLimitBehavior == other.dataLimitBehavior
&& dataUsageBytes == other.dataUsageBytes
&& dataUsageTime == other.dataUsageTime
- && Arrays.equals(networkTypes, other.networkTypes);
+ && Arrays.equals(networkTypes, other.networkTypes)
+ && mSubscriptionStatus == other.mSubscriptionStatus;
}
return false;
}
@@ -179,6 +213,13 @@ public final class SubscriptionPlan implements Parcelable {
return cycleRule;
}
+ /** Return the end date of this plan, or null if no end date exists. */
+ @FlaggedApi(Flags.FLAG_SUBSCRIPTION_PLAN_ALLOW_STATUS_AND_END_DATE)
+ public @Nullable ZonedDateTime getPlanEndDate() {
+ // ZonedDateTime is immutable, so no need to create a defensive copy.
+ return cycleRule.end;
+ }
+
/** Return the short title of this plan. */
public @Nullable CharSequence getTitle() {
return title;
@@ -237,6 +278,16 @@ public final class SubscriptionPlan implements Parcelable {
return cycleRule.cycleIterator();
}
+ /**
+ * Returns the status of the subscription plan.
+ *
+ * @return The subscription status, or {@link #SUBSCRIPTION_STATUS_UNKNOWN} if not available.
+ */
+ @FlaggedApi(Flags.FLAG_SUBSCRIPTION_PLAN_ALLOW_STATUS_AND_END_DATE)
+ public @SubscriptionStatus int getSubscriptionStatus() {
+ return mSubscriptionStatus;
+ }
+
/**
* Builder for a {@link SubscriptionPlan}.
*/
@@ -382,5 +433,21 @@ public final class SubscriptionPlan implements Parcelable {
TelephonyManager.getAllNetworkTypes().length);
return this;
}
+
+ /**
+ * Set the subscription status.
+ *
+ * @param subscriptionStatus the current subscription status
+ */
+ @FlaggedApi(Flags.FLAG_SUBSCRIPTION_PLAN_ALLOW_STATUS_AND_END_DATE)
+ public @NonNull Builder setSubscriptionStatus(@SubscriptionStatus int subscriptionStatus) {
+ if (subscriptionStatus < SUBSCRIPTION_STATUS_UNKNOWN
+ || subscriptionStatus > SUBSCRIPTION_STATUS_SUSPENDED) {
+ throw new IllegalArgumentException(
+ "Subscription status must be defined with a valid value");
+ }
+ plan.mSubscriptionStatus = subscriptionStatus;
+ return this;
+ }
}
}
diff --git a/core/java/android/telephony/TelephonyCallback.java b/core/java/android/telephony/TelephonyCallback.java
index 0d1dc4611343a409a9b48dcda221514c10ba14cf..2c585e640fdd19ddc091644aa61aca8f36018981 100644
--- a/core/java/android/telephony/TelephonyCallback.java
+++ b/core/java/android/telephony/TelephonyCallback.java
@@ -704,6 +704,28 @@ public class TelephonyCallback {
*/
public static final int EVENT_CARRIER_ROAMING_NTN_SIGNAL_STRENGTH_CHANGED = 45;
+ /**
+ * Event for changes to mobile network ciphering algorithms.
+ * See {@link SecurityAlgorithmsListener#onSecurityAlgorithmsChanged}
+ *
+ * @hide
+ */
+ @FlaggedApi(Flags.FLAG_CELLULAR_IDENTIFIER_DISCLOSURE_INDICATIONS)
+ @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @SystemApi
+ public static final int EVENT_SECURITY_ALGORITHMS_CHANGED = 46;
+
+ /**
+ * Event for updates to sensitive device identifier disclosures (IMSI, IMEI, unciphered SUCI).
+ * See {@link CellularIdentifierDisclosedListener#onCellularIdentifierDisclosedChanged}
+ *
+ * @hide
+ */
+ @FlaggedApi(Flags.FLAG_CELLULAR_IDENTIFIER_DISCLOSURE_INDICATIONS)
+ @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @SystemApi
+ public static final int EVENT_CELLULAR_IDENTIFIER_DISCLOSED_CHANGED = 47;
+
/**
* @hide
*/
@@ -752,7 +774,9 @@ public class TelephonyCallback {
EVENT_CARRIER_ROAMING_NTN_MODE_CHANGED,
EVENT_CARRIER_ROAMING_NTN_ELIGIBLE_STATE_CHANGED,
EVENT_CARRIER_ROAMING_NTN_AVAILABLE_SERVICES_CHANGED,
- EVENT_CARRIER_ROAMING_NTN_SIGNAL_STRENGTH_CHANGED
+ EVENT_CARRIER_ROAMING_NTN_SIGNAL_STRENGTH_CHANGED,
+ EVENT_SECURITY_ALGORITHMS_CHANGED,
+ EVENT_CELLULAR_IDENTIFIER_DISCLOSED_CHANGED
})
@Retention(RetentionPolicy.SOURCE)
public @interface TelephonyEvent {
@@ -1826,6 +1850,41 @@ public class TelephonyCallback {
@NonNull NtnSignalStrength ntnSignalStrength) {}
}
+ /**
+ * Interface for CellularIdentifierDisclosedListener
+ * @hide
+ */
+ @SystemApi
+ @FlaggedApi(Flags.FLAG_CELLULAR_IDENTIFIER_DISCLOSURE_INDICATIONS)
+ public interface CellularIdentifierDisclosedListener {
+ /**
+ * Callback invoked when a device identifier (IMSI, IMEI, or unciphered SUCI)
+ * is disclosed over the network before a security context is established
+ * ("pre-authentication").
+ *
+ * @param disclosure details of the identifier disclosure
+ * See {@link CellularIdentifierDisclosure} for more details
+ */
+ void onCellularIdentifierDisclosedChanged(@NonNull CellularIdentifierDisclosure disclosure);
+ }
+
+ /**
+ * Interface for SecurityAlgorithmsListener
+ * @hide
+ */
+ @SystemApi
+ @FlaggedApi(Flags.FLAG_SECURITY_ALGORITHMS_UPDATE_INDICATIONS)
+ public interface SecurityAlgorithmsListener {
+ /**
+ * Callback invoked when the most recently reported security algorithms has changed,
+ * per a specified connection event.
+ *
+ * @param securityAlgorithmUpdate details of the security algorithm update
+ * See {@link SecurityAlgorithmUpdate} for more details
+ */
+ void onSecurityAlgorithmsChanged(@NonNull SecurityAlgorithmUpdate securityAlgorithmUpdate);
+ }
+
/**
* The callback methods need to be called on the handler thread where
* this object was created. If the binder did that for us it'd be nice.
@@ -2302,5 +2361,27 @@ public class TelephonyCallback {
() -> listener.onCarrierRoamingNtnSignalStrengthChanged(ntnSignalStrength)));
}
+
+ public void onSecurityAlgorithmsChanged(SecurityAlgorithmUpdate update) {
+ if (!Flags.securityAlgorithmsUpdateIndications()) return;
+
+ SecurityAlgorithmsListener listener =
+ (SecurityAlgorithmsListener) mTelephonyCallbackWeakRef.get();
+ if (listener == null) return;
+
+ Binder.withCleanCallingIdentity(() -> mExecutor.execute(
+ () -> listener.onSecurityAlgorithmsChanged(update)));
+ }
+
+ public void onCellularIdentifierDisclosedChanged(CellularIdentifierDisclosure disclosure) {
+ if (!Flags.cellularIdentifierDisclosureIndications()) return;
+
+ CellularIdentifierDisclosedListener listener =
+ (CellularIdentifierDisclosedListener) mTelephonyCallbackWeakRef.get();
+ if (listener == null) return;
+
+ Binder.withCleanCallingIdentity(() -> mExecutor.execute(
+ () -> listener.onCellularIdentifierDisclosedChanged(disclosure)));
+ }
}
}
diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java
index 90b0bb34c145e37b95ee3d4c6a659c5fac5eb4a9..4ec429d0c4adae1eecc9a6a12e1acc9131e5e99e 100644
--- a/core/java/android/telephony/TelephonyRegistryManager.java
+++ b/core/java/android/telephony/TelephonyRegistryManager.java
@@ -1154,6 +1154,40 @@ public class TelephonyRegistryManager {
}
}
+ /**
+ * Notify external listeners that the radio security algorithms have changed.
+ * @param slotIndex for the phone object that got updated
+ * @param subId for which the security algorithm changed
+ * @param update details of the security algorithm update
+ * @hide
+ */
+ public void notifySecurityAlgorithmsChanged(
+ int slotIndex, int subId, SecurityAlgorithmUpdate update) {
+ try {
+ sRegistry.notifySecurityAlgorithmsChanged(slotIndex, subId, update);
+ } catch (RemoteException ex) {
+ // system server crash
+ throw ex.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Notify external listeners of a new cellular identifier disclosure change.
+ * @param slotIndex for the phone object that the disclosure applies to
+ * @param subId for which the disclosure applies to
+ * @param disclosure details of the identifier disclosure
+ * @hide
+ */
+ public void notifyCellularIdentifierDisclosedChanged(
+ int slotIndex, int subId, CellularIdentifierDisclosure disclosure) {
+ try {
+ sRegistry.notifyCellularIdentifierDisclosedChanged(slotIndex, subId, disclosure);
+ } catch (RemoteException ex) {
+ // system server crash
+ throw ex.rethrowFromSystemServer();
+ }
+ }
+
/**
* Processes potential event changes from the provided {@link TelephonyCallback}.
*
@@ -1313,6 +1347,15 @@ public class TelephonyRegistryManager {
eventList.add(TelephonyCallback.EVENT_CARRIER_ROAMING_NTN_AVAILABLE_SERVICES_CHANGED);
eventList.add(TelephonyCallback.EVENT_CARRIER_ROAMING_NTN_SIGNAL_STRENGTH_CHANGED);
}
+
+ if (telephonyCallback instanceof TelephonyCallback.CellularIdentifierDisclosedListener) {
+ eventList.add(TelephonyCallback.EVENT_CELLULAR_IDENTIFIER_DISCLOSED_CHANGED);
+ }
+
+ if (telephonyCallback instanceof TelephonyCallback.SecurityAlgorithmsListener) {
+ eventList.add(TelephonyCallback.EVENT_SECURITY_ALGORITHMS_CHANGED);
+ }
+
return eventList;
}
diff --git a/core/java/android/text/Html.java b/core/java/android/text/Html.java
index ae12132d49a1f55a8ae1213c8d8811e0c3e97d9c..a42eece57eec99c164876a4080962e38ccdda952 100644
--- a/core/java/android/text/Html.java
+++ b/core/java/android/text/Html.java
@@ -614,7 +614,7 @@ public class Html {
if (style[j] instanceof TypefaceSpan) {
String s = ((TypefaceSpan) style[j]).getFamily();
- if (s.equals("monospace")) {
+ if ("monospace".equals(s)) {
out.append("");
}
}
diff --git a/core/java/android/text/TextFlags.java b/core/java/android/text/TextFlags.java
deleted file mode 100644
index f69a333ff81f5100c2c69f6bdbc3025278ccd6dc..0000000000000000000000000000000000000000
--- a/core/java/android/text/TextFlags.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * 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.text;
-
-import android.annotation.NonNull;
-import android.app.AppGlobals;
-
-/**
- * Flags in the "text" namespace.
- *
- * TODO(nona): Remove this class.
- * @hide
- */
-public final class TextFlags {
-
- /**
- * The name space of the "text" feature.
- *
- * This needs to move to DeviceConfig constant.
- */
- public static final String NAMESPACE = "text";
-
- /**
- * Whether we use the new design of context menu.
- */
- public static final String ENABLE_NEW_CONTEXT_MENU =
- "TextEditing__enable_new_context_menu";
-
- /**
- * The key name used in app core settings for {@link #ENABLE_NEW_CONTEXT_MENU}.
- */
- public static final String KEY_ENABLE_NEW_CONTEXT_MENU = "text__enable_new_context_menu";
-
- /**
- * Default value for the flag {@link #ENABLE_NEW_CONTEXT_MENU}.
- */
- public static final boolean ENABLE_NEW_CONTEXT_MENU_DEFAULT = true;
-
- /**
- * List of text flags to be transferred to the application process.
- */
- public static final String[] TEXT_ACONFIGS_FLAGS = {
- };
-
- /**
- * List of the default values of the text flags.
- *
- * The order must be the same to the TEXT_ACONFIG_FLAGS.
- */
- public static final boolean[] TEXT_ACONFIG_DEFAULT_VALUE = {
- };
-
- /**
- * Get a key for the feature flag.
- */
- public static String getKeyForFlag(@NonNull String flag) {
- return "text__" + flag;
- }
-
- /**
- * Return true if the feature flag is enabled.
- */
- public static boolean isFeatureEnabled(@NonNull String flag) {
- return AppGlobals.getIntCoreSetting(
- getKeyForFlag(flag), 0 /* aconfig is false by default */) != 0;
- }
-}
diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java
index 032f5923d3f2cae0e553d4b5d9ea5fd125950c0e..cb72b976c784778f4cff957ea63c0357f4321ef5 100644
--- a/core/java/android/text/TextUtils.java
+++ b/core/java/android/text/TextUtils.java
@@ -50,6 +50,7 @@ import android.text.style.LineBackgroundSpan;
import android.text.style.LineBreakConfigSpan;
import android.text.style.LineHeightSpan;
import android.text.style.LocaleSpan;
+import android.text.style.NoWritingToolsSpan;
import android.text.style.ParagraphStyle;
import android.text.style.QuoteSpan;
import android.text.style.RelativeSizeSpan;
@@ -817,7 +818,9 @@ public class TextUtils {
/** @hide */
public static final int LINE_BREAK_CONFIG_SPAN = 30;
/** @hide */
- public static final int LAST_SPAN = LINE_BREAK_CONFIG_SPAN;
+ public static final int NO_WRITING_TOOLS_SPAN = 31;
+ /** @hide */
+ public static final int LAST_SPAN = NO_WRITING_TOOLS_SPAN;
/**
* Flatten a CharSequence and whatever styles can be copied across processes
@@ -1025,6 +1028,10 @@ public class TextUtils {
span = LineBreakConfigSpan.CREATOR.createFromParcel(p);
break;
+ case NO_WRITING_TOOLS_SPAN:
+ span = NoWritingToolsSpan.CREATOR.createFromParcel(p);
+ break;
+
default:
throw new RuntimeException("bogus span encoding " + kind);
}
diff --git a/core/java/android/text/flags/flags.aconfig b/core/java/android/text/flags/flags.aconfig
index 02923eda308ef5d3a90ab56e3f2f28c8a331becc..f43f172d7d5b622b6bf20eef30d4a29b108df707 100644
--- a/core/java/android/text/flags/flags.aconfig
+++ b/core/java/android/text/flags/flags.aconfig
@@ -163,10 +163,12 @@ flag {
}
flag {
- name: "typeface_redesign"
+ name: "typeface_redesign_readonly"
namespace: "text"
description: "Decouple variation settings, weight and style information from Typeface class"
bug: "361260253"
+ # This feature does not support runtime flag switch which leads crash in System UI.
+ is_fixed_read_only: true
}
flag {
diff --git a/core/java/android/text/style/NoWritingToolsSpan.java b/core/java/android/text/style/NoWritingToolsSpan.java
new file mode 100644
index 0000000000000000000000000000000000000000..90f85aa69faa5df31c6f00d5121c918384c34b48
--- /dev/null
+++ b/core/java/android/text/style/NoWritingToolsSpan.java
@@ -0,0 +1,87 @@
+/*
+ * 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.text.style;
+
+import static android.view.inputmethod.Flags.FLAG_WRITING_TOOLS;
+
+import android.annotation.FlaggedApi;
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.text.ParcelableSpan;
+import android.text.TextUtils;
+
+/**
+ * A span that signals to IMEs that writing tools should not modify the text.
+ *
+ *
For example, a text field may contain a mix of user input text and quoted text. The app
+ * can apply {@code NoWritingToolsSpan} to the quoted text so that the IME knows that writing
+ * tools should only rewrite the user input text, and not modify the quoted text.
+ */
+@FlaggedApi(FLAG_WRITING_TOOLS)
+public final class NoWritingToolsSpan implements ParcelableSpan {
+
+ /**
+ * Creates a {@link NoWritingToolsSpan}.
+ */
+ public NoWritingToolsSpan() {
+ }
+
+ @Override
+ public int getSpanTypeId() {
+ return getSpanTypeIdInternal();
+ }
+
+ /** @hide */
+ @Override
+ public int getSpanTypeIdInternal() {
+ return TextUtils.NO_WRITING_TOOLS_SPAN;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ writeToParcelInternal(dest, flags);
+ }
+
+ /** @hide */
+ @Override
+ public void writeToParcelInternal(@NonNull Parcel dest, int flags) {
+ }
+
+ @Override
+ public String toString() {
+ return "NoWritingToolsSpan{}";
+ }
+
+ @NonNull
+ public static final Creator CREATOR = new Creator<>() {
+
+ @Override
+ public NoWritingToolsSpan createFromParcel(Parcel source) {
+ return new NoWritingToolsSpan();
+ }
+
+ @Override
+ public NoWritingToolsSpan[] newArray(int size) {
+ return new NoWritingToolsSpan[size];
+ }
+ };
+}
diff --git a/core/java/android/util/ArrayMap.java b/core/java/android/util/ArrayMap.java
index 174e0c8e6549e55b176f1d4953fb7f96ab879951..7ee0ff15c5ad2e903e4afe6010d2d9355847bcf9 100644
--- a/core/java/android/util/ArrayMap.java
+++ b/core/java/android/util/ArrayMap.java
@@ -649,7 +649,6 @@ public final class ArrayMap implements Map {
}
if (index > 0 && mHashes[index-1] > hash) {
RuntimeException e = new RuntimeException("here");
- e.fillInStackTrace();
Log.w(TAG, "New hash " + hash
+ " is before end of array hash " + mHashes[index-1]
+ " at index " + index + (DEBUG ? " key " + key : ""), e);
diff --git a/core/java/android/util/ArraySet.java b/core/java/android/util/ArraySet.java
index bfbca07ed2568ce0055a6159c7f76d2389a3403b..1344bb9a73eb56feff1c209645c85155f4399972 100644
--- a/core/java/android/util/ArraySet.java
+++ b/core/java/android/util/ArraySet.java
@@ -526,7 +526,6 @@ public final class ArraySet implements Collection, Set {
// Cannot optimize since it would break the sorted order - fallback to add()
if (DEBUG) {
RuntimeException e = new RuntimeException("here");
- e.fillInStackTrace();
Log.w(TAG, "New hash " + hash
+ " is before end of array hash " + mHashes[index - 1]
+ " at index " + index, e);
diff --git a/core/java/android/view/AttachedSurfaceControl.java b/core/java/android/view/AttachedSurfaceControl.java
index 5406cf5574106f59fa922fd0853b07595689a046..264db4a604ffd9d8138f8e9e78d4597c243ad54e 100644
--- a/core/java/android/view/AttachedSurfaceControl.java
+++ b/core/java/android/view/AttachedSurfaceControl.java
@@ -15,9 +15,11 @@
*/
package android.view;
+import android.annotation.CallbackExecutor;
import android.annotation.FlaggedApi;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SuppressLint;
import android.annotation.UiThread;
import android.content.Context;
import android.graphics.Rect;
@@ -29,6 +31,8 @@ import android.window.SurfaceSyncGroup;
import com.android.window.flags.Flags;
+import java.util.concurrent.Executor;
+
/**
* Provides an interface to the root-Surface of a View Hierarchy or Window. This
* is used in combination with the {@link android.view.SurfaceControl} API to enable
@@ -202,4 +206,21 @@ public interface AttachedSurfaceControl {
throw new UnsupportedOperationException("The getInputTransferToken needs to be "
+ "implemented before making this call.");
}
+
+ /**
+ * Registers a {@link OnJankDataListener} to receive jank classification data about rendered
+ * frames.
+ *
+ * @param executor The executor on which the listener will be invoked.
+ * @param listener The listener to add.
+ * @return The {@link OnJankDataListenerRegistration} for the listener.
+ */
+ @NonNull
+ @FlaggedApi(Flags.FLAG_JANK_API)
+ @SuppressLint("PairedRegistration")
+ default SurfaceControl.OnJankDataListenerRegistration registerOnJankDataListener(
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull SurfaceControl.OnJankDataListener listener) {
+ return SurfaceControl.OnJankDataListenerRegistration.NONE;
+ }
}
diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java
index 7e247493e35ca10e90958d0d819cb3adf7a099dd..8cb96ae1d611258f550491bd43de75f89ee6b6d6 100644
--- a/core/java/android/view/Choreographer.java
+++ b/core/java/android/view/Choreographer.java
@@ -189,6 +189,11 @@ public final class Choreographer {
@UnsupportedAppUsage
private long mLastFrameTimeNanos;
+ // Keeps track of the last scheduled frame time without additional offsets
+ // added from buffer stuffing recovery. Used to compare timing of vsyncs to
+ // determine idle state.
+ private long mLastNoOffsetFrameTimeNanos;
+
/** DO NOT USE since this will not updated when screen refresh changes. */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R,
publicAlternatives = "Use {@link android.view.Display#getRefreshRate} instead")
@@ -203,6 +208,50 @@ public final class Choreographer {
private final FrameData mFrameData = new FrameData();
private volatile boolean mInDoFrameCallback = false;
+ private static class BufferStuffingData {
+ enum RecoveryAction {
+ // No recovery
+ NONE,
+ // Recovery has started, adds a negative offset
+ OFFSET,
+ // Recovery has started, delays a frame to return buffer count
+ // back toward threshold.
+ DELAY_FRAME
+ }
+ // The maximum number of times frames will be delayed per buffer stuffing event.
+ // Since buffer stuffing can persist for several consecutive frames following the
+ // initial missed frame, we want to adjust the timeline with enough frame delays and
+ // offsets to return the queued buffer count back to threshold.
+ public static final int MAX_FRAME_DELAYS = 3;
+
+ // Whether buffer stuffing recovery has begun. Recovery can only end
+ // when events are idle.
+ public boolean isRecovering = false;
+
+ // The number of frames delayed so far during recovery. Used to compare with
+ // MAX_FRAME_DELAYS to safeguard against excessive frame delays during recovery.
+ // Also used as unique cookie for tracing.
+ public int numberFrameDelays = 0;
+
+ // The number of additional frame delays scheduled during recovery to wait for the next
+ // vsync. These are scheduled when frame times appear to go backward or frames are
+ // being skipped due to FPSDivisor.
+ public int numberWaitsForNextVsync = 0;
+
+ /**
+ * After buffer stuffing recovery has ended with a detected idle state, the
+ * recovery data trackers can be reset in preparation for any future
+ * stuffing events.
+ */
+ public void reset() {
+ isRecovering = false;
+ numberFrameDelays = 0;
+ numberWaitsForNextVsync = 0;
+ }
+ }
+
+ private final BufferStuffingData mBufferStuffingData = new BufferStuffingData();
+
/**
* Contains information about the current frame for jank-tracking,
* mainly timings of key events along with a bit of metadata about
@@ -850,13 +899,99 @@ public final class Choreographer {
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
+ // Conducts logic for beginning or ending buffer stuffing recovery.
+ // Returns an enum for the recovery action that should be taken in doFrame().
+ BufferStuffingData.RecoveryAction checkBufferStuffingRecovery(long frameTimeNanos,
+ DisplayEventReceiver.VsyncEventData vsyncEventData) {
+ // Canned animations can recover from buffer stuffing whenever more
+ // than 2 buffers are queued.
+ if (vsyncEventData.numberQueuedBuffers > 2) {
+ mBufferStuffingData.isRecovering = true;
+ // Intentional frame delay that can happen at most MAX_FRAME_DELAYS times per
+ // buffer stuffing event until the buffer count returns to threshold. The
+ // delayed frames are compensated for by the negative offsets added to the
+ // animation timestamps.
+ if (mBufferStuffingData.numberFrameDelays < mBufferStuffingData.MAX_FRAME_DELAYS) {
+ if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
+ Trace.asyncTraceForTrackBegin(
+ Trace.TRACE_TAG_VIEW, "Buffer stuffing recovery", "Thread "
+ + android.os.Process.myTid() + ", recover frame #"
+ + mBufferStuffingData.numberFrameDelays,
+ mBufferStuffingData.numberFrameDelays);
+ }
+ mBufferStuffingData.numberFrameDelays++;
+ scheduleVsyncLocked();
+ return BufferStuffingData.RecoveryAction.DELAY_FRAME;
+ }
+ }
+
+ if (mBufferStuffingData.isRecovering) {
+ // Includes an additional expected frame delay from the natural scheduling
+ // of the next vsync event.
+ int totalFrameDelays = mBufferStuffingData.numberFrameDelays
+ + mBufferStuffingData.numberWaitsForNextVsync + 1;
+ long vsyncsSinceLastCallback = mLastFrameIntervalNanos > 0
+ ? (frameTimeNanos - mLastNoOffsetFrameTimeNanos) / mLastFrameIntervalNanos : 0;
+
+ // Detected idle state due to a longer inactive period since the last vsync callback
+ // than the total expected number of vsync frame delays. End buffer stuffing recovery.
+ // There are no frames to animate and offsets no longer need to be added
+ // since the idle state gives the animation a chance to catch up.
+ if (vsyncsSinceLastCallback > totalFrameDelays) {
+ if (DEBUG_JANK) {
+ Log.d(TAG, "End buffer stuffing recovery");
+ }
+ if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
+ for (int i = 0; i < mBufferStuffingData.numberFrameDelays; i++) {
+ Trace.asyncTraceForTrackEnd(
+ Trace.TRACE_TAG_VIEW, "Buffer stuffing recovery", i);
+ }
+ }
+ mBufferStuffingData.reset();
+
+ } else {
+ if (DEBUG_JANK) {
+ Log.d(TAG, "Adjust animation timeline with a negative offset");
+ }
+ if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
+ Trace.instantForTrack(
+ Trace.TRACE_TAG_VIEW, "Buffer stuffing recovery",
+ "Negative offset added to animation");
+ }
+ return BufferStuffingData.RecoveryAction.OFFSET;
+ }
+ }
+ return BufferStuffingData.RecoveryAction.NONE;
+ }
+
void doFrame(long frameTimeNanos, int frame,
DisplayEventReceiver.VsyncEventData vsyncEventData) {
final long startNanos;
final long frameIntervalNanos = vsyncEventData.frameInterval;
boolean resynced = false;
+ long offsetFrameTimeNanos = frameTimeNanos;
+
+ // Evaluate if buffer stuffing recovery needs to start or end, and
+ // what actions need to be taken for recovery.
+ switch (checkBufferStuffingRecovery(frameTimeNanos, vsyncEventData)) {
+ case NONE:
+ // Without buffer stuffing recovery, offsetFrameTimeNanos is
+ // synonymous with frameTimeNanos.
+ break;
+ case OFFSET:
+ // Add animation offset. Used to update frame timeline with
+ // offset before jitter is calculated.
+ offsetFrameTimeNanos = frameTimeNanos - frameIntervalNanos;
+ break;
+ case DELAY_FRAME:
+ // Intentional frame delay to help restore queued buffer count to threshold.
+ return;
+ default:
+ break;
+ }
+
try {
- FrameTimeline timeline = mFrameData.update(frameTimeNanos, vsyncEventData);
+ FrameTimeline timeline = mFrameData.update(offsetFrameTimeNanos, vsyncEventData);
if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
Trace.traceBegin(
Trace.TRACE_TAG_VIEW, "Choreographer#doFrame " + timeline.mVsyncId);
@@ -867,15 +1002,18 @@ public final class Choreographer {
traceMessage("Frame not scheduled");
return; // no work to do
}
+ mLastNoOffsetFrameTimeNanos = frameTimeNanos;
if (DEBUG_JANK && mDebugPrintNextFrameTimeDelta) {
mDebugPrintNextFrameTimeDelta = false;
Log.d(TAG, "Frame time delta: "
- + ((frameTimeNanos - mLastFrameTimeNanos) * 0.000001f) + " ms");
+ + ((offsetFrameTimeNanos - mLastFrameTimeNanos) * 0.000001f) + " ms");
}
- long intendedFrameTimeNanos = frameTimeNanos;
+ long intendedFrameTimeNanos = offsetFrameTimeNanos;
startNanos = System.nanoTime();
+ // Calculating jitter involves using the original frame time without
+ // adjustments from buffer stuffing
final long jitterNanos = startNanos - frameTimeNanos;
if (jitterNanos >= frameIntervalNanos) {
frameTimeNanos = startNanos;
@@ -899,6 +1037,13 @@ public final class Choreographer {
+ " ms in the past.");
}
}
+ if (mBufferStuffingData.isRecovering) {
+ frameTimeNanos -= frameIntervalNanos;
+ if (DEBUG_JANK) {
+ Log.d(TAG, "Adjusted animation timeline with a negative offset after"
+ + " jitter calculation");
+ }
+ }
timeline = mFrameData.update(
frameTimeNanos, mDisplayEventReceiver, jitterNanos);
resynced = true;
@@ -910,6 +1055,9 @@ public final class Choreographer {
+ "previously skipped frame. Waiting for next vsync.");
}
traceMessage("Frame time goes backward");
+ if (mBufferStuffingData.isRecovering) {
+ mBufferStuffingData.numberWaitsForNextVsync++;
+ }
scheduleVsyncLocked();
return;
}
@@ -918,6 +1066,9 @@ public final class Choreographer {
long timeSinceVsync = frameTimeNanos - mLastFrameTimeNanos;
if (timeSinceVsync < (frameIntervalNanos * mFPSDivisor) && timeSinceVsync > 0) {
traceMessage("Frame skipped due to FPSDivisor");
+ if (mBufferStuffingData.isRecovering) {
+ mBufferStuffingData.numberWaitsForNextVsync++;
+ }
scheduleVsyncLocked();
return;
}
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 0241e943795077e5b9f0d914b7567e8e54096aa5..a1a9fc697271cf2411df978e7ea8af4cd38bc54e 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -1786,7 +1786,12 @@ public final class Display {
* {@code getWindowManager()} or {@code getSystemService(Context.WINDOW_SERVICE)}), the
* returned metrics provide the size of the current app window. As a result, in
* multi-window mode, the returned size can be smaller than the size of the device
- * screen.
+ * screen. System decoration handling may vary depending on API level:
+ *
+ * - API level 35 and above, the window size will be returned.
+ *
- API level 34 and below, the window size minus system decoration areas and
+ * display cutout is returned.
+ *
* If metrics are requested from a non-activity context (for example, the application
* context, where the WindowManager is accessed by
* {@code getApplicationContext().getSystemService(Context.WINDOW_SERVICE)}), the
diff --git a/core/java/android/view/DisplayEventReceiver.java b/core/java/android/view/DisplayEventReceiver.java
index fc7a65dbdc41a14e365f87df9185d6f309cd3e5e..bb233d2711de05ab0f41a53e27c36a1ff9f1be81 100644
--- a/core/java/android/view/DisplayEventReceiver.java
+++ b/core/java/android/view/DisplayEventReceiver.java
@@ -207,6 +207,8 @@ public abstract class DisplayEventReceiver {
// reasonable timestamps.
public int frameTimelinesLength = 1;
+ public int numberQueuedBuffers = 0;
+
VsyncEventData() {
frameTimelines = new FrameTimeline[FRAME_TIMELINES_CAPACITY];
for (int i = 0; i < frameTimelines.length; i++) {
@@ -217,11 +219,13 @@ public abstract class DisplayEventReceiver {
// Called from native code.
@SuppressWarnings("unused")
VsyncEventData(FrameTimeline[] frameTimelines, int preferredFrameTimelineIndex,
- int frameTimelinesLength, long frameInterval) {
+ int frameTimelinesLength, long frameInterval,
+ int numberQueuedBuffers) {
this.frameTimelines = frameTimelines;
this.preferredFrameTimelineIndex = preferredFrameTimelineIndex;
this.frameTimelinesLength = frameTimelinesLength;
this.frameInterval = frameInterval;
+ this.numberQueuedBuffers = numberQueuedBuffers;
}
void copyFrom(VsyncEventData other) {
@@ -231,6 +235,7 @@ public abstract class DisplayEventReceiver {
for (int i = 0; i < frameTimelines.length; i++) {
frameTimelines[i].copyFrom(other.frameTimelines[i]);
}
+ numberQueuedBuffers = other.numberQueuedBuffers;
}
public FrameTimeline preferredFrameTimeline() {
diff --git a/core/java/android/view/FrameMetrics.java b/core/java/android/view/FrameMetrics.java
index 9e25a3e18c0c8d7aa60322f7c947361ee3e9c86b..58b2a67ec69ef9bc2c572d6a58b212c18b34d470 100644
--- a/core/java/android/view/FrameMetrics.java
+++ b/core/java/android/view/FrameMetrics.java
@@ -18,10 +18,13 @@ package android.view;
import static android.graphics.FrameInfo.FLAG_WINDOW_VISIBILITY_CHANGED;
+import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
+import com.android.window.flags.Flags;
+
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -176,6 +179,16 @@ public final class FrameMetrics {
**/
public static final int DEADLINE = 13;
+ /**
+ * Metric identifier for the frame's VSync identifier.
+ *
+ * The id that corresponds to the chosen frame timeline, used to correlate a frame produced
+ * by HWUI with the timeline data from the compositor.
+ *
+ */
+ @FlaggedApi(Flags.FLAG_JANK_API)
+ public static final int FRAME_TIMELINE_VSYNC_ID = 14;
+
/**
* Identifiers for metrics available for each frame.
*
@@ -337,7 +350,8 @@ public final class FrameMetrics {
* @return the value of the metric or -1 if it is not available.
*/
public long getMetric(@Metric int id) {
- if (id < UNKNOWN_DELAY_DURATION || id > DEADLINE) {
+ if (id < UNKNOWN_DELAY_DURATION
+ || id > (Flags.jankApi() ? FRAME_TIMELINE_VSYNC_ID : DEADLINE)) {
return -1;
}
@@ -351,6 +365,8 @@ public final class FrameMetrics {
return mTimingData[Index.INTENDED_VSYNC];
} else if (id == VSYNC_TIMESTAMP) {
return mTimingData[Index.VSYNC];
+ } else if (id == FRAME_TIMELINE_VSYNC_ID) {
+ return mTimingData[Index.FRAME_TIMELINE_VSYNC_ID];
}
int durationsIdx = 2 * id;
@@ -358,4 +374,3 @@ public final class FrameMetrics {
- mTimingData[DURATIONS[durationsIdx]];
}
}
-
diff --git a/core/java/android/view/HapticScrollFeedbackProvider.java b/core/java/android/view/HapticScrollFeedbackProvider.java
index 0001176220b58a90808e4905c3801959598703ef..c3fb855eb1ffe7de6e8a6459392a48b10d97e15c 100644
--- a/core/java/android/view/HapticScrollFeedbackProvider.java
+++ b/core/java/android/view/HapticScrollFeedbackProvider.java
@@ -16,6 +16,8 @@
package android.view;
+import static android.view.flags.Flags.dynamicViewRotaryHapticsConfiguration;
+
import android.annotation.NonNull;
import com.android.internal.annotations.VisibleForTesting;
@@ -41,13 +43,8 @@ public class HapticScrollFeedbackProvider implements ScrollFeedbackProvider {
private final View mView;
private final ViewConfiguration mViewConfig;
- /**
- * Flag to disable the logic in this class if the View-based scroll haptics implementation is
- * enabled. If {@code false}, this class will continue to run despite the View's scroll
- * haptics implementation being enabled. This value should be set to {@code true} when this
- * class is directly used by the View class.
- */
- private final boolean mDisabledIfViewPlaysScrollHaptics;
+ /** Whether or not this provider is being used directly by the View class. */
+ private final boolean mIsFromView;
// Info about the cause of the latest scroll event.
@@ -65,17 +62,23 @@ public class HapticScrollFeedbackProvider implements ScrollFeedbackProvider {
private boolean mHapticScrollFeedbackEnabled = false;
public HapticScrollFeedbackProvider(@NonNull View view) {
- this(view, ViewConfiguration.get(view.getContext()),
- /* disabledIfViewPlaysScrollHaptics= */ true);
+ this(view, ViewConfiguration.get(view.getContext()), /* isFromView= */ false);
}
/** @hide */
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
public HapticScrollFeedbackProvider(
- View view, ViewConfiguration viewConfig, boolean disabledIfViewPlaysScrollHaptics) {
+ View view, ViewConfiguration viewConfig, boolean isFromView) {
mView = view;
mViewConfig = viewConfig;
- mDisabledIfViewPlaysScrollHaptics = disabledIfViewPlaysScrollHaptics;
+ mIsFromView = isFromView;
+ if (dynamicViewRotaryHapticsConfiguration() && !isFromView) {
+ // Disable the View class's rotary scroll feedback logic if this provider is not being
+ // directly used by the View class. This is to avoid double rotary scroll feedback:
+ // one from the View class, and one from this provider instance (i.e. mute the View
+ // class's rotary feedback and enable this provider).
+ view.disableRotaryScrollFeedback();
+ }
}
@Override
@@ -151,7 +154,8 @@ public class HapticScrollFeedbackProvider implements ScrollFeedbackProvider {
mAxis = axis;
mDeviceId = deviceId;
- if (mDisabledIfViewPlaysScrollHaptics
+ if (!dynamicViewRotaryHapticsConfiguration()
+ && !mIsFromView
&& (source == InputDevice.SOURCE_ROTARY_ENCODER)
&& mViewConfig.isViewBasedRotaryEncoderHapticScrollFeedbackEnabled()) {
mHapticScrollFeedbackEnabled = false;
diff --git a/core/java/android/view/ImeFocusController.java b/core/java/android/view/ImeFocusController.java
index 97148969e17f0d1509a1a5df0ebbeb1e0b804017..2d2f79d760083a18f51f2570c0515ebf7f21506f 100644
--- a/core/java/android/view/ImeFocusController.java
+++ b/core/java/android/view/ImeFocusController.java
@@ -23,6 +23,7 @@ import android.annotation.NonNull;
import android.annotation.UiThread;
import android.util.Log;
import android.util.proto.ProtoOutputStream;
+import android.view.inputmethod.Flags;
import android.view.inputmethod.InputMethodManager;
import com.android.internal.inputmethod.InputMethodDebug;
@@ -150,6 +151,17 @@ public final class ImeFocusController {
if (!mHasImeFocus || isInLocalFocusMode(windowAttribute)) {
return InputMethodManager.DISPATCH_NOT_HANDLED;
}
+ if (Flags.refactorInsetsController() && event instanceof KeyEvent keyEvent
+ && keyEvent.getKeyCode() == KeyEvent.KEYCODE_BACK) {
+ final var insetsController = mViewRootImpl.getInsetsController();
+ if (insetsController.getAnimationType(WindowInsets.Type.ime())
+ == InsetsController.ANIMATION_TYPE_HIDE
+ || insetsController.isPredictiveBackImeHideAnimInProgress()) {
+ // if there is an ongoing hide animation, the back event should not be dispatched
+ // to the IME.
+ return InputMethodManager.DISPATCH_NOT_HANDLED;
+ }
+ }
final InputMethodManager imm =
mViewRootImpl.mContext.getSystemService(InputMethodManager.class);
if (imm == null) {
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index 26ca813a9caac53540c8edeb2744afa51f7cc828..b0813f3a98f69dc962697aa7f6b2ed84d70752b7 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -1910,7 +1910,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
mImeSourceConsumer.onWindowFocusLost();
}
- @VisibleForTesting
+ /** Returns the current {@link AnimationType} of an {@link InsetsType}. */
+ @VisibleForTesting(visibility = PACKAGE)
public @AnimationType int getAnimationType(@InsetsType int type) {
for (int i = mRunningAnimations.size() - 1; i >= 0; i--) {
InsetsAnimationControlRunner control = mRunningAnimations.get(i).runner;
diff --git a/core/java/android/view/ScaleGestureDetector.java b/core/java/android/view/ScaleGestureDetector.java
index 5a28d5f7fc019d1170607274ee33472289e001df..80ae3c3d4e7306dae4e16e20fd87a5dfd32d75cc 100644
--- a/core/java/android/view/ScaleGestureDetector.java
+++ b/core/java/android/view/ScaleGestureDetector.java
@@ -437,16 +437,16 @@ public class ScaleGestureDetector {
}
}
- /**
- * Return whether the quick scale gesture, in which the user performs a double tap followed by a
- * swipe, should perform scaling. {@see #setQuickScaleEnabled(boolean)}.
- */
+ /**
+ * Return whether the quick scale gesture, in which the user performs a double tap followed by a
+ * swipe, should perform scaling. {@see #setQuickScaleEnabled(boolean)}.
+ */
public boolean isQuickScaleEnabled() {
return mQuickScaleEnabled;
}
/**
- * Sets whether the associates {@link OnScaleGestureListener} should receive
+ * Sets whether the associated {@link OnScaleGestureListener} should receive
* onScale callbacks when the user uses a stylus and presses the button.
* Note that this is enabled by default if the app targets API 23 and newer.
*
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 206c7375608814709b273947665bdc5f8f1dfab1..d56768d2db031e26c1b57067ccda5a4f9aa9e635 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -22,6 +22,7 @@ import static android.graphics.Matrix.MSKEW_X;
import static android.graphics.Matrix.MSKEW_Y;
import static android.graphics.Matrix.MTRANS_X;
import static android.graphics.Matrix.MTRANS_Y;
+import static android.view.flags.Flags.bufferStuffingRecovery;
import static android.view.SurfaceControlProto.HASH_CODE;
import static android.view.SurfaceControlProto.LAYER_ID;
import static android.view.SurfaceControlProto.NAME;
@@ -410,8 +411,19 @@ public final class SurfaceControl implements Parcelable {
/**
* Jank information to be fed back via {@link OnJankDataListener}.
- * @hide
+ *
+ * Apps may register a {@link OnJankDataListener} to get periodic batches of jank classification
+ * data from the (
+ * composer regarding rendered frames. A frame is considered janky if it did not reach the
+ * display at the intended time, typically due to missing a rendering deadline. This API
+ * provides information that can be used to identify the root cause of the scheduling misses
+ * and provides overall frame scheduling statistics.
+ *
+ * This API can be used in conjunction with the {@link FrameMetrics} API by associating jank
+ * classification data with {@link FrameMetrics} data via the frame VSync id.
*/
+ @FlaggedApi(Flags.FLAG_JANK_API)
public static class JankData {
/**
@@ -428,29 +440,105 @@ public final class SurfaceControl implements Parcelable {
@Retention(RetentionPolicy.SOURCE)
public @interface JankType {}
- // No Jank
+ /**
+ * No jank detected, the frame was on time.
+ */
public static final int JANK_NONE = 0;
- // Jank caused by the composer missing a deadline
+
+ /**
+ * Bitmask for jank due to deadlines missed by the composer.
+ */
public static final int JANK_COMPOSER = 1 << 0;
- // Jank caused by the application missing the composer's deadline
+
+ /**
+ * Bitmask for jank due to deadlines missed by the application.
+ */
public static final int JANK_APPLICATION = 1 << 1;
- // Jank due to other unknown reasons
+
+ /**
+ * Bitmask for jank due to deadlines missed by other system components.
+ */
public static final int JANK_OTHER = 1 << 2;
+ private final long mFrameVsyncId;
+ private final @JankType int mJankType;
+ private final long mFrameIntervalNs;
+ private final long mScheduledAppFrameTimeNs;
+ private final long mActualAppFrameTimeNs;
+
+ /**
+ * @hide
+ */
public JankData(long frameVsyncId, @JankType int jankType, long frameIntervalNs,
long scheduledAppFrameTimeNs, long actualAppFrameTimeNs) {
- this.frameVsyncId = frameVsyncId;
- this.jankType = jankType;
- this.frameIntervalNs = frameIntervalNs;
- this.scheduledAppFrameTimeNs = scheduledAppFrameTimeNs;
- this.actualAppFrameTimeNs = actualAppFrameTimeNs;
- }
-
- public final long frameVsyncId;
- public final @JankType int jankType;
- public final long frameIntervalNs;
- public final long scheduledAppFrameTimeNs;
- public final long actualAppFrameTimeNs;
+ mFrameVsyncId = frameVsyncId;
+ mJankType = jankType;
+ mFrameIntervalNs = frameIntervalNs;
+ mScheduledAppFrameTimeNs = scheduledAppFrameTimeNs;
+ mActualAppFrameTimeNs = actualAppFrameTimeNs;
+ }
+
+ /**
+ * Returns the id of the frame for this jank classification.
+ *
+ * @see FrameMetrics#FRAME_TIMELINE_VSYNC_ID
+ * @see Choreographer.FrameTimeline#getVsyncId
+ * @see Transaction#setFrameTimeline
+ * @return the frame id
+ */
+ public long getVsyncId() {
+ return mFrameVsyncId;
+ }
+
+ /**
+ * Returns the bitmask indicating the types of jank observed.
+ *
+ * @return the jank type bitmask
+ */
+ public @JankType int getJankType() {
+ return mJankType;
+ }
+
+ /**
+ * Returns the time between frame VSyncs in nanoseconds.
+ *
+ * @return the frame interval in ns
+ * @hide
+ */
+ public long getFrameIntervalNanos() {
+ return mFrameIntervalNs;
+ }
+
+ /**
+ * Returns the duration in nanoseconds the application was scheduled to use to render this
+ * frame.
+ *
+ * Note that this may be higher than the frame interval to allow for CPU/GPU
+ * parallelization of work.
+ *
+ * @return scheduled app time in ns
+ */
+ public long getScheduledAppFrameTimeNanos() {
+ return mScheduledAppFrameTimeNs;
+ }
+
+ /**
+ * Returns the actual time in nanoseconds taken by the application to render this frame.
+ *
+ * @return the actual app time in ns
+ */
+ public long getActualAppFrameTimeNanos() {
+ return mActualAppFrameTimeNs;
+ }
+
+ @Override
+ public String toString() {
+ return "JankData{vsync=" + mFrameVsyncId
+ + ", jankType=0x" + Integer.toHexString(mJankType)
+ + ", frameInterval=" + mFrameIntervalNs + "ns"
+ + ", scheduledAppTime=" + mScheduledAppFrameTimeNs + "ns"
+ + ", actualAppTime=" + mActualAppFrameTimeNs + "ns}";
+ }
}
/**
@@ -458,12 +546,13 @@ public final class SurfaceControl implements Parcelable {
* surface.
*
* @see JankData
- * @see #addJankDataListener
- * @hide
+ * @see #addOnJankDataListener
*/
+ @FlaggedApi(Flags.FLAG_JANK_API)
public interface OnJankDataListener {
/**
- * Called when new jank classifications are available.
+ * Called when new jank classifications are available. The listener is invoked out of band
+ * of the rendered frames with jank classification data for a batch of frames.
*/
void onJankDataAvailable(@NonNull List jankData);
@@ -471,9 +560,22 @@ public final class SurfaceControl implements Parcelable {
/**
* Handle to a registered {@link OnJankDatalistener}.
- * @hide
*/
+ @FlaggedApi(Flags.FLAG_JANK_API)
public static class OnJankDataListenerRegistration {
+ /** @hide */
+ public static final OnJankDataListenerRegistration NONE =
+ new OnJankDataListenerRegistration() {
+ @Override
+ public void flush() {}
+
+ @Override
+ public void removeAfter(long afterVsync) {}
+
+ @Override
+ public void release() {}
+ };
+
private final long mNativeObject;
private static final NativeAllocationRegistry sRegistry =
@@ -484,6 +586,11 @@ public final class SurfaceControl implements Parcelable {
private final Runnable mFreeNativeResources;
private boolean mRemoved = false;
+ private OnJankDataListenerRegistration() {
+ mNativeObject = 0;
+ mFreeNativeResources = () -> {};
+ }
+
OnJankDataListenerRegistration(SurfaceControl surface, OnJankDataListener listener) {
mNativeObject = nativeCreateJankDataListenerWrapper(surface.mNativeObject, listener);
mFreeNativeResources = (mNativeObject == 0) ? () -> {} :
@@ -499,10 +606,17 @@ public final class SurfaceControl implements Parcelable {
}
/**
- * Request the removal of the registered listener after the VSync with the provided ID. Use
- * a value <= 0 for afterVsync to remove the listener immediately. The given listener will
- * not be removed before the given VSync, but may still reveive data for frames past the
- * provided VSync.
+ * Schedule the removal of the registered listener after the frame with the provided id.
+ *
+ * Because jank classification is only possible after frames have been displayed, the
+ * callbacks are always delayed. To ensure receipt of all jank classification data, an
+ * application can schedule the removal to happen no sooner than after the data for the
+ * frame with the provided id has been provided.
+ *
+ * Use a value <= 0 for afterVsync to remove the listener immediately, ensuring no future
+ * callbacks.
+ *
+ * @param afterVsync the id of the Vsync after which to remove the listener
*/
public void removeAfter(long afterVsync) {
mRemoved = true;
@@ -511,6 +625,7 @@ public final class SurfaceControl implements Parcelable {
/**
* Free the native resources associated with the listener registration.
+ * @hide
*/
public void release() {
if (!mRemoved) {
@@ -662,6 +777,13 @@ public final class SurfaceControl implements Parcelable {
*/
public static final int CAN_OCCLUDE_PRESENTATION = 0x00001000;
+ /**
+ * Indicates that the SurfaceControl should recover from buffer stuffing when
+ * possible. This is the case when the SurfaceControl is a ViewRootImpl.
+ * @hide
+ */
+ public static final int RECOVERABLE_FROM_BUFFER_STUFFING = 0x00002000;
+
/**
* Surface creation flag: Creates a surface where color components are interpreted
* as "non pre-multiplied" by their alpha channel. Of course this flag is
@@ -4444,14 +4566,31 @@ public final class SurfaceControl implements Parcelable {
return this;
}
- /** @hide */
+ /**
+ * Sets the Luts for the layer.
+ *
+ *
The function also allows to clear previously applied lut(s). To do this,
+ * set the displayluts to be either {@code nullptr} or
+ * an empty {@link android.hardware.DisplayLuts} instance.
+ *
+ * @param sc The SurfaceControl to update
+ *
+ * @param displayLuts The selected Lut(s)
+ *
+ * @return this
+ * @see DisplayLuts
+ */
+ @FlaggedApi(android.hardware.flags.Flags.FLAG_LUTS_API)
public @NonNull Transaction setLuts(@NonNull SurfaceControl sc,
- @NonNull DisplayLuts displayLuts) {
+ @Nullable DisplayLuts displayLuts) {
checkPreconditions(sc);
-
- nativeSetLuts(mNativeObject, sc.mNativeObject, displayLuts.getLutBuffers(),
- displayLuts.getOffsets(), displayLuts.getLutDimensions(),
- displayLuts.getLutSizes(), displayLuts.getLutSamplingKeys());
+ if (displayLuts != null && displayLuts.valid()) {
+ nativeSetLuts(mNativeObject, sc.mNativeObject, displayLuts.getLutBuffers(),
+ displayLuts.getOffsets(), displayLuts.getLutDimensions(),
+ displayLuts.getLutSizes(), displayLuts.getLutSamplingKeys());
+ } else {
+ nativeSetLuts(mNativeObject, sc.mNativeObject, null, null, null, null, null);
+ }
return this;
}
@@ -4867,6 +5006,23 @@ public final class SurfaceControl implements Parcelable {
nativeSetDesiredPresentTimeNanos(mNativeObject, desiredPresentTimeNanos);
return this;
}
+
+ /**
+ * Specifies that the SurfaceControl is a buffer producer that should recover from buffer
+ * stuffing, meaning that the SurfaceControl is a ViewRootImpl.
+ *
+ * @hide
+ */
+ @NonNull
+ public Transaction setRecoverableFromBufferStuffing(@NonNull SurfaceControl sc) {
+ if (bufferStuffingRecovery()) {
+ checkPreconditions(sc);
+ nativeSetFlags(mNativeObject, sc.mNativeObject, RECOVERABLE_FROM_BUFFER_STUFFING,
+ RECOVERABLE_FROM_BUFFER_STUFFING);
+ }
+ return this;
+ }
+
/**
* Writes the transaction to parcel, clearing the transaction as if it had been applied so
* it can be used to store future transactions. It's the responsibility of the parcel
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index fa06831f65141854f45678b0cd76b11ebdd870e7..049189f8af8d4db876b234b4d6b16bcce32ba874 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -65,6 +65,7 @@ import static com.android.internal.util.FrameworkStatsLog.TOUCH_GESTURE_CLASSIFI
import static com.android.internal.util.FrameworkStatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__SINGLE_TAP;
import static com.android.internal.util.FrameworkStatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__UNKNOWN_CLASSIFICATION;
import static com.android.window.flags.Flags.FLAG_DELEGATE_UNHANDLED_DRAGS;
+import static com.android.window.flags.Flags.FLAG_SUPPORTS_DRAG_ASSISTANT_TO_MULTIWINDOW;
import static java.lang.Math.max;
@@ -91,6 +92,8 @@ import android.annotation.TestApi;
import android.annotation.UiContext;
import android.annotation.UiThread;
import android.app.PendingIntent;
+import android.app.jank.AppJankStats;
+import android.app.jank.JankTracker;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.AutofillOptions;
import android.content.ClipData;
@@ -5550,10 +5553,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
/**
* Flag indicating that this drag will result in the caller activity's task to be hidden for the
- * duration of the drag, this means that the source activity will not receive drag events for
- * the current drag gesture. Only the current voice interaction service may use this flag.
- * @hide
+ * duration of the drag, which means that the source activity will not receive drag events for
+ * the current drag gesture. Only the current
+ * {@link android.service.voice.VoiceInteractionService} may use this flag.
*/
+ @FlaggedApi(FLAG_SUPPORTS_DRAG_ASSISTANT_TO_MULTIWINDOW)
public static final int DRAG_FLAG_HIDE_CALLING_TASK_ON_DRAG_START = 1 << 14;
/**
@@ -16750,9 +16754,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
mPrivateFlags4 |= PFLAG4_ROTARY_HAPTICS_DETERMINED;
}
}
- final boolean processForRotaryScrollHaptics =
- isRotaryEncoderEvent && ((mPrivateFlags4 & PFLAG4_ROTARY_HAPTICS_ENABLED) != 0);
- if (processForRotaryScrollHaptics) {
+ if (isRotaryEncoderEvent && ((mPrivateFlags4 & PFLAG4_ROTARY_HAPTICS_ENABLED) != 0)) {
mPrivateFlags4 &= ~PFLAG4_ROTARY_HAPTICS_SCROLL_SINCE_LAST_ROTARY_INPUT;
mPrivateFlags4 |= PFLAG4_ROTARY_HAPTICS_WAITING_FOR_SCROLL_EVENT;
}
@@ -16769,7 +16771,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
// Process scroll haptics after `onGenericMotionEvent`, since that's where scrolling usually
// happens. Some views may return false from `onGenericMotionEvent` even if they have done
// scrolling, so disregard the return value when processing for scroll haptics.
- if (processForRotaryScrollHaptics) {
+ // Check for `PFLAG4_ROTARY_HAPTICS_ENABLED` again, because the View implementation may
+ // call `disableRotaryScrollFeedback` in `onGenericMotionEvent`, which could change the
+ // value of `PFLAG4_ROTARY_HAPTICS_ENABLED`.
+ if (isRotaryEncoderEvent && ((mPrivateFlags4 & PFLAG4_ROTARY_HAPTICS_ENABLED) != 0)) {
if ((mPrivateFlags4 & PFLAG4_ROTARY_HAPTICS_SCROLL_SINCE_LAST_ROTARY_INPUT) != 0) {
doRotaryProgressForScrollHaptics(event);
} else {
@@ -18712,7 +18717,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
private HapticScrollFeedbackProvider getScrollFeedbackProvider() {
if (mScrollFeedbackProvider == null) {
mScrollFeedbackProvider = new HapticScrollFeedbackProvider(this,
- ViewConfiguration.get(mContext), /* disabledIfViewPlaysScrollHaptics= */ false);
+ ViewConfiguration.get(mContext), /* isFromView= */ true);
}
return mScrollFeedbackProvider;
}
@@ -18741,6 +18746,21 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
}
+ /**
+ * Disables the rotary scroll feedback implementation of the View class.
+ *
+ *
Note that this does NOT disable all rotary scroll feedback; it just disables the logic
+ * implemented within the View class. The child implementation of the View may implement its own
+ * rotary scroll feedback logic or use {@link ScrollFeedbackProvider} to generate rotary scroll
+ * feedback.
+ */
+ void disableRotaryScrollFeedback() {
+ // Force set PFLAG4_ROTARY_HAPTICS_DETERMINED to avoid recalculating
+ // PFLAG4_ROTARY_HAPTICS_ENABLED under any circumstance.
+ mPrivateFlags4 |= PFLAG4_ROTARY_HAPTICS_DETERMINED;
+ mPrivateFlags4 &= ~PFLAG4_ROTARY_HAPTICS_ENABLED;
+ }
+
/**
* This is called in response to an internal scroll in this view (i.e., the
* view scrolled its own contents). This is typically as a result of
@@ -34420,4 +34440,21 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
boolean getSelfRequestedFrameRateFlag() {
return (mPrivateFlags4 & PFLAG4_SELF_REQUESTED_FRAME_RATE) != 0;
}
+
+ /**
+ * Called from apps when they want to report jank stats to the system.
+ * @param appJankStats the stats that will be merged with the stats collected by the system.
+ */
+ @FlaggedApi(android.app.jank.Flags.FLAG_DETAILED_APP_JANK_METRICS_API)
+ public void reportAppJankStats(@NonNull AppJankStats appJankStats) {
+ getRootView().reportAppJankStats(appJankStats);
+ }
+
+ /**
+ * Called by widgets to get a reference to JankTracker in order to update states.
+ * @hide
+ */
+ public @Nullable JankTracker getJankTracker() {
+ return getRootView().getJankTracker();
+ }
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 75d2da1b70e4cf963e8411d729a9f12964b3c80d..19d3dc4df04e83784a0d7f1c712735e0fb52f123 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -140,6 +140,8 @@ import android.accessibilityservice.AccessibilityService;
import android.animation.AnimationHandler;
import android.animation.LayoutTransition;
import android.annotation.AnyThread;
+import android.annotation.CallbackExecutor;
+import android.annotation.FlaggedApi;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Size;
@@ -1250,7 +1252,6 @@ public final class ViewRootImpl implements ViewParent,
mExtraDisplayListenerLogging = !TextUtils.isEmpty(name) && name.equals(mBasePackageName);
mThread = Thread.currentThread();
mLocation = new WindowLeaked(null);
- mLocation.fillInStackTrace();
mWidth = -1;
mHeight = -1;
mDirty = new Rect();
@@ -2515,6 +2516,11 @@ public final class ViewRootImpl implements ViewParent,
public void notifyInsetsAnimationRunningStateChanged(boolean running) {
if (sToolkitSetFrameRateReadOnlyFlagValue) {
mInsetsAnimationRunning = running;
+ if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
+ Trace.instant(Trace.TRACE_TAG_VIEW,
+ TextUtils.formatSimple("notifyInsetsAnimationRunningStateChanged(%s)",
+ Boolean.toString(running)));
+ }
}
}
@@ -2758,6 +2764,9 @@ public final class ViewRootImpl implements ViewParent,
// Only call transferFrom if the surface has changed to prevent inc the generation ID and
// causing EGL resources to be recreated.
mSurface.transferFrom(blastSurface);
+
+ // Since the SurfaceControl is a VRI, indicate that it can recover from buffer stuffing.
+ mTransaction.setRecoverableFromBufferStuffing(mSurfaceControl).applyAsyncUnsafe();
}
private void setBoundsLayerCrop(Transaction t) {
@@ -11896,6 +11905,20 @@ public final class ViewRootImpl implements ViewParent,
return mAttachInfo.mWindowToken;
}
+ /**
+ * {@inheritDoc}
+ */
+ @NonNull
+ @Override
+ @FlaggedApi(com.android.window.flags.Flags.FLAG_JANK_API)
+ public SurfaceControl.OnJankDataListenerRegistration registerOnJankDataListener(
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull SurfaceControl.OnJankDataListener listener) {
+ SurfaceControl.OnJankDataListener wrapped = (data) ->
+ executor.execute(() -> listener.onJankDataAvailable(data));
+ return mSurfaceControl.addOnJankDataListener(wrapped);
+ }
+
/**
* Class for managing the accessibility interaction connection
* based on the global accessibility state.
diff --git a/core/java/android/view/ViewStructure.java b/core/java/android/view/ViewStructure.java
index 1af9387e6fbdafd6f271c418aabcb2bfa1771e7a..1be7f4849f07a1b7291191643b82219ca5a528fa 100644
--- a/core/java/android/view/ViewStructure.java
+++ b/core/java/android/view/ViewStructure.java
@@ -17,6 +17,7 @@
package android.view;
import static android.service.autofill.Flags.FLAG_AUTOFILL_CREDMAN_DEV_INTEGRATION;
+import static android.service.autofill.Flags.FLAG_AUTOFILL_W_METRICS;
import android.annotation.FlaggedApi;
import android.annotation.NonNull;
@@ -79,27 +80,24 @@ public abstract class ViewStructure {
* Key used for writing the type of the view that generated the virtual structure of its
* children.
*
- * For example, if the virtual structure is generated by a webview, the value would be
+ *
For example, if the virtual structure is generated by a webview, the value would be
* "WebView". If the virtual structure is generated by a compose view, then the value would be
* "ComposeView". The value is of type String.
*
- * This value is added to mainly help with debugging purpose.
- *
- * @hide
+ *
This value is added to mainly help with debugging purpose.
*/
+ @FlaggedApi(FLAG_AUTOFILL_W_METRICS)
public static final String EXTRA_VIRTUAL_STRUCTURE_TYPE =
"android.view.ViewStructure.extra.VIRTUAL_STRUCTURE_TYPE";
-
/**
* Key used for specifying the version of the view that generated the virtual structure for
* itself and its children
*
- * For example, if the virtual structure is generated by a webview of version "104.0.5112.69",
- * then the value should be "104.0.5112.69"
- *
- * @hide
+ *
For example, if the virtual structure is generated by a webview of version
+ * "104.0.5112.69", then the value should be "104.0.5112.69"
*/
+ @FlaggedApi(FLAG_AUTOFILL_W_METRICS)
public static final String EXTRA_VIRTUAL_STRUCTURE_VERSION_NUMBER =
"android.view.ViewStructure.extra.VIRTUAL_STRUCTURE_VERSION_NUMBER";
diff --git a/core/java/android/view/WindowMetrics.java b/core/java/android/view/WindowMetrics.java
index 8bcc9de118e21549d7f85e6438c74c9e59f2c931..12af692a45568753b368a29a344c4299a9fa6a28 100644
--- a/core/java/android/view/WindowMetrics.java
+++ b/core/java/android/view/WindowMetrics.java
@@ -107,8 +107,8 @@ public final class WindowMetrics {
* and display cutout areas depending on the calling context and target SDK level. Please refer
* to {@link Display#getSize(Point)} for details.
*
- * The value reported by {@link Display#getSize(Point)} excluding system decoration areas can be
- * obtained by using:
+ * The following code snippet shows how to get the bounds excluding navigation bars and display
+ * cutout:
*
* final WindowMetrics metrics = windowManager.getCurrentWindowMetrics();
* // Gets all excluding insets
diff --git a/core/java/android/view/autofill/AutofillId.java b/core/java/android/view/autofill/AutofillId.java
index 6b608582c1dd18b27f14a90ed084c080391c3564..bd277784c1d3de1a20746f4488a5f48f448b5658 100644
--- a/core/java/android/view/autofill/AutofillId.java
+++ b/core/java/android/view/autofill/AutofillId.java
@@ -15,6 +15,9 @@
*/
package android.view.autofill;
+import static android.service.autofill.Flags.FLAG_AUTOFILL_W_METRICS;
+
+import android.annotation.FlaggedApi;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
@@ -111,11 +114,42 @@ public final class AutofillId implements Parcelable {
return new AutofillId(flags, id.mViewId, virtualChildId, NO_SESSION);
}
- /** @hide */
+ /**
+ * Returns the assigned unique identifier of this AutofillID.
+ *
+ * See @link{android.view.View#getAutofillId()} for more information on
+ * how this is generated for native Views.
+ */
+ @FlaggedApi(FLAG_AUTOFILL_W_METRICS)
public int getViewId() {
return mViewId;
}
+ /**
+ * Gets the virtual id. This is set if the view is a virtual view, most commonly set if the View
+ * is of {@link android.webkit.WebView}.
+ */
+ @FlaggedApi(FLAG_AUTOFILL_W_METRICS)
+ public int getAutofillVirtualId() {
+ return mVirtualIntId;
+ }
+
+ /** Checks whether this AutofillId represents a virtual view. */
+ @FlaggedApi(FLAG_AUTOFILL_W_METRICS)
+ public boolean isVirtual() {
+ return !isNonVirtual();
+ }
+
+ /**
+ * Checks if this node is generate as part of a {@link android.app.assist.AssistStructure}. This
+ * will usually return true if it should be used by an autofill service provider, and false
+ * otherwise.
+ */
+ @FlaggedApi(FLAG_AUTOFILL_W_METRICS)
+ public boolean isInAutofillSession() {
+ return hasSession();
+ }
+
/**
* Gets the virtual child id.
*
@@ -181,7 +215,12 @@ public final class AutofillId implements Parcelable {
return (mFlags & FLAG_HAS_SESSION) != 0;
}
- /** @hide */
+ /**
+ * Used to get the Session identifier associated with this AutofillId.
+ *
+ * @return a non-zero integer if {@link #isInAutofillSession()} returns true
+ */
+ @FlaggedApi(FLAG_AUTOFILL_W_METRICS)
public int getSessionId() {
return mSessionId;
}
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index 1a45939f65b626dd74bc527b7270f4d7c78138e7..52c5af8889ec494b81e3e65d583bcd86d94c55eb 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -25,12 +25,14 @@ import static android.service.autofill.FillRequest.FLAG_SCREEN_HAS_CREDMAN_FIELD
import static android.service.autofill.FillRequest.FLAG_SUPPORTS_FILL_DIALOG;
import static android.service.autofill.FillRequest.FLAG_VIEW_NOT_FOCUSED;
import static android.service.autofill.FillRequest.FLAG_VIEW_REQUESTS_CREDMAN_SERVICE;
+import static android.service.autofill.Flags.FLAG_FILL_DIALOG_IMPROVEMENTS;
import static android.view.ContentInfo.SOURCE_AUTOFILL;
import static android.view.autofill.Helper.sDebug;
import static android.view.autofill.Helper.sVerbose;
import static android.view.autofill.Helper.toList;
import android.accessibilityservice.AccessibilityServiceInfo;
+import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -1607,7 +1609,12 @@ public final class AutofillManager {
* the virtual view in the host view.
*
* @throws IllegalArgumentException if the {@code infos} was empty
+ *
+ * @deprecated This function will not do anything. Showing fill dialog is now fully controlled
+ * by the framework and the autofill provider.
*/
+ @FlaggedApi(FLAG_FILL_DIALOG_IMPROVEMENTS)
+ @Deprecated
public void notifyVirtualViewsReady(
@NonNull View view, @NonNull SparseArray infos) {
Objects.requireNonNull(infos);
@@ -4034,8 +4041,13 @@ public final class AutofillManager {
* receiving a focus event. The autofill suggestions shown will include content for
* related views as well.
* @return {@code true} if the autofill dialog is being shown
+ *
+ * @deprecated This function will not do anything. Showing fill dialog is now fully controlled
+ * by the framework and the autofill provider.
*/
// TODO(b/210926084): Consider whether to include the one-time show logic within this method.
+ @FlaggedApi(FLAG_FILL_DIALOG_IMPROVEMENTS)
+ @Deprecated
public boolean showAutofillDialog(@NonNull View view) {
Objects.requireNonNull(view);
if (shouldShowAutofillDialog(view, view.getAutofillId())) {
@@ -4073,7 +4085,12 @@ public final class AutofillManager {
* suggestions.
* @param virtualId id identifying the virtual view inside the host view.
* @return {@code true} if the autofill dialog is being shown
+ *
+ * @deprecated This function will not do anything. Showing fill dialog is now fully controlled
+ * by the framework and the autofill provider.
*/
+ @FlaggedApi(FLAG_FILL_DIALOG_IMPROVEMENTS)
+ @Deprecated
public boolean showAutofillDialog(@NonNull View view, int virtualId) {
Objects.requireNonNull(view);
if (shouldShowAutofillDialog(view, getAutofillId(view, virtualId))) {
diff --git a/core/java/android/view/flags/scroll_feedback_flags.aconfig b/core/java/android/view/flags/scroll_feedback_flags.aconfig
index 658aa29a3cc65bb0dceffab21103a35d354b1a08..ebda4d472b0d91b739c6d199d7aafceaf4cc2fdb 100644
--- a/core/java/android/view/flags/scroll_feedback_flags.aconfig
+++ b/core/java/android/view/flags/scroll_feedback_flags.aconfig
@@ -23,3 +23,10 @@ flag {
bug: "331830899"
is_fixed_read_only: true
}
+
+flag {
+ namespace: "wear_frameworks"
+ name: "dynamic_view_rotary_haptics_configuration"
+ description: "Whether ScrollFeedbackProvider dynamically disables View-based rotary haptics."
+ bug: "377998870"
+}
diff --git a/core/java/android/view/flags/view_flags.aconfig b/core/java/android/view/flags/view_flags.aconfig
index 1b86f96d7eb7e557922e1aab3fcf835b1b8d3851..3b6343e7c4ae88b424abe08dd550a930347fa6ee 100644
--- a/core/java/android/view/flags/view_flags.aconfig
+++ b/core/java/android/view/flags/view_flags.aconfig
@@ -132,4 +132,12 @@ flag {
description: "Use refactored round scrollbar."
bug: "333417898"
is_fixed_read_only: true
+}
+
+flag {
+ name: "buffer_stuffing_recovery"
+ namespace: "window_surfaces"
+ description: "Recover from buffer stuffing when SurfaceFlinger misses a frame"
+ bug: "294922229"
+ is_fixed_read_only: true
}
\ No newline at end of file
diff --git a/core/java/android/view/inputmethod/EditorInfo.java b/core/java/android/view/inputmethod/EditorInfo.java
index fb3e0831fdc9bcc9b346db2acf89639d1d96c2b0..afe195c48b013dfa0bc6466450f45080f8ae3200 100644
--- a/core/java/android/view/inputmethod/EditorInfo.java
+++ b/core/java/android/view/inputmethod/EditorInfo.java
@@ -24,6 +24,7 @@ import static android.view.inputmethod.EditorInfoProto.PACKAGE_NAME;
import static android.view.inputmethod.EditorInfoProto.PRIVATE_IME_OPTIONS;
import static android.view.inputmethod.EditorInfoProto.TARGET_INPUT_METHOD_USER_ID;
import static android.view.inputmethod.Flags.FLAG_EDITORINFO_HANDWRITING_ENABLED;
+import static android.view.inputmethod.Flags.FLAG_PUBLIC_AUTOFILL_ID_IN_EDITORINFO;
import android.annotation.FlaggedApi;
import android.annotation.IntDef;
@@ -470,12 +471,10 @@ public class EditorInfo implements InputType, Parcelable {
public String packageName;
/**
- * Autofill Id for the field that's currently on focus.
- *
- * Marked as hide since it's only used by framework.
- * @hide
+ * Autofill Id for the field that's currently on focus. See link {@link AutofillId} for more
+ * details. It is set by {@link View#getAutofillId()}
*/
- public AutofillId autofillId;
+ private AutofillId autofillId;
/**
* Identifier for the editor's field. This is optional, and may be
@@ -524,7 +523,6 @@ public class EditorInfo implements InputType, Parcelable {
@Nullable
public LocaleList hintLocales = null;
-
/**
* List of acceptable MIME types for
* {@link InputConnection#commitContent(InputContentInfo, int, Bundle)}.
@@ -759,6 +757,30 @@ public class EditorInfo implements InputType, Parcelable {
return mIsStylusHandwritingEnabled;
}
+ private boolean mWritingToolsEnabled = true;
+
+ /**
+ * Returns {@code true} when an {@code Editor} has writing tools enabled.
+ * {@code true} by default for all editors. Toolkits can optionally disable them where not
+ * relevant e.g. passwords, number input, etc.
+ * @see #setWritingToolsEnabled(boolean)
+ */
+ @FlaggedApi(Flags.FLAG_WRITING_TOOLS)
+ public boolean isWritingToolsEnabled() {
+ return mWritingToolsEnabled;
+ }
+
+ /**
+ * Set {@code false} if {@code Editor} opts-out of writing tools, that enable IMEs to replace
+ * text with generative AI text.
+ * @param enabled set {@code true} to enabled or {@code false to disable} support.
+ * @see #isWritingToolsEnabled()
+ */
+ @FlaggedApi(Flags.FLAG_WRITING_TOOLS)
+ public void setWritingToolsEnabled(boolean enabled) {
+ mWritingToolsEnabled = enabled;
+ }
+
/**
* If not {@code null}, this editor needs to talk to IMEs that run for the specified user, no
* matter what user ID the calling process has.
@@ -1199,6 +1221,28 @@ public class EditorInfo implements InputType, Parcelable {
mInitialToolType = toolType;
}
+ /**
+ * Returns the {@link AutofillId} of the view that this {@link EditorInfo} is associated with.
+ * The value is filled in with the result of {@link android.view.View#getAutofillId()
+ * View.getAutofillId()} on the view that is being edited.
+ *
+ * Note: For virtual view(e.g. Compose or Webview), default behavior is the autofillId is the id
+ * of the container view, unless the virtual view provider sets the virtual id when the
+ * InputMethodManager calls {@link android.view.View#onCreateInputConnection()} on the container
+ * view.
+ */
+ @FlaggedApi(FLAG_PUBLIC_AUTOFILL_ID_IN_EDITORINFO)
+ @Nullable
+ public AutofillId getAutofillId() {
+ return autofillId;
+ }
+
+ /** Sets the {@link AutofillId} of the view that this {@link EditorInfo} is associated with. */
+ @FlaggedApi(FLAG_PUBLIC_AUTOFILL_ID_IN_EDITORINFO)
+ public void setAutofillId(@Nullable AutofillId autofillId) {
+ this.autofillId = autofillId;
+ }
+
/**
* Export the state of {@link EditorInfo} into a protocol buffer output stream.
*
@@ -1255,6 +1299,7 @@ public class EditorInfo implements InputType, Parcelable {
+ InputMethodDebug.handwritingGestureTypeFlagsToString(
mSupportedHandwritingGesturePreviewTypes));
pw.println(prefix + "isStylusHandwritingEnabled=" + mIsStylusHandwritingEnabled);
+ pw.println(prefix + "writingToolsEnabled=" + mWritingToolsEnabled);
pw.println(prefix + "contentMimeTypes=" + Arrays.toString(contentMimeTypes));
if (targetInputMethodUser != null) {
pw.println(prefix + "targetInputMethodUserId=" + targetInputMethodUser.getIdentifier());
@@ -1335,6 +1380,7 @@ public class EditorInfo implements InputType, Parcelable {
}
dest.writeStringArray(contentMimeTypes);
UserHandle.writeToParcel(targetInputMethodUser, dest);
+ dest.writeBoolean(mWritingToolsEnabled);
}
/**
@@ -1375,6 +1421,7 @@ public class EditorInfo implements InputType, Parcelable {
res.hintLocales = hintLocales.isEmpty() ? null : hintLocales;
res.contentMimeTypes = source.readStringArray();
res.targetInputMethodUser = UserHandle.readFromParcel(source);
+ res.mWritingToolsEnabled = source.readBoolean();
return res;
}
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 73f9d9fc23dc90c2b7bfa872a06dcf39f1df7ccc..6303c7637a59c0acbc01d6b45530a6808af6aae2 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -2471,6 +2471,11 @@ public final class InputMethodManager {
return;
}
+ if (Flags.refactorInsetsController()) {
+ showSoftInput(rootView, statsToken, flags, resultReceiver, reason);
+ return;
+ }
+
ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
// Makes sure to call ImeInsetsSourceConsumer#onShowRequested on the UI thread.
@@ -5174,7 +5179,7 @@ public final class InputMethodManager {
// system can verify the consistency between the uid of this process and package name passed
// from here. See comment of Context#getOpPackageName() for details.
editorInfo.packageName = servedView.getContext().getOpPackageName();
- editorInfo.autofillId = servedView.getAutofillId();
+ editorInfo.setAutofillId(servedView.getAutofillId());
editorInfo.fieldId = servedView.getId();
final InputConnection ic = servedView.onCreateInputConnection(editorInfo);
if (DEBUG) Log.v(TAG, "Starting input: editorInfo=" + editorInfo + " ic=" + ic);
@@ -5183,7 +5188,7 @@ public final class InputMethodManager {
// This ensures that even disconnected EditorInfos have well-defined attributes,
// making them consistently and straightforwardly comparable.
if (ic == null) {
- editorInfo.autofillId = AutofillId.NO_AUTOFILL_ID;
+ editorInfo.setAutofillId(AutofillId.NO_AUTOFILL_ID);
editorInfo.fieldId = 0;
}
return new Pair<>(ic, editorInfo);
diff --git a/core/java/android/view/inputmethod/flags.aconfig b/core/java/android/view/inputmethod/flags.aconfig
index edd9d6cff799769a5cef5aab91b0b89e40316cec..deaf95797127b9c8ed5770e9d00ffb2e1aa41a82 100644
--- a/core/java/android/view/inputmethod/flags.aconfig
+++ b/core/java/android/view/inputmethod/flags.aconfig
@@ -165,4 +165,22 @@ flag {
description: "Writing tools API"
bug: "373788889"
is_fixed_read_only: true
-}
\ No newline at end of file
+}
+
+flag {
+ name: "public_autofill_id_in_editorinfo"
+ is_exported: true
+ namespace: "input_method"
+ description: "Guarding public API autofillId in editor info"
+ bug: "342672560"
+ is_fixed_read_only: true
+}
+
+flag {
+ name: "adaptive_handwriting_bounds"
+ is_exported: true
+ namespace: "input_method"
+ description: "Feature flag for adaptively increasing handwriting bounds."
+ bug: "350047836"
+ is_fixed_read_only: true
+}
diff --git a/core/java/android/webkit/WebChromeClient.java b/core/java/android/webkit/WebChromeClient.java
index 877fa74138feb2b3fcd87fc3164616037729ff9e..1baf3b82ca500119992bd77b6fa555ec2a24a199 100644
--- a/core/java/android/webkit/WebChromeClient.java
+++ b/core/java/android/webkit/WebChromeClient.java
@@ -20,6 +20,8 @@ import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.Nullable;
import android.annotation.SystemApi;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledAfter;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.graphics.Bitmap;
@@ -552,6 +554,23 @@ public class WebChromeClient {
* Parameters used in the {@link #onShowFileChooser} method.
*/
public static abstract class FileChooserParams {
+ /**
+ * Enable File System Access for webview.
+ *
+ * File System Access JS APIs window.showOpenFileChooser(), showDirectoryChooser(), and
+ * showSaveFilePicker() will invoke #onFileChooser(). Additional MODE_OPEN_FOLDER will be
+ * returned by #getMode(), #getIntent() will return ACTION_OPEN_DOCUMENT,
+ * ACTION_OPEN_DOCUMENT_TREE, and ACTION_CREATE_DOCUMENT rather than the current
+ * ACTION_GET_CONTENT, and new function #getPermissionMode() will be available.
+ *
+ * @hide
+ */
+ @ChangeId
+ @EnabledAfter(targetSdkVersion = android.os.Build.VERSION_CODES.VANILLA_ICE_CREAM)
+ @FlaggedApi(android.webkit.Flags.FLAG_FILE_SYSTEM_ACCESS)
+ @SystemApi
+ public static final long ENABLE_FILE_SYSTEM_ACCESS = 364980165L;
+
/** @hide */
@IntDef(prefix = { "MODE_" }, value = {
MODE_OPEN,
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index d7750bd412a3790dce7a04f3eb9009a1d4518dbe..cb70466fcd81c32e39894178876f0127f1761cc1 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -106,6 +106,7 @@ import android.os.Parcelable;
import android.os.ParcelableParcel;
import android.os.Process;
import android.os.SystemClock;
+import android.os.Trace;
import android.os.UserHandle;
import android.provider.Settings;
import android.text.BoringLayout;
@@ -9229,174 +9230,179 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
@Override
protected void onDraw(Canvas canvas) {
- restartMarqueeIfNeeded();
+ Trace.traceBegin(Trace.TRACE_TAG_VIEW, "TextView.onDraw");
+ try {
+ restartMarqueeIfNeeded();
- // Draw the background for this view
- super.onDraw(canvas);
-
- final int compoundPaddingLeft = getCompoundPaddingLeft();
- final int compoundPaddingTop = getCompoundPaddingTop();
- final int compoundPaddingRight = getCompoundPaddingRight();
- final int compoundPaddingBottom = getCompoundPaddingBottom();
- final int scrollX = mScrollX;
- final int scrollY = mScrollY;
- final int right = mRight;
- final int left = mLeft;
- final int bottom = mBottom;
- final int top = mTop;
- final boolean isLayoutRtl = isLayoutRtl();
- final int offset = getHorizontalOffsetForDrawables();
- final int leftOffset = isLayoutRtl ? 0 : offset;
- final int rightOffset = isLayoutRtl ? offset : 0;
+ // Draw the background for this view
+ super.onDraw(canvas);
- final Drawables dr = mDrawables;
- if (dr != null) {
- /*
- * Compound, not extended, because the icon is not clipped
- * if the text height is smaller.
- */
+ final int compoundPaddingLeft = getCompoundPaddingLeft();
+ final int compoundPaddingTop = getCompoundPaddingTop();
+ final int compoundPaddingRight = getCompoundPaddingRight();
+ final int compoundPaddingBottom = getCompoundPaddingBottom();
+ final int scrollX = mScrollX;
+ final int scrollY = mScrollY;
+ final int right = mRight;
+ final int left = mLeft;
+ final int bottom = mBottom;
+ final int top = mTop;
+ final boolean isLayoutRtl = isLayoutRtl();
+ final int offset = getHorizontalOffsetForDrawables();
+ final int leftOffset = isLayoutRtl ? 0 : offset;
+ final int rightOffset = isLayoutRtl ? offset : 0;
- int vspace = bottom - top - compoundPaddingBottom - compoundPaddingTop;
- int hspace = right - left - compoundPaddingRight - compoundPaddingLeft;
+ final Drawables dr = mDrawables;
+ if (dr != null) {
+ /*
+ * Compound, not extended, because the icon is not clipped
+ * if the text height is smaller.
+ */
- // IMPORTANT: The coordinates computed are also used in invalidateDrawable()
- // Make sure to update invalidateDrawable() when changing this code.
- if (dr.mShowing[Drawables.LEFT] != null) {
- canvas.save();
- canvas.translate(scrollX + mPaddingLeft + leftOffset,
- scrollY + compoundPaddingTop + (vspace - dr.mDrawableHeightLeft) / 2);
- dr.mShowing[Drawables.LEFT].draw(canvas);
- canvas.restore();
- }
+ int vspace = bottom - top - compoundPaddingBottom - compoundPaddingTop;
+ int hspace = right - left - compoundPaddingRight - compoundPaddingLeft;
+
+ // IMPORTANT: The coordinates computed are also used in invalidateDrawable()
+ // Make sure to update invalidateDrawable() when changing this code.
+ if (dr.mShowing[Drawables.LEFT] != null) {
+ canvas.save();
+ canvas.translate(scrollX + mPaddingLeft + leftOffset,
+ scrollY + compoundPaddingTop + (vspace - dr.mDrawableHeightLeft) / 2);
+ dr.mShowing[Drawables.LEFT].draw(canvas);
+ canvas.restore();
+ }
- // IMPORTANT: The coordinates computed are also used in invalidateDrawable()
- // Make sure to update invalidateDrawable() when changing this code.
- if (dr.mShowing[Drawables.RIGHT] != null) {
- canvas.save();
- canvas.translate(scrollX + right - left - mPaddingRight
- - dr.mDrawableSizeRight - rightOffset,
- scrollY + compoundPaddingTop + (vspace - dr.mDrawableHeightRight) / 2);
- dr.mShowing[Drawables.RIGHT].draw(canvas);
- canvas.restore();
- }
+ // IMPORTANT: The coordinates computed are also used in invalidateDrawable()
+ // Make sure to update invalidateDrawable() when changing this code.
+ if (dr.mShowing[Drawables.RIGHT] != null) {
+ canvas.save();
+ canvas.translate(scrollX + right - left - mPaddingRight
+ - dr.mDrawableSizeRight - rightOffset,
+ scrollY + compoundPaddingTop + (vspace - dr.mDrawableHeightRight) / 2);
+ dr.mShowing[Drawables.RIGHT].draw(canvas);
+ canvas.restore();
+ }
- // IMPORTANT: The coordinates computed are also used in invalidateDrawable()
- // Make sure to update invalidateDrawable() when changing this code.
- if (dr.mShowing[Drawables.TOP] != null) {
- canvas.save();
- canvas.translate(scrollX + compoundPaddingLeft
- + (hspace - dr.mDrawableWidthTop) / 2, scrollY + mPaddingTop);
- dr.mShowing[Drawables.TOP].draw(canvas);
- canvas.restore();
- }
+ // IMPORTANT: The coordinates computed are also used in invalidateDrawable()
+ // Make sure to update invalidateDrawable() when changing this code.
+ if (dr.mShowing[Drawables.TOP] != null) {
+ canvas.save();
+ canvas.translate(scrollX + compoundPaddingLeft
+ + (hspace - dr.mDrawableWidthTop) / 2, scrollY + mPaddingTop);
+ dr.mShowing[Drawables.TOP].draw(canvas);
+ canvas.restore();
+ }
- // IMPORTANT: The coordinates computed are also used in invalidateDrawable()
- // Make sure to update invalidateDrawable() when changing this code.
- if (dr.mShowing[Drawables.BOTTOM] != null) {
- canvas.save();
- canvas.translate(scrollX + compoundPaddingLeft
- + (hspace - dr.mDrawableWidthBottom) / 2,
- scrollY + bottom - top - mPaddingBottom - dr.mDrawableSizeBottom);
- dr.mShowing[Drawables.BOTTOM].draw(canvas);
- canvas.restore();
+ // IMPORTANT: The coordinates computed are also used in invalidateDrawable()
+ // Make sure to update invalidateDrawable() when changing this code.
+ if (dr.mShowing[Drawables.BOTTOM] != null) {
+ canvas.save();
+ canvas.translate(scrollX + compoundPaddingLeft
+ + (hspace - dr.mDrawableWidthBottom) / 2,
+ scrollY + bottom - top - mPaddingBottom - dr.mDrawableSizeBottom);
+ dr.mShowing[Drawables.BOTTOM].draw(canvas);
+ canvas.restore();
+ }
}
- }
- int color = mCurTextColor;
+ int color = mCurTextColor;
- if (mLayout == null) {
- assumeLayout();
- }
+ if (mLayout == null) {
+ assumeLayout();
+ }
+
+ Layout layout = mLayout;
- Layout layout = mLayout;
+ if (mHint != null && !mHideHint && mText.length() == 0) {
+ if (mHintTextColor != null) {
+ color = mCurHintTextColor;
+ }
- if (mHint != null && !mHideHint && mText.length() == 0) {
- if (mHintTextColor != null) {
- color = mCurHintTextColor;
+ layout = mHintLayout;
}
- layout = mHintLayout;
- }
+ mTextPaint.setColor(color);
+ mTextPaint.drawableState = getDrawableState();
- mTextPaint.setColor(color);
- mTextPaint.drawableState = getDrawableState();
+ canvas.save();
+ /* Would be faster if we didn't have to do this. Can we chop the
+ (displayable) text so that we don't need to do this ever?
+ */
- canvas.save();
- /* Would be faster if we didn't have to do this. Can we chop the
- (displayable) text so that we don't need to do this ever?
- */
+ int extendedPaddingTop = getExtendedPaddingTop();
+ int extendedPaddingBottom = getExtendedPaddingBottom();
- int extendedPaddingTop = getExtendedPaddingTop();
- int extendedPaddingBottom = getExtendedPaddingBottom();
+ final int vspace = mBottom - mTop - compoundPaddingBottom - compoundPaddingTop;
+ final int maxScrollY = mLayout.getHeight() - vspace;
- final int vspace = mBottom - mTop - compoundPaddingBottom - compoundPaddingTop;
- final int maxScrollY = mLayout.getHeight() - vspace;
+ float clipLeft = compoundPaddingLeft + scrollX;
+ float clipTop = (scrollY == 0) ? 0 : extendedPaddingTop + scrollY;
+ float clipRight = right - left - getCompoundPaddingRight() + scrollX;
+ float clipBottom = bottom - top + scrollY
+ - ((scrollY == maxScrollY) ? 0 : extendedPaddingBottom);
- float clipLeft = compoundPaddingLeft + scrollX;
- float clipTop = (scrollY == 0) ? 0 : extendedPaddingTop + scrollY;
- float clipRight = right - left - getCompoundPaddingRight() + scrollX;
- float clipBottom = bottom - top + scrollY
- - ((scrollY == maxScrollY) ? 0 : extendedPaddingBottom);
+ if (mShadowRadius != 0) {
+ clipLeft += Math.min(0, mShadowDx - mShadowRadius);
+ clipRight += Math.max(0, mShadowDx + mShadowRadius);
- if (mShadowRadius != 0) {
- clipLeft += Math.min(0, mShadowDx - mShadowRadius);
- clipRight += Math.max(0, mShadowDx + mShadowRadius);
+ clipTop += Math.min(0, mShadowDy - mShadowRadius);
+ clipBottom += Math.max(0, mShadowDy + mShadowRadius);
+ }
- clipTop += Math.min(0, mShadowDy - mShadowRadius);
- clipBottom += Math.max(0, mShadowDy + mShadowRadius);
- }
+ canvas.clipRect(clipLeft, clipTop, clipRight, clipBottom);
- canvas.clipRect(clipLeft, clipTop, clipRight, clipBottom);
+ int voffsetText = 0;
+ int voffsetCursor = 0;
- int voffsetText = 0;
- int voffsetCursor = 0;
+ // translate in by our padding
+ /* shortcircuit calling getVerticaOffset() */
+ if ((mGravity & Gravity.VERTICAL_GRAVITY_MASK) != Gravity.TOP) {
+ voffsetText = getVerticalOffset(false);
+ voffsetCursor = getVerticalOffset(true);
+ }
+ canvas.translate(compoundPaddingLeft, extendedPaddingTop + voffsetText);
+
+ final int layoutDirection = getLayoutDirection();
+ final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, layoutDirection);
+ if (isMarqueeFadeEnabled()) {
+ if (!mSingleLine && getLineCount() == 1 && canMarquee()
+ && (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) != Gravity.LEFT) {
+ final int width = mRight - mLeft;
+ final int padding = getCompoundPaddingLeft() + getCompoundPaddingRight();
+ final float dx = mLayout.getLineRight(0) - (width - padding);
+ canvas.translate(layout.getParagraphDirection(0) * dx, 0.0f);
+ }
- // translate in by our padding
- /* shortcircuit calling getVerticaOffset() */
- if ((mGravity & Gravity.VERTICAL_GRAVITY_MASK) != Gravity.TOP) {
- voffsetText = getVerticalOffset(false);
- voffsetCursor = getVerticalOffset(true);
- }
- canvas.translate(compoundPaddingLeft, extendedPaddingTop + voffsetText);
-
- final int layoutDirection = getLayoutDirection();
- final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, layoutDirection);
- if (isMarqueeFadeEnabled()) {
- if (!mSingleLine && getLineCount() == 1 && canMarquee()
- && (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) != Gravity.LEFT) {
- final int width = mRight - mLeft;
- final int padding = getCompoundPaddingLeft() + getCompoundPaddingRight();
- final float dx = mLayout.getLineRight(0) - (width - padding);
- canvas.translate(layout.getParagraphDirection(0) * dx, 0.0f);
+ if (mMarquee != null && mMarquee.isRunning()) {
+ final float dx = -mMarquee.getScroll();
+ canvas.translate(layout.getParagraphDirection(0) * dx, 0.0f);
+ }
}
- if (mMarquee != null && mMarquee.isRunning()) {
- final float dx = -mMarquee.getScroll();
- canvas.translate(layout.getParagraphDirection(0) * dx, 0.0f);
- }
- }
+ final int cursorOffsetVertical = voffsetCursor - voffsetText;
- final int cursorOffsetVertical = voffsetCursor - voffsetText;
+ maybeUpdateHighlightPaths();
+ // If there is a gesture preview highlight, then the selection or cursor is not drawn.
+ Path highlight = hasGesturePreviewHighlight() ? null : getUpdatedHighlightPath();
+ if (mEditor != null) {
+ mEditor.onDraw(canvas, layout, mHighlightPaths, mHighlightPaints, highlight,
+ mHighlightPaint, cursorOffsetVertical);
+ } else {
+ layout.draw(canvas, mHighlightPaths, mHighlightPaints, highlight, mHighlightPaint,
+ cursorOffsetVertical);
+ }
- maybeUpdateHighlightPaths();
- // If there is a gesture preview highlight, then the selection or cursor is not drawn.
- Path highlight = hasGesturePreviewHighlight() ? null : getUpdatedHighlightPath();
- if (mEditor != null) {
- mEditor.onDraw(canvas, layout, mHighlightPaths, mHighlightPaints, highlight,
- mHighlightPaint, cursorOffsetVertical);
- } else {
- layout.draw(canvas, mHighlightPaths, mHighlightPaints, highlight, mHighlightPaint,
- cursorOffsetVertical);
- }
+ if (mMarquee != null && mMarquee.shouldDrawGhost()) {
+ final float dx = mMarquee.getGhostOffset();
+ canvas.translate(layout.getParagraphDirection(0) * dx, 0.0f);
+ layout.draw(canvas, mHighlightPaths, mHighlightPaints, highlight, mHighlightPaint,
+ cursorOffsetVertical);
+ }
- if (mMarquee != null && mMarquee.shouldDrawGhost()) {
- final float dx = mMarquee.getGhostOffset();
- canvas.translate(layout.getParagraphDirection(0) * dx, 0.0f);
- layout.draw(canvas, mHighlightPaths, mHighlightPaints, highlight, mHighlightPaint,
- cursorOffsetVertical);
+ canvas.restore();
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
-
- canvas.restore();
}
@Override
@@ -11254,192 +11260,201 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- int widthMode = MeasureSpec.getMode(widthMeasureSpec);
- int heightMode = MeasureSpec.getMode(heightMeasureSpec);
- int widthSize = MeasureSpec.getSize(widthMeasureSpec);
- int heightSize = MeasureSpec.getSize(heightMeasureSpec);
-
- int width;
- int height;
+ Trace.traceBegin(Trace.TRACE_TAG_VIEW, "TextView.onMeasure");
+ try {
+ int widthMode = MeasureSpec.getMode(widthMeasureSpec);
+ int heightMode = MeasureSpec.getMode(heightMeasureSpec);
+ int widthSize = MeasureSpec.getSize(widthMeasureSpec);
+ int heightSize = MeasureSpec.getSize(heightMeasureSpec);
- BoringLayout.Metrics boring = UNKNOWN_BORING;
- BoringLayout.Metrics hintBoring = UNKNOWN_BORING;
+ int width;
+ int height;
- if (mTextDir == null) {
- mTextDir = getTextDirectionHeuristic();
- }
+ BoringLayout.Metrics boring = UNKNOWN_BORING;
+ BoringLayout.Metrics hintBoring = UNKNOWN_BORING;
- int des = -1;
- boolean fromexisting = false;
- final float widthLimit = (widthMode == MeasureSpec.AT_MOST)
- ? (float) widthSize : Float.MAX_VALUE;
-
- if (widthMode == MeasureSpec.EXACTLY) {
- // Parent has told us how big to be. So be it.
- width = widthSize;
- } else {
- if (mLayout != null && mEllipsize == null) {
- des = desired(mLayout, mUseBoundsForWidth);
+ if (mTextDir == null) {
+ mTextDir = getTextDirectionHeuristic();
}
- if (des < 0) {
- boring = BoringLayout.isBoring(mTransformed, mTextPaint, mTextDir,
- isFallbackLineSpacingForBoringLayout(), getResolvedMinimumFontMetrics(),
- mBoring);
- if (boring != null) {
- mBoring = boring;
- }
- } else {
- fromexisting = true;
- }
+ int des = -1;
+ boolean fromexisting = false;
+ final float widthLimit = (widthMode == MeasureSpec.AT_MOST)
+ ? (float) widthSize : Float.MAX_VALUE;
- if (boring == null || boring == UNKNOWN_BORING) {
- if (des < 0) {
- des = (int) Math.ceil(Layout.getDesiredWidthWithLimit(mTransformed, 0,
- mTransformed.length(), mTextPaint, mTextDir, widthLimit,
- mUseBoundsForWidth));
- }
- width = des;
+ if (widthMode == MeasureSpec.EXACTLY) {
+ // Parent has told us how big to be. So be it.
+ width = widthSize;
} else {
- if (mUseBoundsForWidth) {
- RectF bbox = boring.getDrawingBoundingBox();
- float rightMax = Math.max(bbox.right, boring.width);
- float leftMin = Math.min(bbox.left, 0);
- width = Math.max(boring.width, (int) Math.ceil(rightMax - leftMin));
- } else {
- width = boring.width;
+ if (mLayout != null && mEllipsize == null) {
+ des = desired(mLayout, mUseBoundsForWidth);
}
- }
-
- final Drawables dr = mDrawables;
- if (dr != null) {
- width = Math.max(width, dr.mDrawableWidthTop);
- width = Math.max(width, dr.mDrawableWidthBottom);
- }
-
- if (mHint != null) {
- int hintDes = -1;
- int hintWidth;
- if (mHintLayout != null && mEllipsize == null) {
- hintDes = desired(mHintLayout, mUseBoundsForWidth);
- }
-
- if (hintDes < 0) {
- hintBoring = BoringLayout.isBoring(mHint, mTextPaint, mTextDir,
+ if (des < 0) {
+ boring = BoringLayout.isBoring(mTransformed, mTextPaint, mTextDir,
isFallbackLineSpacingForBoringLayout(), getResolvedMinimumFontMetrics(),
- mHintBoring);
- if (hintBoring != null) {
- mHintBoring = hintBoring;
+ mBoring);
+ if (boring != null) {
+ mBoring = boring;
}
+ } else {
+ fromexisting = true;
}
- if (hintBoring == null || hintBoring == UNKNOWN_BORING) {
- if (hintDes < 0) {
- hintDes = (int) Math.ceil(Layout.getDesiredWidthWithLimit(mHint, 0,
- mHint.length(), mTextPaint, mTextDir, widthLimit,
+ if (boring == null || boring == UNKNOWN_BORING) {
+ if (des < 0) {
+ des = (int) Math.ceil(Layout.getDesiredWidthWithLimit(mTransformed, 0,
+ mTransformed.length(), mTextPaint, mTextDir, widthLimit,
mUseBoundsForWidth));
}
- hintWidth = hintDes;
+ width = des;
} else {
- hintWidth = hintBoring.width;
+ if (mUseBoundsForWidth) {
+ RectF bbox = boring.getDrawingBoundingBox();
+ float rightMax = Math.max(bbox.right, boring.width);
+ float leftMin = Math.min(bbox.left, 0);
+ width = Math.max(boring.width, (int) Math.ceil(rightMax - leftMin));
+ } else {
+ width = boring.width;
+ }
}
- if (hintWidth > width) {
- width = hintWidth;
+ final Drawables dr = mDrawables;
+ if (dr != null) {
+ width = Math.max(width, dr.mDrawableWidthTop);
+ width = Math.max(width, dr.mDrawableWidthBottom);
}
- }
- width += getCompoundPaddingLeft() + getCompoundPaddingRight();
+ if (mHint != null) {
+ int hintDes = -1;
+ int hintWidth;
- if (mMaxWidthMode == EMS) {
- width = Math.min(width, mMaxWidth * getLineHeight());
- } else {
- width = Math.min(width, mMaxWidth);
- }
+ if (mHintLayout != null && mEllipsize == null) {
+ hintDes = desired(mHintLayout, mUseBoundsForWidth);
+ }
- if (mMinWidthMode == EMS) {
- width = Math.max(width, mMinWidth * getLineHeight());
- } else {
- width = Math.max(width, mMinWidth);
- }
+ if (hintDes < 0) {
+ hintBoring = BoringLayout.isBoring(mHint, mTextPaint, mTextDir,
+ isFallbackLineSpacingForBoringLayout(),
+ getResolvedMinimumFontMetrics(),
+ mHintBoring);
+ if (hintBoring != null) {
+ mHintBoring = hintBoring;
+ }
+ }
- // Check against our minimum width
- width = Math.max(width, getSuggestedMinimumWidth());
+ if (hintBoring == null || hintBoring == UNKNOWN_BORING) {
+ if (hintDes < 0) {
+ hintDes = (int) Math.ceil(Layout.getDesiredWidthWithLimit(mHint, 0,
+ mHint.length(), mTextPaint, mTextDir, widthLimit,
+ mUseBoundsForWidth));
+ }
+ hintWidth = hintDes;
+ } else {
+ hintWidth = hintBoring.width;
+ }
- if (widthMode == MeasureSpec.AT_MOST) {
- width = Math.min(widthSize, width);
- }
- }
+ if (hintWidth > width) {
+ width = hintWidth;
+ }
+ }
- int want = width - getCompoundPaddingLeft() - getCompoundPaddingRight();
- int unpaddedWidth = want;
+ width += getCompoundPaddingLeft() + getCompoundPaddingRight();
- if (mHorizontallyScrolling) want = VERY_WIDE;
+ if (mMaxWidthMode == EMS) {
+ width = Math.min(width, mMaxWidth * getLineHeight());
+ } else {
+ width = Math.min(width, mMaxWidth);
+ }
- int hintWant = want;
- int hintWidth = (mHintLayout == null) ? hintWant : mHintLayout.getWidth();
+ if (mMinWidthMode == EMS) {
+ width = Math.max(width, mMinWidth * getLineHeight());
+ } else {
+ width = Math.max(width, mMinWidth);
+ }
- if (mLayout == null) {
- makeNewLayout(want, hintWant, boring, hintBoring,
- width - getCompoundPaddingLeft() - getCompoundPaddingRight(), false);
- } else {
- final boolean layoutChanged = (mLayout.getWidth() != want) || (hintWidth != hintWant)
- || (mLayout.getEllipsizedWidth()
- != width - getCompoundPaddingLeft() - getCompoundPaddingRight());
+ // Check against our minimum width
+ width = Math.max(width, getSuggestedMinimumWidth());
+
+ if (widthMode == MeasureSpec.AT_MOST) {
+ width = Math.min(widthSize, width);
+ }
+ }
- final boolean widthChanged = (mHint == null) && (mEllipsize == null)
- && (want > mLayout.getWidth())
- && (mLayout instanceof BoringLayout
- || (fromexisting && des >= 0 && des <= want));
+ int want = width - getCompoundPaddingLeft() - getCompoundPaddingRight();
+ int unpaddedWidth = want;
- final boolean maximumChanged = (mMaxMode != mOldMaxMode) || (mMaximum != mOldMaximum);
+ if (mHorizontallyScrolling) want = VERY_WIDE;
- if (layoutChanged || maximumChanged) {
- if (!maximumChanged && widthChanged) {
- mLayout.increaseWidthTo(want);
+ int hintWant = want;
+ int hintWidth = (mHintLayout == null) ? hintWant : mHintLayout.getWidth();
+
+ if (mLayout == null) {
+ makeNewLayout(want, hintWant, boring, hintBoring,
+ width - getCompoundPaddingLeft() - getCompoundPaddingRight(), false);
+ } else {
+ final boolean layoutChanged =
+ (mLayout.getWidth() != want) || (hintWidth != hintWant)
+ || (mLayout.getEllipsizedWidth()
+ != width - getCompoundPaddingLeft() - getCompoundPaddingRight());
+
+ final boolean widthChanged = (mHint == null) && (mEllipsize == null)
+ && (want > mLayout.getWidth())
+ && (mLayout instanceof BoringLayout
+ || (fromexisting && des >= 0 && des <= want));
+
+ final boolean maximumChanged =
+ (mMaxMode != mOldMaxMode) || (mMaximum != mOldMaximum);
+
+ if (layoutChanged || maximumChanged) {
+ if (!maximumChanged && widthChanged) {
+ mLayout.increaseWidthTo(want);
+ } else {
+ makeNewLayout(want, hintWant, boring, hintBoring,
+ width - getCompoundPaddingLeft() - getCompoundPaddingRight(),
+ false);
+ }
} else {
- makeNewLayout(want, hintWant, boring, hintBoring,
- width - getCompoundPaddingLeft() - getCompoundPaddingRight(), false);
+ // Nothing has changed
}
- } else {
- // Nothing has changed
}
- }
- if (heightMode == MeasureSpec.EXACTLY) {
- // Parent has told us how big to be. So be it.
- height = heightSize;
- mDesiredHeightAtMeasure = -1;
- } else {
- int desired = getDesiredHeight();
+ if (heightMode == MeasureSpec.EXACTLY) {
+ // Parent has told us how big to be. So be it.
+ height = heightSize;
+ mDesiredHeightAtMeasure = -1;
+ } else {
+ int desired = getDesiredHeight();
- height = desired;
- mDesiredHeightAtMeasure = desired;
+ height = desired;
+ mDesiredHeightAtMeasure = desired;
- if (heightMode == MeasureSpec.AT_MOST) {
- height = Math.min(desired, heightSize);
+ if (heightMode == MeasureSpec.AT_MOST) {
+ height = Math.min(desired, heightSize);
+ }
}
- }
- int unpaddedHeight = height - getCompoundPaddingTop() - getCompoundPaddingBottom();
- if (mMaxMode == LINES && mLayout.getLineCount() > mMaximum) {
- unpaddedHeight = Math.min(unpaddedHeight, mLayout.getLineTop(mMaximum));
- }
+ int unpaddedHeight = height - getCompoundPaddingTop() - getCompoundPaddingBottom();
+ if (mMaxMode == LINES && mLayout.getLineCount() > mMaximum) {
+ unpaddedHeight = Math.min(unpaddedHeight, mLayout.getLineTop(mMaximum));
+ }
- /*
- * We didn't let makeNewLayout() register to bring the cursor into view,
- * so do it here if there is any possibility that it is needed.
- */
- if (mMovement != null
- || mLayout.getWidth() > unpaddedWidth
- || mLayout.getHeight() > unpaddedHeight) {
- registerForPreDraw();
- } else {
- scrollTo(0, 0);
- }
+ /*
+ * We didn't let makeNewLayout() register to bring the cursor into view,
+ * so do it here if there is any possibility that it is needed.
+ */
+ if (mMovement != null
+ || mLayout.getWidth() > unpaddedWidth
+ || mLayout.getHeight() > unpaddedHeight) {
+ registerForPreDraw();
+ } else {
+ scrollTo(0, 0);
+ }
- setMeasuredDimension(width, height);
+ setMeasuredDimension(width, height);
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_VIEW);
+ }
}
/**
diff --git a/core/java/android/window/DesktopModeFlags.java b/core/java/android/window/DesktopModeFlags.java
index 6b5a367ab4602c8affeb98421c148ac018c1ef88..7a01ad340c561be0b4d07c84716e4e0b1f0ab731 100644
--- a/core/java/android/window/DesktopModeFlags.java
+++ b/core/java/android/window/DesktopModeFlags.java
@@ -54,6 +54,7 @@ public enum DesktopModeFlags {
Flags::enableDesktopWindowingWallpaperActivity, true),
ENABLE_DESKTOP_WINDOWING_MODALS_POLICY(Flags::enableDesktopWindowingModalsPolicy, true),
ENABLE_THEMED_APP_HEADERS(Flags::enableThemedAppHeaders, true),
+ ENABLE_HOLD_TO_DRAG_APP_HANDLE(Flags::enableHoldToDragAppHandle, true),
ENABLE_DESKTOP_WINDOWING_QUICK_SWITCH(Flags::enableDesktopWindowingQuickSwitch, true),
ENABLE_APP_HEADER_WITH_TASK_DENSITY(Flags::enableAppHeaderWithTaskDensity, true),
ENABLE_TASK_STACK_OBSERVER_IN_SHELL(Flags::enableTaskStackObserverInShell, true),
diff --git a/core/java/android/window/TransitionInfo.java b/core/java/android/window/TransitionInfo.java
index 0f2dd10d7f474cdfb788cda7c779a3fb5ca2c42a..2c21417fb79023bcf88b3a489f5bcf3739090466 100644
--- a/core/java/android/window/TransitionInfo.java
+++ b/core/java/android/window/TransitionInfo.java
@@ -49,6 +49,7 @@ import android.content.ComponentName;
import android.graphics.Point;
import android.graphics.Rect;
import android.hardware.HardwareBuffer;
+import android.os.BinderProxy;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
@@ -1089,8 +1090,13 @@ public final class TransitionInfo implements Parcelable {
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
- sb.append('{'); sb.append(mContainer);
- sb.append(" m="); sb.append(modeToString(mMode));
+ sb.append('{');
+ if (mContainer != null && !(mContainer.asBinder() instanceof BinderProxy)) {
+ // Only log the token if it is not a binder proxy and has additional container info
+ sb.append(mContainer);
+ sb.append(" ");
+ }
+ sb.append("m="); sb.append(modeToString(mMode));
sb.append(" f="); sb.append(flagsToString(mFlags));
if (mParent != null) {
sb.append(" p="); sb.append(mParent);
diff --git a/core/java/android/window/WindowContainerTransaction.java b/core/java/android/window/WindowContainerTransaction.java
index 3fe63ab17248aec955a4dc200bc875dcaa266d9c..a88a1728348274e6d235c0cf2190d8dbb145d25f 100644
--- a/core/java/android/window/WindowContainerTransaction.java
+++ b/core/java/android/window/WindowContainerTransaction.java
@@ -1120,8 +1120,8 @@ public final class WindowContainerTransaction implements Parcelable {
@NonNull
public String toString() {
return "WindowContainerTransaction {"
- + " changes = " + mChanges
- + " hops = " + mHierarchyOps
+ + " changes= " + mChanges
+ + " hops= " + mHierarchyOps
+ " errorCallbackToken=" + mErrorCallbackToken
+ " taskFragmentOrganizer=" + mTaskFragmentOrganizer
+ " }";
diff --git a/core/java/android/window/flags/lse_desktop_experience.aconfig b/core/java/android/window/flags/lse_desktop_experience.aconfig
index d39ecabbb2d25bc46eb26c599a84e3b96a5d45d3..eebdeadcdeb295d64ff962cbf7282b8df5a36c61 100644
--- a/core/java/android/window/flags/lse_desktop_experience.aconfig
+++ b/core/java/android/window/flags/lse_desktop_experience.aconfig
@@ -352,6 +352,16 @@ flag {
bug: "375992828"
}
+flag {
+ name: "enable_desktop_system_dialogs_transitions"
+ namespace: "lse_desktop_experience"
+ description: "Enables custom transitions for system dialogs in Desktop Mode."
+ bug: "335638193"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
flag {
name: "enable_move_to_next_display_shortcut"
namespace: "lse_desktop_experience"
@@ -392,4 +402,11 @@ flag {
namespace: "lse_desktop_experience"
description: "Enables HSUM on desktop mode."
bug: "366397912"
+}
+
+flag {
+ name: "enable_multiple_desktops"
+ namespace: "lse_desktop_experience"
+ description: "Enable multiple desktop sessions for desktop windowing."
+ bug: "379158791"
}
\ No newline at end of file
diff --git a/core/java/android/window/flags/window_surfaces.aconfig b/core/java/android/window/flags/window_surfaces.aconfig
index 392c307de7ba7ce5864b8c5261f4470a09ba10ba..96b9dc7cab0efec0a9ba215f1df53a7f3a804355 100644
--- a/core/java/android/window/flags/window_surfaces.aconfig
+++ b/core/java/android/window/flags/window_surfaces.aconfig
@@ -97,3 +97,12 @@ flag {
is_fixed_read_only: true
bug: "308662081"
}
+
+flag {
+ name: "jank_api"
+ namespace: "window_surfaces"
+ description: "Adds the jank data listener to AttachedSurfaceControl"
+ is_fixed_read_only: true
+ is_exported: true
+ bug: "293949943"
+}
diff --git a/core/java/android/window/flags/windowing_frontend.aconfig b/core/java/android/window/flags/windowing_frontend.aconfig
index 68e78fed29c5e1a2d0a817349da9622d6b1f8d2a..ff69610dbf0e56c16a9029b7e82ec1d7b8bcc07d 100644
--- a/core/java/android/window/flags/windowing_frontend.aconfig
+++ b/core/java/android/window/flags/windowing_frontend.aconfig
@@ -160,12 +160,21 @@ flag {
}
flag {
- name: "delegate_unhandled_drags"
- is_exported: true
- namespace: "multitasking"
- description: "Enables delegating unhandled drags to SystemUI"
- bug: "320797628"
- is_fixed_read_only: true
+ name: "delegate_unhandled_drags"
+ is_exported: true
+ namespace: "multitasking"
+ description: "Enables delegating unhandled drags to SystemUI"
+ bug: "320797628"
+ is_fixed_read_only: true
+}
+
+flag {
+ name: "supports_drag_assistant_to_multiwindow"
+ is_exported: true
+ namespace: "multitasking"
+ description: "Enables support for dragging the assistant into multiwindow"
+ bug: "371206207"
+ is_fixed_read_only: true
}
flag {
@@ -267,6 +276,16 @@ flag {
}
}
+flag {
+ name: "system_ui_post_animation_end"
+ namespace: "windowing_frontend"
+ description: "Run AnimatorListener#onAnimationEnd on next frame for SystemUI"
+ bug: "300035126"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
flag {
name: "system_ui_immersive_confirmation_dialog"
namespace: "windowing_frontend"
@@ -398,6 +417,17 @@ flag {
bug: "362938401"
}
+flag {
+ name: "record_task_snapshots_before_shutdown"
+ namespace: "windowing_frontend"
+ description: "Record task snapshots before shutdown"
+ bug: "376821232"
+ is_fixed_read_only: true
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
flag {
name: "predictive_back_three_button_nav"
namespace: "systemui"
diff --git a/core/java/com/android/internal/app/AppLocaleCollector.java b/core/java/com/android/internal/app/AppLocaleCollector.java
index 56f633fbc6c9a9d044b7e5491f75719f363fb846..ca1fc0a6d41ff0e8478c6510a55d7047da9152ca 100644
--- a/core/java/com/android/internal/app/AppLocaleCollector.java
+++ b/core/java/com/android/internal/app/AppLocaleCollector.java
@@ -41,7 +41,7 @@ import java.util.Set;
import java.util.stream.Collectors;
/** The Locale data collector for per-app language. */
-public class AppLocaleCollector implements LocalePickerWithRegion.LocaleCollectorBase {
+public class AppLocaleCollector implements LocaleCollectorBase {
private static final String TAG = AppLocaleCollector.class.getSimpleName();
private final Context mContext;
private final String mAppPackageName;
@@ -167,8 +167,8 @@ public class AppLocaleCollector implements LocalePickerWithRegion.LocaleCollecto
}
@Override
- public HashSet getIgnoredLocaleList(boolean translatedOnly) {
- HashSet langTagsToIgnore = new HashSet<>();
+ public Set getIgnoredLocaleList(boolean translatedOnly) {
+ Set langTagsToIgnore = new HashSet<>();
if (mAppCurrentLocale != null) {
langTagsToIgnore.add(mAppCurrentLocale.getLocale().toLanguageTag());
diff --git a/core/java/com/android/internal/app/LocaleCollectorBase.java b/core/java/com/android/internal/app/LocaleCollectorBase.java
new file mode 100644
index 0000000000000000000000000000000000000000..f8390777107472601d2529863a5a0c2920072834
--- /dev/null
+++ b/core/java/com/android/internal/app/LocaleCollectorBase.java
@@ -0,0 +1,36 @@
+/**
+ * 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.internal.app;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * The interface which provides the locale list.
+ */
+public interface LocaleCollectorBase {
+
+ /** Gets the ignored locale list. */
+ Set getIgnoredLocaleList(boolean translatedOnly);
+
+ /** Gets the supported locale list. */
+ Set getSupportedLocaleList(LocaleStore.LocaleInfo parent,
+ boolean translatedOnly, boolean isForCountryMode);
+
+ /** Indicates if the class work for specific package. */
+ boolean hasSpecificPackageName();
+}
diff --git a/core/java/com/android/internal/app/LocalePickerWithRegion.java b/core/java/com/android/internal/app/LocalePickerWithRegion.java
index ef4acd1cdfcb0b1269c1b84bf7b96ec9aed9d99a..ffffefa64758779ffb92f5da0c9d945031fae02e 100644
--- a/core/java/com/android/internal/app/LocalePickerWithRegion.java
+++ b/core/java/com/android/internal/app/LocalePickerWithRegion.java
@@ -44,7 +44,10 @@ import java.util.Set;
* It shows suggestions at the top, then the rest of the locales.
* Allows the user to search for locales using both their native name and their name in the
* default locale.
+ *
+ * @deprecated use SettingLib's widget instead of customized UIs.
*/
+@Deprecated
public class LocalePickerWithRegion extends ListFragment implements SearchView.OnQueryTextListener {
private static final String TAG = LocalePickerWithRegion.class.getSimpleName();
private static final String PARENT_FRAGMENT_NAME = "localeListEditor";
@@ -78,21 +81,6 @@ public class LocalePickerWithRegion extends ListFragment implements SearchView.O
default void onParentLocaleSelected(LocaleStore.LocaleInfo locale) {}
}
- /**
- * The interface which provides the locale list.
- */
- interface LocaleCollectorBase {
- /** Gets the ignored locale list. */
- HashSet getIgnoredLocaleList(boolean translatedOnly);
-
- /** Gets the supported locale list. */
- Set getSupportedLocaleList(LocaleStore.LocaleInfo parent,
- boolean translatedOnly, boolean isForCountryMode);
-
- /** Indicates if the class work for specific package. */
- boolean hasSpecificPackageName();
- }
-
private static LocalePickerWithRegion createNumberingSystemPicker(
LocaleSelectedListener listener, LocaleStore.LocaleInfo parent,
boolean translatedOnly, OnActionExpandListener onActionExpandListener,
diff --git a/core/java/com/android/internal/app/SystemLocaleCollector.java b/core/java/com/android/internal/app/SystemLocaleCollector.java
index 416f510b3230d879a5cec4b321d723cc0a1cca9d..c7931cbfcc5d712e35ea246898593983f32d1e7e 100644
--- a/core/java/com/android/internal/app/SystemLocaleCollector.java
+++ b/core/java/com/android/internal/app/SystemLocaleCollector.java
@@ -24,7 +24,7 @@ import java.util.HashSet;
import java.util.Set;
/** The Locale data collector for System language. */
-class SystemLocaleCollector implements LocalePickerWithRegion.LocaleCollectorBase {
+public class SystemLocaleCollector implements LocaleCollectorBase {
private final Context mContext;
private LocaleList mExplicitLocales;
@@ -32,14 +32,14 @@ class SystemLocaleCollector implements LocalePickerWithRegion.LocaleCollectorBas
this(context, null);
}
- SystemLocaleCollector(Context context, LocaleList explicitLocales) {
+ public SystemLocaleCollector(Context context, LocaleList explicitLocales) {
mContext = context;
mExplicitLocales = explicitLocales;
}
@Override
- public HashSet getIgnoredLocaleList(boolean translatedOnly) {
- HashSet ignoreList = new HashSet<>();
+ public Set getIgnoredLocaleList(boolean translatedOnly) {
+ Set ignoreList = new HashSet<>();
if (!translatedOnly) {
final LocaleList userLocales = LocalePicker.getLocales();
final String[] langTags = userLocales.toLanguageTags().split(",");
diff --git a/core/java/com/android/internal/app/procstats/AssociationState.java b/core/java/com/android/internal/app/procstats/AssociationState.java
index a21a84261ae01d3824f5e840ec4205d9720ef242..543adac14d364439a6c2dbae32d220f4d5bd430e 100644
--- a/core/java/com/android/internal/app/procstats/AssociationState.java
+++ b/core/java/com/android/internal/app/procstats/AssociationState.java
@@ -257,7 +257,6 @@ public final class AssociationState {
if (VALIDATE_TIMES) {
if (mActiveDuration > mAssociationState.mTotalActiveDuration) {
RuntimeException ex = new RuntimeException();
- ex.fillInStackTrace();
Slog.w(TAG, "Source act duration " + mActiveDurations
+ " exceeds total " + mAssociationState.mTotalActiveDuration
+ " in procstate " + mActiveProcState + " in source "
@@ -650,7 +649,6 @@ public final class AssociationState {
+ mySrc.mKey.mProcess + " to assoc " + mName);
if ((mySrc.mDuration + otherSrc.mDuration) > mTotalDuration) {
RuntimeException ex = new RuntimeException();
- ex.fillInStackTrace();
Slog.w(TAG, "Source tot duration " + mySrc.mDuration + "+"
+ otherSrc.mDuration
+ (newSrc ? " (new)" : " (old)") + " exceeds total "
@@ -665,7 +663,6 @@ public final class AssociationState {
+ mySrc.mKey.mProcess + " to assoc " + mName);
if ((mySrc.mActiveDuration + otherSrc.mActiveDuration) > mTotalDuration) {
RuntimeException ex = new RuntimeException();
- ex.fillInStackTrace();
Slog.w(TAG, "Source act duration " + mySrc.mActiveDuration + "+"
+ otherSrc.mActiveDuration
+ (newSrc ? " (new)" : " (old)") + " exceeds total "
@@ -746,14 +743,12 @@ public final class AssociationState {
if (VALIDATE_TIMES) {
if (src.mDuration > mTotalDuration) {
RuntimeException ex = new RuntimeException();
- ex.fillInStackTrace();
Slog.w(TAG, "Reading tot duration " + src.mDuration
+ " exceeds total " + mTotalDuration + " in source "
+ src.mKey.mProcess + " to assoc " + mName, ex);
}
if (src.mActiveDurations == null && src.mActiveDuration > mTotalDuration) {
RuntimeException ex = new RuntimeException();
- ex.fillInStackTrace();
Slog.w(TAG, "Reading act duration " + src.mActiveDuration
+ " exceeds total " + mTotalDuration + " in source "
+ src.mKey.mProcess + " to assoc " + mName, ex);
diff --git a/core/java/com/android/internal/app/procstats/ProcessState.java b/core/java/com/android/internal/app/procstats/ProcessState.java
index 0dbdb36977f441f06da6c3c248d613e087f7cdd3..7523a2d24af85382c18da5f16db007010aa3c213 100644
--- a/core/java/com/android/internal/app/procstats/ProcessState.java
+++ b/core/java/com/android/internal/app/procstats/ProcessState.java
@@ -538,7 +538,6 @@ public final class ProcessState {
public void incActiveServices(String serviceName) {
if (DEBUG && "".equals(mName)) {
RuntimeException here = new RuntimeException("here");
- here.fillInStackTrace();
Slog.d(TAG, "incActiveServices: " + this + " service=" + serviceName
+ " to " + (mNumActiveServices+1), here);
}
@@ -551,7 +550,6 @@ public final class ProcessState {
public void decActiveServices(String serviceName) {
if (DEBUG && "".equals(mName)) {
RuntimeException here = new RuntimeException("here");
- here.fillInStackTrace();
Slog.d(TAG, "decActiveServices: " + this + " service=" + serviceName
+ " to " + (mNumActiveServices-1), here);
}
@@ -569,7 +567,6 @@ public final class ProcessState {
public void incStartedServices(int memFactor, long now, String serviceName) {
if (false) {
RuntimeException here = new RuntimeException("here");
- here.fillInStackTrace();
Slog.d(TAG, "incStartedServices: " + this + " service=" + serviceName
+ " to " + (mNumStartedServices+1), here);
}
@@ -585,7 +582,6 @@ public final class ProcessState {
public void decStartedServices(int memFactor, long now, String serviceName) {
if (false) {
RuntimeException here = new RuntimeException("here");
- here.fillInStackTrace();
Slog.d(TAG, "decActiveServices: " + this + " service=" + serviceName
+ " to " + (mNumStartedServices-1), here);
}
diff --git a/core/java/com/android/internal/backup/IBackupTransport.aidl b/core/java/com/android/internal/backup/IBackupTransport.aidl
index 21c7baab4e8340d3c4c0d96e58492faff3bcd723..469ab48385da9a6e17c033946f6c199b2b01f27a 100644
--- a/core/java/com/android/internal/backup/IBackupTransport.aidl
+++ b/core/java/com/android/internal/backup/IBackupTransport.aidl
@@ -410,4 +410,15 @@ oneway interface IBackupTransport {
* however backups initiated by the framework will call this method to retrieve one.
*/
void getBackupManagerMonitor(in AndroidFuture resultFuture);
+
+ /**
+ * Ask the transport whether packages that are about to be backed up or restored should not be
+ * put into a restricted mode by the framework and started normally instead. The
+ * {@code resultFuture} should be completed with a subset of the packages passed in, indicating
+ * which packages should NOT be put into restricted mode for the given operation type.
+ *
+ * @param operationType 0 for backup, 1 for restore.
+ */
+ void getPackagesThatShouldNotUseRestrictedMode(in List packageNames, int operationType,
+ in AndroidFuture> resultFuture);
}
diff --git a/core/java/com/android/internal/jank/FrameTracker.java b/core/java/com/android/internal/jank/FrameTracker.java
index 44c0bd01d54530b7197d7697a35c7fec5d201f95..2834e68833160ebc90a9f6203d5a90a67250088e 100644
--- a/core/java/com/android/internal/jank/FrameTracker.java
+++ b/core/java/com/android/internal/jank/FrameTracker.java
@@ -139,7 +139,7 @@ public class FrameTracker implements HardwareRendererObserver.OnFrameMetricsAvai
}
static JankInfo createFromSurfaceControlCallback(SurfaceControl.JankData jankStat) {
- return new JankInfo(jankStat.frameVsyncId).update(jankStat);
+ return new JankInfo(jankStat.getVsyncId()).update(jankStat);
}
private JankInfo(long frameVsyncId) {
@@ -154,10 +154,10 @@ public class FrameTracker implements HardwareRendererObserver.OnFrameMetricsAvai
private JankInfo update(SurfaceControl.JankData jankStat) {
this.surfaceControlCallbackFired = true;
- this.jankType = jankStat.jankType;
- this.refreshRate = DisplayRefreshRate.getRefreshRate(jankStat.frameIntervalNs);
+ this.jankType = jankStat.getJankType();
+ this.refreshRate = DisplayRefreshRate.getRefreshRate(jankStat.getFrameIntervalNanos());
if (Flags.useSfFrameDuration()) {
- this.totalDurationNanos = jankStat.actualAppFrameTimeNs;
+ this.totalDurationNanos = jankStat.getActualAppFrameTimeNanos();
}
return this;
}
@@ -458,14 +458,14 @@ public class FrameTracker implements HardwareRendererObserver.OnFrameMetricsAvai
}
for (SurfaceControl.JankData jankStat : jankData) {
- if (!isInRange(jankStat.frameVsyncId)) {
+ if (!isInRange(jankStat.getVsyncId())) {
continue;
}
- JankInfo info = findJankInfo(jankStat.frameVsyncId);
+ JankInfo info = findJankInfo(jankStat.getVsyncId());
if (info != null) {
info.update(jankStat);
} else {
- mJankInfos.put((int) jankStat.frameVsyncId,
+ mJankInfos.put((int) jankStat.getVsyncId(),
JankInfo.createFromSurfaceControlCallback(jankStat));
}
}
diff --git a/core/java/com/android/internal/pm/parsing/pkg/PackageImpl.java b/core/java/com/android/internal/pm/parsing/pkg/PackageImpl.java
index 6b6b81f1f805018c2d96b4573c877f3d1cfa6953..48d0d6c777debcf4c906ca3851af91f01af7deff 100644
--- a/core/java/com/android/internal/pm/parsing/pkg/PackageImpl.java
+++ b/core/java/com/android/internal/pm/parsing/pkg/PackageImpl.java
@@ -410,6 +410,11 @@ public class PackageImpl implements ParsedPackage, AndroidPackageInternal,
private int mLocaleConfigRes;
private boolean mAllowCrossUidActivitySwitchFromBelow;
+ @Nullable
+ private int[] mAlternateLauncherIconResIds;
+ @Nullable
+ private int[] mAlternateLauncherLabelResIds;
+
private List mSplits;
@NonNull
@@ -874,6 +879,18 @@ public class PackageImpl implements ParsedPackage, AndroidPackageInternal,
return adoptPermissions;
}
+ @Nullable
+ @Override
+ public int[] getAlternateLauncherIconResIds() {
+ return mAlternateLauncherIconResIds;
+ }
+
+ @Nullable
+ @Override
+ public int[] getAlternateLauncherLabelResIds() {
+ return mAlternateLauncherLabelResIds;
+ }
+
@NonNull
@Override
public List getApexSystemServices() {
@@ -1887,6 +1904,19 @@ public class PackageImpl implements ParsedPackage, AndroidPackageInternal,
return setBoolean(Booleans.ALLOW_NATIVE_HEAP_POINTER_TAGGING, value);
}
+ @Override
+ public PackageImpl setAlternateLauncherIconResIds(@Nullable int[] alternateLauncherIconResIds) {
+ this.mAlternateLauncherIconResIds = alternateLauncherIconResIds;
+ return this;
+ }
+
+ @Override
+ public PackageImpl setAlternateLauncherLabelResIds(
+ @Nullable int[] alternateLauncherLabelResIds) {
+ this.mAlternateLauncherLabelResIds = alternateLauncherLabelResIds;
+ return this;
+ }
+
@Override
public PackageImpl setTaskReparentingAllowed(boolean value) {
return setBoolean(Booleans.ALLOW_TASK_REPARENTING, value);
@@ -3273,6 +3303,8 @@ public class PackageImpl implements ParsedPackage, AndroidPackageInternal,
dest.writeLong(this.mBooleans2);
dest.writeBoolean(this.mAllowCrossUidActivitySwitchFromBelow);
dest.writeInt(this.mIntentMatchingFlags);
+ dest.writeIntArray(this.mAlternateLauncherIconResIds);
+ dest.writeIntArray(this.mAlternateLauncherLabelResIds);
}
private void writeFeatureFlagState(@NonNull Parcel dest) {
@@ -3465,6 +3497,8 @@ public class PackageImpl implements ParsedPackage, AndroidPackageInternal,
this.mBooleans2 = in.readLong();
this.mAllowCrossUidActivitySwitchFromBelow = in.readBoolean();
this.mIntentMatchingFlags = in.readInt();
+ this.mAlternateLauncherIconResIds = in.createIntArray();
+ this.mAlternateLauncherLabelResIds = in.createIntArray();
assignDerivedFields();
assignDerivedFields2();
diff --git a/core/java/com/android/internal/pm/pkg/component/AconfigFlags.java b/core/java/com/android/internal/pm/pkg/component/AconfigFlags.java
index 70b7953ed364ff807ec968d8f2153d1af3009d2c..c953d88c94828a690a803de8d9a49884bb26a4d7 100644
--- a/core/java/com/android/internal/pm/pkg/component/AconfigFlags.java
+++ b/core/java/com/android/internal/pm/pkg/component/AconfigFlags.java
@@ -214,13 +214,30 @@ public class AconfigFlags {
* @param parser XML parser object currently parsing an element
* @return true if the element is disabled because of its feature flag
*/
+ public boolean skipCurrentElement(@Nullable ParsingPackage pkg, @NonNull XmlPullParser parser) {
+ return skipCurrentElement(pkg, parser, /* allowNoNamespace= */ false);
+ }
+
+ /**
+ * Check if the element in {@code parser} should be skipped because of the feature flag.
+ * @param pkg The package being parsed
+ * @param parser XML parser object currently parsing an element
+ * @param allowNoNamespace Whether to allow namespace null
+ * @return true if the element is disabled because of its feature flag
+ */
public boolean skipCurrentElement(
- @NonNull ParsingPackage pkg,
- @NonNull XmlResourceParser parser) {
+ @Nullable ParsingPackage pkg,
+ @NonNull XmlPullParser parser,
+ boolean allowNoNamespace
+ ) {
if (!Flags.manifestFlagging()) {
return false;
}
String featureFlag = parser.getAttributeValue(ANDROID_RES_NAMESPACE, "featureFlag");
+ // If allow no namespace, make another attempt to parse feature flag with null namespace.
+ if (featureFlag == null && allowNoNamespace) {
+ featureFlag = parser.getAttributeValue(null, "featureFlag");
+ }
if (featureFlag == null) {
return false;
}
@@ -242,7 +259,7 @@ public class AconfigFlags {
+ " behind feature flag " + featureFlag + " = " + flagValue);
shouldSkip = true;
}
- if (android.content.pm.Flags.includeFeatureFlagsInPackageCacher()) {
+ if (pkg != null && android.content.pm.Flags.includeFeatureFlagsInPackageCacher()) {
pkg.addFeatureFlag(featureFlag, flagValue);
}
return shouldSkip;
diff --git a/core/java/com/android/internal/pm/pkg/parsing/ParsingPackage.java b/core/java/com/android/internal/pm/pkg/parsing/ParsingPackage.java
index f4bceb880617d613e68cf31ef8a6269ba5d60914..67b985a614553f95f16741484dc141cbff618a7a 100644
--- a/core/java/com/android/internal/pm/pkg/parsing/ParsingPackage.java
+++ b/core/java/com/android/internal/pm/pkg/parsing/ParsingPackage.java
@@ -413,6 +413,18 @@ public interface ParsingPackage {
ParsingPackage setOnBackInvokedCallbackEnabled(boolean enableOnBackInvokedCallback);
+ /**
+ * Set the drawable resources id array of the alternate icons that are parsing from the
+ * AndroidManifest file
+ */
+ ParsingPackage setAlternateLauncherIconResIds(int[] alternateLauncherIconResIds);
+
+ /**
+ * Set the string resources id array of the alternate labels that are parsing from the
+ * AndroidManifest file
+ */
+ ParsingPackage setAlternateLauncherLabelResIds(int[] alternateLauncherLabelResIds);
+
@CallSuper
ParsedPackage hideAsParsed();
diff --git a/core/java/com/android/internal/pm/pkg/parsing/ParsingPackageUtils.java b/core/java/com/android/internal/pm/pkg/parsing/ParsingPackageUtils.java
index 5db7b419765858e56378900c4256cbd2edf69c48..8a6e6be1abbf45ce5488dc546e876a1f751411cf 100644
--- a/core/java/com/android/internal/pm/pkg/parsing/ParsingPackageUtils.java
+++ b/core/java/com/android/internal/pm/pkg/parsing/ParsingPackageUtils.java
@@ -46,6 +46,7 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.ConfigurationInfo;
import android.content.pm.FeatureGroupInfo;
import android.content.pm.FeatureInfo;
+import android.content.pm.Flags;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.Property;
@@ -154,6 +155,13 @@ public class ParsingPackageUtils {
private static final String TAG = ParsingUtils.TAG;
+ // It is the maximum length of the typedArray of {@link android.R.attr#alternateIcons}
+ // and {@link android.R.attr#alternateLabels}.
+ private static final int MAXIMUM_LAUNCHER_ALTERNATE_IDS_LENGTH = 500;
+
+ private static final String TYPE_STRING = "string";
+ private static final String TYPE_DRAWABLE = "drawable";
+
public static final boolean DEBUG_JAR = false;
public static final boolean DEBUG_BACKUP = false;
public static final float DEFAULT_PRE_O_MAX_ASPECT_RATIO = 1.86f;
@@ -2021,6 +2029,24 @@ public class ParsingPackageUtils {
pkg.setManageSpaceActivityName(manageSpaceActivityName);
}
+ if (Flags.changeLauncherBadging()) {
+ ParseResult result = drawableResIdArray(input, sa, res,
+ R.styleable.AndroidManifestApplication_alternateLauncherIcons,
+ MAXIMUM_LAUNCHER_ALTERNATE_IDS_LENGTH);
+ if (result.isError()) {
+ return input.error(result);
+ }
+ pkg.setAlternateLauncherIconResIds(result.getResult());
+
+ result = stringResIdArray(input, sa, res,
+ R.styleable.AndroidManifestApplication_alternateLauncherLabels,
+ MAXIMUM_LAUNCHER_ALTERNATE_IDS_LENGTH);
+ if (result.isError()) {
+ return input.error(result);
+ }
+ pkg.setAlternateLauncherLabelResIds(result.getResult());
+ }
+
if (pkg.isBackupAllowed()) {
// backupAgent, killAfterRestore, fullBackupContent, backupInForeground,
// and restoreAnyVersion are only relevant if backup is possible for the
@@ -3395,6 +3421,95 @@ public class ParsingPackageUtils {
return sa.getResourceId(attribute, 0);
}
+ /**
+ * Parse the drawable resource id array in the typed array {@code resourceId}
+ * if available. If {@code maxSize} is not zero, only parse and preserve at most
+ * {@code maxSize} ids.
+ */
+ private static ParseResult drawableResIdArray(ParseInput input, @NonNull TypedArray sa,
+ @NonNull Resources res, int resourceId, int maxSize) {
+ return resIdArray(input, sa, res, resourceId, TYPE_DRAWABLE, maxSize);
+ }
+
+ /**
+ * Parse the string resource id array in the typed array {@code resourceId}
+ * if available. If {@code maxSize} is not zero, only parse and preserve at most
+ * {@code maxSize} ids.
+ */
+ private static ParseResult stringResIdArray(ParseInput input, @NonNull TypedArray sa,
+ @NonNull Resources res, int resourceId, int maxSize) {
+ return resIdArray(input, sa, res, resourceId, TYPE_STRING, maxSize);
+ }
+
+ /**
+ * Parse the resource id array in the typed array {@code resourceId}
+ * if available. If {@code maxSize} is larger than zero, only parse and preserve
+ * at most {@code maxSize} ids that type is matched to the {@code expectedTypeName}.
+ * Because the TypedArray allows mixed types in an array, if {@code expectedTypeName}
+ * is null, it means don't check the type.
+ */
+ private static ParseResult resIdArray(ParseInput input, @NonNull TypedArray sa,
+ @NonNull Resources res, int resourceId, @Nullable String expectedTypeName,
+ int maxSize) {
+ if (!sa.hasValue(resourceId)) {
+ return input.success(null);
+ }
+
+ final int typeArrayResId = sa.getResourceId(resourceId, /* defValue= */ 0);
+ if (typeArrayResId == 0) {
+ return input.success(null);
+ }
+
+ // Parse the typedArray
+ try (TypedArray typedArray = res.obtainTypedArray(typeArrayResId)) {
+ final String typedArrayName = res.getResourceName(typeArrayResId);
+ final int length = typedArray.length();
+ if (maxSize > 0 && length > maxSize) {
+ return input.error(TextUtils.formatSimple(
+ "The length of the typedArray (%s) is larger than %d.",
+ typedArrayName, maxSize));
+ }
+ Set resourceIdSet = new ArraySet<>();
+ for (int i = 0; i < length; i++) {
+ final int id = typedArray.getResourceId(i, /* defValue= */ 0);
+ // Add the id when the conditions are all matched:
+ // 1. The resource Id is not 0
+ // 2. The type is the expected type
+ // 3. The id is not duplicated
+ if (id == 0) {
+ return input.error(TextUtils.formatSimple(
+ "There is an item that is not a resource id in the typedArray (%s).",
+ typedArrayName));
+ }
+
+ try {
+ if (resourceIdSet.contains(id)) {
+ return input.error(TextUtils.formatSimple(
+ "There is a duplicated resource (%s) in the typedArray (%s).",
+ res.getResourceName(id), typedArrayName));
+ }
+ final String typeName = res.getResourceTypeName(id);
+ if (expectedTypeName != null
+ && !TextUtils.equals(typeName, expectedTypeName)) {
+ return input.error(TextUtils.formatSimple(
+ "There is a resource (%s) in the typedArray (%s) that is not a"
+ + " %s type.", res.getResourceName(id), typedArrayName,
+ expectedTypeName));
+ }
+ } catch (Resources.NotFoundException e) {
+ return input.error(TextUtils.formatSimple(
+ "There is a resource in the typedArray (%s) that is not found in"
+ + " the app resources.", typedArrayName));
+ }
+ resourceIdSet.add(id);
+ }
+ if (resourceIdSet.isEmpty()) {
+ return input.success(null);
+ }
+ return input.success(resourceIdSet.stream().mapToInt(i -> i).toArray());
+ }
+ }
+
private static String string(@StyleableRes int attribute, TypedArray sa) {
return sa.getString(attribute);
}
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index bd746d5ecf048dcb33f325058c2a006bc9c9460a..270cf085b06ffdbec594ccbd5d445d5fede35d7c 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -46,9 +46,13 @@ import static com.android.internal.policy.PhoneWindow.FEATURE_OPTIONS_PANEL;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
+import android.annotation.FlaggedApi;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
import android.app.WindowConfiguration;
+import android.app.jank.AppJankStats;
+import android.app.jank.JankTracker;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Configuration;
@@ -283,6 +287,9 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
private final WearGestureInterceptionDetector mWearGestureInterceptionDetector;
+ @Nullable
+ private AppJankStatsCallback mAppJankStatsCallback;
+
DecorView(Context context, int featureId, PhoneWindow window,
WindowManager.LayoutParams params) {
super(context);
@@ -2336,6 +2343,38 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
}
}
+ public interface AppJankStatsCallback {
+ /**
+ * Called when app jank stats are being reported to the platform or when a widget needs
+ * to obtain a reference to the JankTracker instance to update states.
+ */
+ JankTracker getAppJankTracker();
+ }
+
+ public void setAppJankStatsCallback(AppJankStatsCallback
+ jankStatsReportedCallback) {
+ mAppJankStatsCallback = jankStatsReportedCallback;
+ }
+
+ @Override
+ @FlaggedApi(android.app.jank.Flags.FLAG_DETAILED_APP_JANK_METRICS_API)
+ public void reportAppJankStats(@NonNull AppJankStats appJankStats) {
+ if (mAppJankStatsCallback != null) {
+ JankTracker jankTracker = mAppJankStatsCallback.getAppJankTracker();
+ if (jankTracker != null) {
+ jankTracker.mergeAppJankStats(appJankStats);
+ }
+ }
+ }
+
+ @Override
+ public @Nullable JankTracker getJankTracker() {
+ if (mAppJankStatsCallback != null) {
+ return mAppJankStatsCallback.getAppJankTracker();
+ }
+ return null;
+ }
+
@Override
public String toString() {
return super.toString() + "[" + getTitleSuffix(mWindow.getAttributes()) + "]";
diff --git a/core/java/com/android/internal/policy/IDeviceLockedStateListener.aidl b/core/java/com/android/internal/policy/IDeviceLockedStateListener.aidl
new file mode 100644
index 0000000000000000000000000000000000000000..cc626f699d430f7c3b11e14e187ab6a26424d253
--- /dev/null
+++ b/core/java/com/android/internal/policy/IDeviceLockedStateListener.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 com.android.internal.policy;
+
+oneway interface IDeviceLockedStateListener {
+ void onDeviceLockedStateChanged(boolean isDeviceLocked);
+}
\ No newline at end of file
diff --git a/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java b/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java
index a1c987f79304ca77f19d86fcd4ff7ca141f41d32..eb682dff14de7ddfe4d5566086efe43c806530ac 100644
--- a/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java
+++ b/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java
@@ -676,15 +676,30 @@ public abstract class PerfettoProtoLogImpl extends IProtoLogClient.Stub implemen
return internMap.get(string);
}
+ protected boolean validateGroups(ILogger logger, String[] groups) {
+ for (int i = 0; i < groups.length; i++) {
+ String group = groups[i];
+ IProtoLogGroup g = mLogGroups.get(group);
+ if (g == null) {
+ logger.log("No IProtoLogGroup named " + group);
+ return false;
+ }
+ }
+ return true;
+ }
+
private int setTextLogging(boolean value, ILogger logger, String... groups) {
+ if (!validateGroups(logger, groups)) {
+ return -1;
+ }
+
for (int i = 0; i < groups.length; i++) {
String group = groups[i];
IProtoLogGroup g = mLogGroups.get(group);
if (g != null) {
g.setLogToLogcat(value);
} else {
- logger.log("No IProtoLogGroup named " + group);
- return -1;
+ throw new RuntimeException("No IProtoLogGroup named " + group);
}
}
diff --git a/core/java/com/android/internal/protolog/ProcessedPerfettoProtoLogImpl.java b/core/java/com/android/internal/protolog/ProcessedPerfettoProtoLogImpl.java
index 70d148a311f69c5adfac80d878b8c5901083477d..967a5ed1744de1b2203118b76057fd5c25b742b0 100644
--- a/core/java/com/android/internal/protolog/ProcessedPerfettoProtoLogImpl.java
+++ b/core/java/com/android/internal/protolog/ProcessedPerfettoProtoLogImpl.java
@@ -113,6 +113,10 @@ public class ProcessedPerfettoProtoLogImpl extends PerfettoProtoLogImpl {
*/
@Override
public int startLoggingToLogcat(String[] groups, @NonNull ILogger logger) {
+ if (!validateGroups(logger, groups)) {
+ return -1;
+ }
+
mViewerConfigReader.loadViewerConfig(groups, logger);
return super.startLoggingToLogcat(groups, logger);
}
@@ -125,8 +129,19 @@ public class ProcessedPerfettoProtoLogImpl extends PerfettoProtoLogImpl {
*/
@Override
public int stopLoggingToLogcat(String[] groups, @NonNull ILogger logger) {
+ if (!validateGroups(logger, groups)) {
+ return -1;
+ }
+
+ var status = super.stopLoggingToLogcat(groups, logger);
+
+ if (status != 0) {
+ throw new RuntimeException("Failed to stop logging to logcat");
+ }
+
+ // If we successfully disabled logging, unload the viewer config.
mViewerConfigReader.unloadViewerConfig(groups, logger);
- return super.stopLoggingToLogcat(groups, logger);
+ return status;
}
@Deprecated
diff --git a/core/java/com/android/internal/ravenwood/RavenwoodEnvironment.java b/core/java/com/android/internal/ravenwood/RavenwoodEnvironment.java
index 3303d875c4279d5987ee3463060ad827c5f07bb9..8df3f2abcafd506e6b843bcdf0d6ac71fc6a29c1 100644
--- a/core/java/com/android/internal/ravenwood/RavenwoodEnvironment.java
+++ b/core/java/com/android/internal/ravenwood/RavenwoodEnvironment.java
@@ -88,15 +88,19 @@ public final class RavenwoodEnvironment {
/** @hide */
public static class CompatIdsForTest {
// Enabled by default
+ /** Used for testing */
@ChangeId
public static final long TEST_COMPAT_ID_1 = 368131859L;
+ /** Used for testing */
@Disabled
@ChangeId public static final long TEST_COMPAT_ID_2 = 368131701L;
+ /** Used for testing */
@EnabledAfter(targetSdkVersion = S)
@ChangeId public static final long TEST_COMPAT_ID_3 = 368131659L;
+ /** Used for testing */
@EnabledAfter(targetSdkVersion = UPSIDE_DOWN_CAKE)
@ChangeId public static final long TEST_COMPAT_ID_4 = 368132057L;
}
diff --git a/core/java/com/android/internal/telephony/IPhoneStateListener.aidl b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
index 0e85e046e1b68691de6bc21430600aaf81a09891..bf8a56508f54e310b52a84d4a086cb0620ad2c5e 100644
--- a/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
+++ b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
@@ -20,6 +20,7 @@ import android.telephony.BarringInfo;
import android.telephony.CallState;
import android.telephony.CellIdentity;
import android.telephony.CellInfo;
+import android.telephony.CellularIdentifierDisclosure;
import android.telephony.DataConnectionRealTimeInfo;
import android.telephony.LinkCapacityEstimate;
import android.telephony.TelephonyDisplayInfo;
@@ -28,6 +29,7 @@ import android.telephony.PhysicalChannelConfig;
import android.telephony.PreciseCallState;
import android.telephony.PreciseDataConnectionState;
import android.telephony.satellite.NtnSignalStrength;
+import android.telephony.SecurityAlgorithmUpdate;
import android.telephony.ServiceState;
import android.telephony.SignalStrength;
import android.telephony.emergency.EmergencyNumber;
@@ -87,4 +89,6 @@ oneway interface IPhoneStateListener {
void onCarrierRoamingNtnEligibleStateChanged(in boolean eligible);
void onCarrierRoamingNtnAvailableServicesChanged(in int[] availableServices);
void onCarrierRoamingNtnSignalStrengthChanged(in NtnSignalStrength ntnSignalStrength);
+ void onSecurityAlgorithmsChanged(in SecurityAlgorithmUpdate update);
+ void onCellularIdentifierDisclosedChanged(in CellularIdentifierDisclosure disclosure);
}
diff --git a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
index 0f268d5de62bab58a5d00458d2c5ae8b9ab3944a..a296fbd1cfe4f00f5b6283369884d5902ca50ae6 100644
--- a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
+++ b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
@@ -23,6 +23,7 @@ import android.telephony.BarringInfo;
import android.telephony.CallQuality;
import android.telephony.CellIdentity;
import android.telephony.CellInfo;
+import android.telephony.CellularIdentifierDisclosure;
import android.telephony.LinkCapacityEstimate;
import android.telephony.TelephonyDisplayInfo;
import android.telephony.ims.ImsReasonInfo;
@@ -30,6 +31,7 @@ import android.telephony.PhoneCapability;
import android.telephony.PhysicalChannelConfig;
import android.telephony.PreciseDataConnectionState;
import android.telephony.satellite.NtnSignalStrength;
+import android.telephony.SecurityAlgorithmUpdate;
import android.telephony.ServiceState;
import android.telephony.SignalStrength;
import android.telephony.emergency.EmergencyNumber;
@@ -132,4 +134,7 @@ interface ITelephonyRegistry {
void removeSatelliteStateChangeListener(ISatelliteStateChangeListener listener, String pkg);
void notifySatelliteStateChanged(boolean isEnabled);
+ void notifySecurityAlgorithmsChanged(int phoneId, int subId, in SecurityAlgorithmUpdate update);
+ void notifyCellularIdentifierDisclosedChanged(
+ int phoneId, int subId, in CellularIdentifierDisclosure disclosure);
}
diff --git a/core/java/com/android/internal/widget/NotificationProgressBar.java b/core/java/com/android/internal/widget/NotificationProgressBar.java
index f2b36c3b99814a6950c62164925ba71778e834fc..7a21275d611e96a604a81b2a18422d8b61769f7d 100644
--- a/core/java/com/android/internal/widget/NotificationProgressBar.java
+++ b/core/java/com/android/internal/widget/NotificationProgressBar.java
@@ -59,6 +59,8 @@ import java.util.TreeSet;
public final class NotificationProgressBar extends ProgressBar {
private static final String TAG = "NotificationProgressBar";
+ private NotificationProgressDrawable mNotificationProgressDrawable;
+
private NotificationProgressModel mProgressModel;
@Nullable
@@ -94,6 +96,12 @@ public final class NotificationProgressBar extends ProgressBar {
defStyleAttr,
defStyleRes);
+ try {
+ mNotificationProgressDrawable = getNotificationProgressDrawable();
+ } catch (IllegalStateException ex) {
+ Log.e(TAG, "Can't get NotificationProgressDrawable", ex);
+ }
+
// Supports setting the tracker in xml, but ProgressStyle notifications set/override it
// via {@code setProgressTrackerIcon}.
final Drawable tracker = a.getDrawable(R.styleable.NotificationProgressBar_tracker);
@@ -131,11 +139,8 @@ public final class NotificationProgressBar extends ProgressBar {
progressMax,
mProgressModel.isStyledByProgress());
- try {
- final NotificationProgressDrawable drawable = getNotificationProgressDrawable();
- drawable.setParts(mProgressDrawableParts);
- } catch (IllegalStateException ex) {
- Log.e(TAG, "Can't set parts because can't get NotificationProgressDrawable", ex);
+ if (mNotificationProgressDrawable != null) {
+ mNotificationProgressDrawable.setParts(mProgressDrawableParts);
}
setMax(progressMax);
@@ -195,10 +200,6 @@ public final class NotificationProgressBar extends ProgressBar {
}
private void setTracker(@Nullable Drawable tracker) {
- if (isIndeterminate() && tracker != null) {
- return;
- }
-
final boolean needUpdate = mTracker != null && tracker != mTracker;
if (needUpdate) {
mTracker.setCallback(null);
@@ -222,6 +223,9 @@ public final class NotificationProgressBar extends ProgressBar {
}
mTracker = tracker;
+ if (mNotificationProgressDrawable != null) {
+ mNotificationProgressDrawable.setHasTrackerIcon(mTracker != null);
+ }
configureTrackerBounds();
@@ -274,16 +278,6 @@ public final class NotificationProgressBar extends ProgressBar {
mTrackerDrawMatrix.postTranslate(Math.round(dx), Math.round(dy));
}
- @Override
- @RemotableViewMethod
- public synchronized void setIndeterminate(boolean indeterminate) {
- super.setIndeterminate(indeterminate);
-
- if (isIndeterminate()) {
- setTracker(null);
- }
- }
-
@Override
protected boolean verifyDrawable(@NonNull Drawable who) {
return who == mTracker || super.verifyDrawable(who);
@@ -421,6 +415,8 @@ public final class NotificationProgressBar extends ProgressBar {
@Override
protected synchronized void onDraw(Canvas canvas) {
super.onDraw(canvas);
+
+ if (isIndeterminate()) return;
drawTracker(canvas);
}
diff --git a/core/java/com/android/internal/widget/NotificationProgressDrawable.java b/core/java/com/android/internal/widget/NotificationProgressDrawable.java
index fb6937c94a3e1867f263b4cd9036f6d887d627cb..e95225eede99cc69b3f3e5e6828075cd8ac0a65e 100644
--- a/core/java/com/android/internal/widget/NotificationProgressDrawable.java
+++ b/core/java/com/android/internal/widget/NotificationProgressDrawable.java
@@ -23,7 +23,6 @@ import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
-import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Rect;
@@ -62,21 +61,15 @@ public final class NotificationProgressDrawable extends Drawable {
private boolean mMutated;
private final ArrayList mParts = new ArrayList<>();
+ private boolean mHasTrackerIcon;
private final RectF mSegRectF = new RectF();
private final Rect mPointRect = new Rect();
private final RectF mPointRectF = new RectF();
- private final Paint mStrokePaint = new Paint();
- private final Paint mDashedStrokePaint = new Paint();
private final Paint mFillPaint = new Paint();
{
- mStrokePaint.setStyle(Paint.Style.STROKE);
- mStrokePaint.setStrokeCap(Paint.Cap.ROUND);
-
- mDashedStrokePaint.setStyle(Paint.Style.STROKE);
-
mFillPaint.setStyle(Paint.Style.FILL);
}
@@ -87,49 +80,15 @@ public final class NotificationProgressDrawable extends Drawable {
}
/**
- * Set the stroke width and default color for the drawable.
- * Note: changing this property will affect all instances of a drawable loaded from a
- * resource. It is recommended to invoke
- * {@link #mutate()} before changing this property.
- *
- * @param width The width in pixels of the stroke
- * @param color The color of the stroke
- * @see #mutate()
- * @see #setStroke(int, int, float, float)
- */
- public void setStroke(int width, @ColorInt int color) {
- setStroke(width, color, 0, 0);
- }
-
- /**
- * Set the stroke width and default color for the drawable. This method can also be used
- * to dash the stroke for the dashed segments.
- * Note: changing this property will affect all instances of a drawable loaded from a
- * resource. It is recommended to invoke {@link #mutate()} before changing this property.
- *
- * @param width The width in pixels of the stroke
- * @param color The color of the stroke
- * @param dashWidth The length in pixels of the dashes, set to 0 to disable dashes
- * @param dashGap The gap in pixels between dashes
- * @see #mutate()
- * @see #setStroke(int, int)
- */
- public void setStroke(int width, @ColorInt int color, float dashWidth, float dashGap) {
- mState.setStroke(width, color, dashWidth, dashGap);
- setStrokeInternal(width, dashWidth, dashGap);
- }
-
- /**
- * Set the stroke default color for the drawable.
+ * Set the segment default color for the drawable.
* Note: changing this property will affect all instances of a drawable loaded from a
* resource. It is recommended to invoke {@link #mutate()} before changing this property.
*
* @param color The color of the stroke
* @see #mutate()
- * @see #setStroke(int, int, float, float)
*/
- public void setStrokeDefaultColor(@ColorInt int color) {
- mState.setStrokeColor(color);
+ public void setSegmentDefaultColor(@ColorInt int color) {
+ mState.setSegmentColor(color);
}
/**
@@ -144,25 +103,14 @@ public final class NotificationProgressDrawable extends Drawable {
mState.setPointRectColor(color);
}
- private void setStrokeInternal(int width, float dashWidth, float dashGap) {
- mStrokePaint.setStrokeWidth(width);
-
- mDashedStrokePaint.setStrokeWidth(width);
- DashPathEffect e = null;
- if (dashWidth > 0) {
- e = new DashPathEffect(new float[] { dashWidth, dashGap }, 0);
- }
- mDashedStrokePaint.setPathEffect(e);
-
- invalidateSelf();
- }
-
/**
* Set the segments and points that constitute the drawable.
*/
public void setParts(List parts) {
mParts.clear();
mParts.addAll(parts);
+
+ invalidateSelf();
}
/**
@@ -172,6 +120,16 @@ public final class NotificationProgressDrawable extends Drawable {
setParts(Arrays.asList(parts));
}
+ /**
+ * Set whether a tracker is drawn on top of this NotificationProgressDrawable.
+ */
+ public void setHasTrackerIcon(boolean hasTrackerIcon) {
+ if (mHasTrackerIcon != hasTrackerIcon) {
+ mHasTrackerIcon = hasTrackerIcon;
+ invalidateSelf();
+ }
+ }
+
@Override
public void draw(@NonNull Canvas canvas) {
final float pointRadius =
@@ -181,6 +139,7 @@ public final class NotificationProgressDrawable extends Drawable {
float x = (float) getBounds().left;
final float centerY = (float) getBounds().centerY();
final float totalWidth = (float) getBounds().width();
+ float segPointGap = mState.mSegPointGap;
final int numParts = mParts.size();
for (int iPart = 0; iPart < numParts; iPart++) {
@@ -188,15 +147,19 @@ public final class NotificationProgressDrawable extends Drawable {
final Part prevPart = iPart == 0 ? null : mParts.get(iPart - 1);
final Part nextPart = iPart + 1 == numParts ? null : mParts.get(iPart + 1);
if (part instanceof Segment segment) {
+ // Update the segment-point gap to 2X upon seeing the first faded segment.
+ // (Assuming that all segments before are solid, and all segments after are faded.)
+ if (segment.mFaded) {
+ segPointGap = mState.mSegPointGap * 2;
+ }
final float segWidth = segment.mFraction * totalWidth;
// Advance the start position to account for a point immediately prior.
- final float startOffset = getSegStartOffset(prevPart, pointRadius,
- mState.mSegPointGap, x);
+ final float startOffset = getSegStartOffset(prevPart, pointRadius, segPointGap, x);
final float start = x + startOffset;
// Retract the end position to account for the padding and a point immediately
// after.
- final float endOffset = getSegEndOffset(nextPart, pointRadius, mState.mSegPointGap,
- mState.mSegSegGap, x + segWidth, totalWidth);
+ final float endOffset = getSegEndOffset(segment, nextPart, pointRadius, segPointGap,
+ mState.mSegSegGap, x + segWidth, totalWidth, mHasTrackerIcon);
final float end = x + segWidth - endOffset;
// Advance the current position to account for the segment's fraction of the total
@@ -206,35 +169,15 @@ public final class NotificationProgressDrawable extends Drawable {
// No space left to draw the segment
if (start > end) continue;
- if (segment.mDashed) {
- // No caps when the segment is dashed.
-
- mDashedStrokePaint.setColor(segment.mColor != Color.TRANSPARENT ? segment.mColor
- : mState.mFadedStrokeColor);
- canvas.drawLine(start, centerY, end, centerY, mDashedStrokePaint);
- } else if (end - start < mState.mStrokeWidth) {
- // Not enough segment length to draw the caps
-
- final float rad = (end - start) / 2F;
- final float capWidth = mStrokePaint.getStrokeWidth() / 2F;
-
- mFillPaint.setColor(segment.mColor != Color.TRANSPARENT ? segment.mColor
- : mState.mStrokeColor);
-
- mSegRectF.set(start, centerY - capWidth, end, centerY + capWidth);
- canvas.drawRoundRect(mSegRectF, rad, rad, mFillPaint);
- } else {
- // Leave space for the rounded line cap which extends beyond start/end.
- final float capWidth = mStrokePaint.getStrokeWidth() / 2F;
+ final float radiusY = segment.mFaded ? mState.mFadedSegmentHeight / 2F
+ : mState.mSegmentHeight / 2F;
+ final float cornerRadius = mState.mSegmentCornerRadius;
- // Transparent is not allowed (and also is the default in the data), so use that
- // as a sentinel to be replaced by default
- mStrokePaint.setColor(segment.mColor != Color.TRANSPARENT ? segment.mColor
- : mState.mStrokeColor);
+ mFillPaint.setColor(segment.mColor != Color.TRANSPARENT ? segment.mColor
+ : (segment.mFaded ? mState.mFadedSegmentColor : mState.mSegmentColor));
- canvas.drawLine(start + capWidth, centerY, end - capWidth, centerY,
- mStrokePaint);
- }
+ mSegRectF.set(start, centerY - radiusY, end, centerY + radiusY);
+ canvas.drawRoundRect(mSegRectF, cornerRadius, cornerRadius, mFillPaint);
} else if (part instanceof Point point) {
final float pointWidth = 2 * pointRadius;
float start = x - pointRadius;
@@ -275,10 +218,17 @@ public final class NotificationProgressDrawable extends Drawable {
return pointOffset + pointRadius + segPointGap;
}
- private static float getSegEndOffset(Part nextPart, float pointRadius, float segPointGap,
- float segSegGap, float endX, float totalWidth) {
+ private static float getSegEndOffset(Segment seg, Part nextPart, float pointRadius,
+ float segPointGap,
+ float segSegGap, float endX, float totalWidth, boolean hasTrackerIcon) {
if (nextPart == null) return 0F;
- if (!(nextPart instanceof Point)) return segSegGap;
+ if (nextPart instanceof Segment nextSeg) {
+ if (!seg.mFaded && nextSeg.mFaded) {
+ // @see Segment#mFaded
+ return hasTrackerIcon ? 0F : segSegGap * 4F;
+ }
+ return segSegGap;
+ }
final float pointWidth = 2 * pointRadius;
final float pointOffset = (endX + pointRadius > totalWidth && totalWidth > pointWidth)
@@ -439,21 +389,17 @@ public final class NotificationProgressDrawable extends Drawable {
// Extract the theme attributes, if any.
state.mThemeAttrsSegments = a.extractThemeAttrs();
- final int width = a.getDimensionPixelSize(
- R.styleable.NotificationProgressDrawableSegments_width, state.mStrokeWidth);
- final float dashWidth = a.getDimension(
- R.styleable.NotificationProgressDrawableSegments_dashWidth, state.mStrokeDashWidth);
-
+ state.mSegmentHeight = a.getDimension(
+ R.styleable.NotificationProgressDrawableSegments_height, state.mSegmentHeight);
+ state.mFadedSegmentHeight = a.getDimension(
+ R.styleable.NotificationProgressDrawableSegments_fadedHeight,
+ state.mFadedSegmentHeight);
+ state.mSegmentCornerRadius = a.getDimension(
+ R.styleable.NotificationProgressDrawableSegments_cornerRadius,
+ state.mSegmentCornerRadius);
final int color = a.getColor(R.styleable.NotificationProgressDrawableSegments_color,
- state.mStrokeColor);
-
- if (dashWidth != 0.0f) {
- final float dashGap = a.getDimension(
- R.styleable.NotificationProgressDrawableSegments_dashGap, state.mStrokeDashGap);
- setStroke(width, color, dashWidth, dashGap);
- } else {
- setStroke(width, color);
- }
+ state.mSegmentColor);
+ setSegmentDefaultColor(color);
}
private void updatePointsFromTypedArray(TypedArray a) {
@@ -532,11 +478,24 @@ public final class NotificationProgressDrawable extends Drawable {
/**
* A segment is a part of the progress bar with non-zero length. For example, it can
* represent a portion in a navigation journey with certain traffic condition.
+ *
*/
public static final class Segment implements Part {
private final float mFraction;
@ColorInt private final int mColor;
- private final boolean mDashed;
+ /** Whether the segment is faded or not.
+ *
+ *
+ * When mFaded is set to true, a combination of the following is done to the segment:
+ * 1. The drawing color is mColor with opacity updated to 15%.
+ * 2. The segment-point gap is 2X the segment-point gap for non-faded segments.
+ * 3. The gap between faded and non-faded segments is:
+ * 4X the segment-segment gap, when there is no tracker icon
+ * 0, when there is tracker icon
+ *
+ *
+ */
+ private final boolean mFaded;
public Segment(float fraction) {
this(fraction, Color.TRANSPARENT);
@@ -546,10 +505,10 @@ public final class NotificationProgressDrawable extends Drawable {
this(fraction, color, false);
}
- public Segment(float fraction, @ColorInt int color, boolean dashed) {
+ public Segment(float fraction, @ColorInt int color, boolean faded) {
mFraction = fraction;
mColor = color;
- mDashed = dashed;
+ mFaded = faded;
}
public float getFraction() {
@@ -560,14 +519,14 @@ public final class NotificationProgressDrawable extends Drawable {
return this.mColor;
}
- public boolean getDashed() {
- return this.mDashed;
+ public boolean getFaded() {
+ return this.mFaded;
}
@Override
public String toString() {
- return "Segment(fraction=" + this.mFraction + ", color=" + this.mColor + ", dashed="
- + this.mDashed + ')';
+ return "Segment(fraction=" + this.mFraction + ", color=" + this.mColor + ", faded="
+ + this.mFaded + ')';
}
// Needed for unit tests
@@ -580,12 +539,12 @@ public final class NotificationProgressDrawable extends Drawable {
Segment that = (Segment) other;
if (Float.compare(this.mFraction, that.mFraction) != 0) return false;
if (this.mColor != that.mColor) return false;
- return this.mDashed == that.mDashed;
+ return this.mFaded == that.mFaded;
}
@Override
public int hashCode() {
- return Objects.hash(mFraction, mColor, mDashed);
+ return Objects.hash(mFraction, mColor, mFaded);
}
}
@@ -675,11 +634,11 @@ public final class NotificationProgressDrawable extends Drawable {
int mChangingConfigurations;
float mSegSegGap = 0.0f;
float mSegPointGap = 0.0f;
- int mStrokeWidth = 0;
- int mStrokeColor;
- int mFadedStrokeColor;
- float mStrokeDashWidth = 0.0f;
- float mStrokeDashGap = 0.0f;
+ float mSegmentHeight;
+ float mFadedSegmentHeight;
+ float mSegmentCornerRadius;
+ int mSegmentColor;
+ int mFadedSegmentColor;
float mPointRadius;
float mPointRectInset;
float mPointRectCornerRadius;
@@ -699,11 +658,11 @@ public final class NotificationProgressDrawable extends Drawable {
mChangingConfigurations = orig.mChangingConfigurations;
mSegSegGap = orig.mSegSegGap;
mSegPointGap = orig.mSegPointGap;
- mStrokeWidth = orig.mStrokeWidth;
- mStrokeColor = orig.mStrokeColor;
- mFadedStrokeColor = orig.mFadedStrokeColor;
- mStrokeDashWidth = orig.mStrokeDashWidth;
- mStrokeDashGap = orig.mStrokeDashGap;
+ mSegmentHeight = orig.mSegmentHeight;
+ mFadedSegmentHeight = orig.mFadedSegmentHeight;
+ mSegmentCornerRadius = orig.mSegmentCornerRadius;
+ mSegmentColor = orig.mSegmentColor;
+ mFadedSegmentColor = orig.mFadedSegmentColor;
mPointRadius = orig.mPointRadius;
mPointRectInset = orig.mPointRectInset;
mPointRectCornerRadius = orig.mPointRectCornerRadius;
@@ -721,17 +680,17 @@ public final class NotificationProgressDrawable extends Drawable {
}
private void applyDensityScaling(int sourceDensity, int targetDensity) {
- if (mStrokeWidth > 0) {
- mStrokeWidth = scaleFromDensity(
- mStrokeWidth, sourceDensity, targetDensity, true);
+ if (mSegmentHeight > 0) {
+ mSegmentHeight = scaleFromDensity(
+ mSegmentHeight, sourceDensity, targetDensity);
}
- if (mStrokeDashWidth > 0) {
- mStrokeDashWidth = scaleFromDensity(
- mStrokeDashWidth, sourceDensity, targetDensity);
+ if (mFadedSegmentHeight > 0) {
+ mFadedSegmentHeight = scaleFromDensity(
+ mFadedSegmentHeight, sourceDensity, targetDensity);
}
- if (mStrokeDashGap > 0) {
- mStrokeDashGap = scaleFromDensity(
- mStrokeDashGap, sourceDensity, targetDensity);
+ if (mSegmentCornerRadius > 0) {
+ mSegmentCornerRadius = scaleFromDensity(
+ mSegmentCornerRadius, sourceDensity, targetDensity);
}
if (mPointRadius > 0) {
mPointRadius = scaleFromDensity(
@@ -788,17 +747,9 @@ public final class NotificationProgressDrawable extends Drawable {
}
}
- public void setStroke(int width, int color, float dashWidth, float dashGap) {
- mStrokeWidth = width;
- mStrokeDashWidth = dashWidth;
- mStrokeDashGap = dashGap;
-
- setStrokeColor(color);
- }
-
- public void setStrokeColor(int color) {
- mStrokeColor = color;
- mFadedStrokeColor = getFadedColor(color);
+ public void setSegmentColor(int color) {
+ mSegmentColor = color;
+ mFadedSegmentColor = getFadedColor(color);
}
public void setPointRectColor(int color) {
@@ -808,11 +759,14 @@ public final class NotificationProgressDrawable extends Drawable {
}
/**
- * Get a color with an opacity that's 50% of the input color.
+ * Get a color with an opacity that's 25% of the input color.
*/
@ColorInt
static int getFadedColor(@ColorInt int color) {
- return Color.argb(Color.alpha(color) / 2, Color.red(color), Color.green(color),
+ return Color.argb(
+ (int) (Color.alpha(color) * 0.25f + 0.5f),
+ Color.red(color),
+ Color.green(color),
Color.blue(color));
}
@@ -836,15 +790,6 @@ public final class NotificationProgressDrawable extends Drawable {
}
private void updateLocalState() {
- final State state = mState;
-
- mStrokePaint.setStrokeWidth(state.mStrokeWidth);
- mDashedStrokePaint.setStrokeWidth(state.mStrokeWidth);
-
- if (state.mStrokeDashWidth != 0.0f) {
- final DashPathEffect e = new DashPathEffect(
- new float[] { state.mStrokeDashWidth, state.mStrokeDashGap }, 0);
- mDashedStrokePaint.setPathEffect(e);
- }
+ // NO-OP
}
}
diff --git a/core/java/com/android/internal/widget/NotificationRowIconView.java b/core/java/com/android/internal/widget/NotificationRowIconView.java
index 5fc61b00e331401256000dceb3f1177c1b70affe..c96e979138dd6f634c99a7a841ae5e24f7a75dfe 100644
--- a/core/java/com/android/internal/widget/NotificationRowIconView.java
+++ b/core/java/com/android/internal/widget/NotificationRowIconView.java
@@ -19,12 +19,7 @@ package com.android.internal.widget;
import android.annotation.Nullable;
import android.app.Flags;
import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.BitmapShader;
-import android.graphics.Canvas;
-import android.graphics.Paint;
import android.graphics.Rect;
-import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
import android.util.AttributeSet;
@@ -41,7 +36,6 @@ import android.widget.RemoteViews;
public class NotificationRowIconView extends CachingIconView {
private NotificationIconProvider mIconProvider;
- private boolean mApplyCircularCrop = false;
private Drawable mAppIcon = null;
// Padding, background and colors set on the view prior to being overridden when showing the app
@@ -221,84 +215,6 @@ public class NotificationRowIconView extends CachingIconView {
}
}
- @Nullable
- @Override
- Drawable loadSizeRestrictedIcon(@Nullable Icon icon) {
- final Drawable original = super.loadSizeRestrictedIcon(icon);
- final Drawable result;
- if (mApplyCircularCrop) {
- result = makeCircularDrawable(original);
- } else {
- result = original;
- }
-
- return result;
- }
-
- /**
- * Enables circle crop that makes given image circular
- */
- @RemotableViewMethod(asyncImpl = "setApplyCircularCropAsync")
- public void setApplyCircularCrop(boolean applyCircularCrop) {
- mApplyCircularCrop = applyCircularCrop;
- }
-
- /**
- * Async version of {@link NotificationRowIconView#setApplyCircularCrop}
- */
- public Runnable setApplyCircularCropAsync(boolean applyCircularCrop) {
- mApplyCircularCrop = applyCircularCrop;
- return () -> {
- };
- }
-
- @Nullable
- private Drawable makeCircularDrawable(@Nullable Drawable original) {
- if (original == null) {
- return original;
- }
-
- final Bitmap source = drawableToBitmap(original);
-
- int size = Math.min(source.getWidth(), source.getHeight());
-
- Bitmap squared = Bitmap.createScaledBitmap(source, size, size, /* filter= */ false);
- Bitmap result = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
-
- final Canvas canvas = new Canvas(result);
- final Paint paint = new Paint();
- paint.setShader(
- new BitmapShader(squared, BitmapShader.TileMode.CLAMP,
- BitmapShader.TileMode.CLAMP));
- paint.setAntiAlias(true);
- float radius = size / 2f;
- canvas.drawCircle(radius, radius, radius, paint);
- return new BitmapDrawable(getResources(), result);
- }
-
- private static Bitmap drawableToBitmap(Drawable drawable) {
- if (drawable instanceof BitmapDrawable bitmapDrawable) {
- final Bitmap bitmap = bitmapDrawable.getBitmap();
- if (bitmap.getConfig() == Bitmap.Config.HARDWARE) {
- return bitmap.copy(Bitmap.Config.ARGB_8888, false);
- } else {
- return bitmap;
- }
- }
-
- int width = drawable.getIntrinsicWidth();
- width = width > 0 ? width : 1;
- int height = drawable.getIntrinsicHeight();
- height = height > 0 ? height : 1;
-
- Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
- Canvas canvas = new Canvas(bitmap);
- drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
- drawable.draw(canvas);
-
- return bitmap;
- }
-
/**
* A provider that allows this view to verify whether it should use the app icon instead of the
* icon provided to it via setImageIcon, as well as actually fetching the app icon. It should
diff --git a/core/java/com/android/server/pm/pkg/AndroidPackage.java b/core/java/com/android/server/pm/pkg/AndroidPackage.java
index 53500596f938a4df6de50f31dddb63ad8ebde6dc..d05f5e3950b41bc3b67e68f3872e55b1d7306754 100644
--- a/core/java/com/android/server/pm/pkg/AndroidPackage.java
+++ b/core/java/com/android/server/pm/pkg/AndroidPackage.java
@@ -90,6 +90,28 @@ import java.util.UUID;
@Immutable
public interface AndroidPackage {
+ /**
+ * An array containing the drawable resources that used for the launcher
+ * activity icons.
+ *
+ * @see R.attr#alternateLauncherIcons
+ * @hide
+ */
+ @Immutable.Ignore
+ @Nullable
+ int[] getAlternateLauncherIconResIds();
+
+ /**
+ * An array containing the string resources that used for the launcher
+ * activity labels.
+ *
+ * @see R.attr#alternateLauncherLabels
+ * @hide
+ */
+ @Immutable.Ignore
+ @Nullable
+ int[] getAlternateLauncherLabelResIds();
+
/**
* @see ApplicationInfo#className
* @see R.styleable#AndroidManifestApplication_name
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index 25412581303c848a831c1ae2e2ebd2e10662b0ed..a21bf9abdd7b19630beea732e7b3e5a43bbfef67 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -77,6 +77,7 @@ cc_library_shared_for_libandroid_runtime {
"android_os_SystemClock.cpp",
"android_os_SystemProperties.cpp",
"android_text_AndroidCharacter.cpp",
+ "android_text_Hyphenator.cpp",
"android_util_AssetManager.cpp",
"android_util_EventLog.cpp",
"android_util_Log.cpp",
@@ -166,7 +167,6 @@ cc_library_shared_for_libandroid_runtime {
"android_view_SurfaceSession.cpp",
"android_view_TextureView.cpp",
"android_view_TunnelModeEnabledListener.cpp",
- "android_text_Hyphenator.cpp",
"android_os_Debug.cpp",
"android_os_GraphicsEnvironment.cpp",
"android_os_HidlMemory.cpp",
diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp
index 50252c11ffb1512ac44553ab3486bcf91c707a3e..42406147b2f0c6d6e8459447146da785167dbf16 100644
--- a/core/jni/android_hardware_Camera.cpp
+++ b/core/jni/android_hardware_Camera.cpp
@@ -538,7 +538,7 @@ static bool attributionSourceStateForJavaParcel(JNIEnv *env, jobject jClientAttr
return false;
}
- if (!(useContextAttributionSource && flags::use_context_attribution_source())) {
+ if (!(useContextAttributionSource && flags::data_delivery_permission_checks())) {
clientAttribution.uid = Camera::USE_CALLING_UID;
clientAttribution.pid = Camera::USE_CALLING_PID;
}
diff --git a/core/jni/android_hardware_OverlayProperties.cpp b/core/jni/android_hardware_OverlayProperties.cpp
index bb4084e8f39e6bbff1e7d0ee6b5fe5e80b9a3521..f64dec8eb21518bc03b6e5f965aaec138db431c6 100644
--- a/core/jni/android_hardware_OverlayProperties.cpp
+++ b/core/jni/android_hardware_OverlayProperties.cpp
@@ -106,7 +106,7 @@ static jobjectArray android_hardware_OverlayProperties_getLutProperties(JNIEnv*
jlong nativeObject) {
gui::OverlayProperties* overlayProperties =
reinterpret_cast(nativeObject);
- if (overlayProperties->lutProperties.has_value()) {
+ if (!overlayProperties || !overlayProperties->lutProperties) {
return NULL;
}
auto& lutProperties = overlayProperties->lutProperties.value();
diff --git a/core/jni/android_media_AudioRecord.cpp b/core/jni/android_media_AudioRecord.cpp
index f9d00edce3fa7fb089a9ce1c1658098e6f841331..5a183925e38e6fbb55f9eafea6ba86864278ba64 100644
--- a/core/jni/android_media_AudioRecord.cpp
+++ b/core/jni/android_media_AudioRecord.cpp
@@ -584,14 +584,23 @@ static jboolean android_media_AudioRecord_setInputDevice(
return lpRecorder->setInputDevice(device_id) == NO_ERROR;
}
-static jint android_media_AudioRecord_getRoutedDeviceId(
- JNIEnv *env, jobject thiz) {
-
+static jintArray android_media_AudioRecord_getRoutedDeviceIds(JNIEnv *env, jobject thiz) {
sp lpRecorder = getAudioRecord(env, thiz);
- if (lpRecorder == 0) {
- return 0;
+ if (lpRecorder == NULL) {
+ return NULL;
+ }
+ DeviceIdVector deviceIds = lpRecorder->getRoutedDeviceIds();
+ jintArray result;
+ result = env->NewIntArray(deviceIds.size());
+ if (result == NULL) {
+ return NULL;
+ }
+ jint *values = env->GetIntArrayElements(result, 0);
+ for (unsigned int i = 0; i < deviceIds.size(); i++) {
+ values[i++] = static_cast(deviceIds[i]);
}
- return (jint)lpRecorder->getRoutedDeviceId();
+ env->ReleaseIntArrayElements(result, values, 0);
+ return result;
}
// Enable and Disable Callback methods are synchronized on the Java side
@@ -821,8 +830,7 @@ static const JNINativeMethod gMethods[] = {
// name, signature, funcPtr
{"native_start", "(II)I", (void *)android_media_AudioRecord_start},
{"native_stop", "()V", (void *)android_media_AudioRecord_stop},
- {"native_setup",
- "(Ljava/lang/Object;Ljava/lang/Object;[IIIII[ILandroid/os/Parcel;JII)I",
+ {"native_setup", "(Ljava/lang/Object;Ljava/lang/Object;[IIIII[ILandroid/os/Parcel;JII)I",
(void *)android_media_AudioRecord_setup},
{"native_finalize", "()V", (void *)android_media_AudioRecord_finalize},
{"native_release", "()V", (void *)android_media_AudioRecord_release},
@@ -846,7 +854,7 @@ static const JNINativeMethod gMethods[] = {
{"native_getMetrics", "()Landroid/os/PersistableBundle;",
(void *)android_media_AudioRecord_native_getMetrics},
{"native_setInputDevice", "(I)Z", (void *)android_media_AudioRecord_setInputDevice},
- {"native_getRoutedDeviceId", "()I", (void *)android_media_AudioRecord_getRoutedDeviceId},
+ {"native_getRoutedDeviceIds", "()[I", (void *)android_media_AudioRecord_getRoutedDeviceIds},
{"native_enableDeviceCallback", "()V",
(void *)android_media_AudioRecord_enableDeviceCallback},
{"native_disableDeviceCallback", "()V",
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index 8eaa7aa99a2da9553a989f6c1dfb64989e4a1f2a..3d9a19e129a8b85ba3084c5ec2d3fbc73751fc73 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -109,6 +109,7 @@ static struct {
// Valid only if an AudioDevicePort
jfieldID mType;
jfieldID mAddress;
+ jfieldID mSpeakerLayoutChannelMask;
// other fields unused by JNI
} gAudioPortFields;
@@ -1084,6 +1085,8 @@ static jint convertAudioPortConfigToNativeWithDevicePort(JNIEnv *env,
strncpy(nAudioPortConfig->ext.device.address,
nDeviceAddress, AUDIO_DEVICE_MAX_ADDRESS_LEN - 1);
env->ReleaseStringUTFChars(jDeviceAddress, nDeviceAddress);
+ nAudioPortConfig->ext.device.speaker_layout_channel_mask = outChannelMaskToNative(
+ env->GetIntField(jAudioDevicePort, gAudioPortFields.mSpeakerLayoutChannelMask));
env->DeleteLocalRef(jDeviceAddress);
env->DeleteLocalRef(jAudioDevicePort);
return jStatus;
@@ -1541,10 +1544,12 @@ static jint convertAudioPortFromNative(JNIEnv *env, ScopedLocalRef *jAu
.encapsulation_metadata_types));
ALOGV("convertAudioPortFromNative is a device %08x", nAudioPort->ext.device.type);
ScopedLocalRef jAddress(env, env->NewStringUTF(nAudioPort->ext.device.address));
+ int speakerLayoutChannelMask = outChannelMaskFromNative(
+ nAudioPort->active_config.ext.device.speaker_layout_channel_mask);
jAudioPort->reset(env->NewObject(gAudioDevicePortClass, gAudioDevicePortCstor,
jHandle.get(), jDeviceName.get(), jAudioProfiles.get(),
jGains.get(), nAudioPort->ext.device.type, jAddress.get(),
- jEncapsulationModes.get(),
+ speakerLayoutChannelMask, jEncapsulationModes.get(),
jEncapsulationMetadataTypes.get(),
jAudioDescriptors.get()));
} else if (nAudioPort->type == AUDIO_PORT_TYPE_MIX) {
@@ -3705,14 +3710,15 @@ int register_android_media_AudioSystem(JNIEnv *env)
gAudioDevicePortCstor =
GetMethodIDOrDie(env, audioDevicePortClass, "",
"(Landroid/media/AudioHandle;Ljava/lang/String;Ljava/util/List;"
- "[Landroid/media/AudioGain;ILjava/lang/String;[I[I"
+ "[Landroid/media/AudioGain;ILjava/lang/String;I[I[I"
"Ljava/util/List;)V");
// When access AudioPort as AudioDevicePort
gAudioPortFields.mType = GetFieldIDOrDie(env, audioDevicePortClass, "mType", "I");
gAudioPortFields.mAddress = GetFieldIDOrDie(env, audioDevicePortClass, "mAddress",
"Ljava/lang/String;");
-
+ gAudioPortFields.mSpeakerLayoutChannelMask =
+ GetFieldIDOrDie(env, audioDevicePortClass, "mSpeakerLayoutChannelMask", "I");
jclass audioMixPortClass = FindClassOrDie(env, "android/media/AudioMixPort");
gAudioMixPortClass = MakeGlobalRefOrDie(env, audioMixPortClass);
gAudioMixPortCstor =
diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp
index 1557f9ed47a5cc1a3339b6736a13c76402bb7d4d..5d4d1ce20e5d9a8f5198d31666feae846573ed5f 100644
--- a/core/jni/android_media_AudioTrack.cpp
+++ b/core/jni/android_media_AudioTrack.cpp
@@ -1190,15 +1190,23 @@ static jboolean android_media_AudioTrack_setOutputDevice(
}
return lpTrack->setOutputDevice(device_id) == NO_ERROR;
}
-
-static jint android_media_AudioTrack_getRoutedDeviceId(
- JNIEnv *env, jobject thiz) {
-
+static jintArray android_media_AudioTrack_getRoutedDeviceIds(JNIEnv *env, jobject thiz) {
sp lpTrack = getAudioTrack(env, thiz);
if (lpTrack == NULL) {
- return 0;
+ return NULL;
+ }
+ DeviceIdVector deviceIds = lpTrack->getRoutedDeviceIds();
+ jintArray result;
+ result = env->NewIntArray(deviceIds.size());
+ if (result == NULL) {
+ return NULL;
+ }
+ jint *values = env->GetIntArrayElements(result, 0);
+ for (unsigned int i = 0; i < deviceIds.size(); i++) {
+ values[i++] = static_cast(deviceIds[i]);
}
- return (jint)lpTrack->getRoutedDeviceId();
+ env->ReleaseIntArrayElements(result, values, 0);
+ return result;
}
static void android_media_AudioTrack_enableDeviceCallback(
@@ -1503,7 +1511,7 @@ static const JNINativeMethod gMethods[] = {
(void *)android_media_AudioTrack_setAuxEffectSendLevel},
{"native_attachAuxEffect", "(I)I", (void *)android_media_AudioTrack_attachAuxEffect},
{"native_setOutputDevice", "(I)Z", (void *)android_media_AudioTrack_setOutputDevice},
- {"native_getRoutedDeviceId", "()I", (void *)android_media_AudioTrack_getRoutedDeviceId},
+ {"native_getRoutedDeviceIds", "()[I", (void *)android_media_AudioTrack_getRoutedDeviceIds},
{"native_enableDeviceCallback", "()V",
(void *)android_media_AudioTrack_enableDeviceCallback},
{"native_disableDeviceCallback", "()V",
diff --git a/core/jni/android_media_DeviceCallback.cpp b/core/jni/android_media_DeviceCallback.cpp
index a1a035110cafef64b750e26e5699f776361eb6b9..ccdf633c842a5dfd50663e7524154bfb17d5e679 100644
--- a/core/jni/android_media_DeviceCallback.cpp
+++ b/core/jni/android_media_DeviceCallback.cpp
@@ -61,21 +61,20 @@ JNIDeviceCallback::~JNIDeviceCallback()
}
void JNIDeviceCallback::onAudioDeviceUpdate(audio_io_handle_t audioIo,
- audio_port_handle_t deviceId)
-{
+ const DeviceIdVector& deviceIds) {
JNIEnv *env = AndroidRuntime::getJNIEnv();
if (env == NULL) {
return;
}
- ALOGV("%s audioIo %d deviceId %d", __FUNCTION__, audioIo, deviceId);
- env->CallStaticVoidMethod(mClass,
- mPostEventFromNative,
- mObject,
- AUDIO_NATIVE_EVENT_ROUTING_CHANGE, deviceId, 0, NULL);
+ ALOGV("%s audioIo %d deviceIds %s", __FUNCTION__, audioIo, toString(deviceIds).c_str());
+ // Java should query the new device ids once it gets the event.
+ // TODO(b/378505346): Pass the deviceIds to Java to avoid race conditions.
+ env->CallStaticVoidMethod(mClass, mPostEventFromNative, mObject,
+ AUDIO_NATIVE_EVENT_ROUTING_CHANGE, 0 /*arg1*/, 0 /*arg2*/,
+ NULL /*obj*/);
if (env->ExceptionCheck()) {
ALOGW("An exception occurred while notifying an event.");
env->ExceptionClear();
}
}
-
diff --git a/core/jni/android_media_DeviceCallback.h b/core/jni/android_media_DeviceCallback.h
index 7ae788eaf0582d953c415c1245ca8b8cdc4b7769..0c9ccc89ba1a6c6821eca4fdb79469f89ac7a5f0 100644
--- a/core/jni/android_media_DeviceCallback.h
+++ b/core/jni/android_media_DeviceCallback.h
@@ -31,8 +31,7 @@ public:
JNIDeviceCallback(JNIEnv* env, jobject thiz, jobject weak_thiz, jmethodID postEventFromNative);
~JNIDeviceCallback();
- virtual void onAudioDeviceUpdate(audio_io_handle_t audioIo,
- audio_port_handle_t deviceId);
+ virtual void onAudioDeviceUpdate(audio_io_handle_t audioIo, const DeviceIdVector& deviceIds);
private:
void sendEvent(int event);
diff --git a/core/jni/android_text_Hyphenator.cpp b/core/jni/android_text_Hyphenator.cpp
index 933781c3e924f9021313427ecbd634b4c6017ebb..e45cbaf07876621220dea0be9b447c871e5cc28b 100644
--- a/core/jni/android_text_Hyphenator.cpp
+++ b/core/jni/android_text_Hyphenator.cpp
@@ -18,10 +18,17 @@
#include
#include
#include
+#ifdef __ANDROID__
#include
+#else
+#include
+#include
+#endif
#include
#include
+#ifdef __ANDROID__
#include
+#endif
#include
#include
@@ -30,7 +37,12 @@
namespace android {
static std::string buildFileName(const std::string& locale) {
+#ifdef __ANDROID__
constexpr char SYSTEM_HYPHENATOR_PREFIX[] = "/system/usr/hyphen-data/hyph-";
+#else
+ std::string hyphenPath = base::GetProperty("ro.hyphen.data.dir", "/system/usr/hyphen-data");
+ std::string SYSTEM_HYPHENATOR_PREFIX = hyphenPath + "/hyph-";
+#endif
constexpr char SYSTEM_HYPHENATOR_SUFFIX[] = ".hyb";
std::string lowerLocale;
lowerLocale.reserve(locale.size());
@@ -51,11 +63,22 @@ static std::pair mmapPatternFile(const std::string& loca
return std::make_pair(nullptr, 0);
}
+#ifdef __ANDROID__
void* ptr = mmap(nullptr, st.st_size, PROT_READ, MAP_SHARED, fd, 0 /* offset */);
close(fd);
if (ptr == MAP_FAILED) {
return std::make_pair(nullptr, 0);
}
+#else
+ std::unique_ptr patternFile =
+ base::MappedFile::FromFd(fd, 0, st.st_size, PROT_READ);
+ close(fd);
+ if (patternFile == nullptr) {
+ return std::make_pair(nullptr, 0);
+ }
+ auto* mappedPtr = new base::MappedFile(std::move(*patternFile));
+ char* ptr = mappedPtr->data();
+#endif
return std::make_pair(reinterpret_cast(ptr), st.st_size);
}
@@ -210,9 +233,13 @@ static void init() {
addHyphenatorAlias("und-Taml", "ta"); // Tamil
addHyphenatorAlias("und-Telu", "te"); // Telugu
+#ifdef __ANDROID__
tracing_perfetto::traceBegin(ATRACE_TAG_VIEW, "CacheUnicodeExtensionSubtagsKeyMap");
+#endif
cacheUnicodeExtensionSubtagsKeyMap();
+#ifdef __ANDROID__
tracing_perfetto::traceEnd(ATRACE_TAG_VIEW); // CacheUnicodeExtensionSubtagsKeyMap
+#endif
}
static const JNINativeMethod gMethods[] = {
diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp
index 49191ee02ad6b3aaf9dfcbb010b66f39a4f5dbbe..7ef7829c6ba556bb2357424c7919e8035515d455 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -33,6 +33,7 @@
#include
#include
+#include
#include
#include
#include
@@ -1008,6 +1009,8 @@ jboolean android_os_Process_parseProcLineArray(JNIEnv* env, jobject clazz,
}
}
if ((mode&PROC_OUT_STRING) != 0 && di < NS) {
+ std::replace_if(buffer+start, buffer+end,
+ [](unsigned char c){ return !std::isprint(c); }, '?');
jstring str = env->NewStringUTF(buffer+start);
env->SetObjectArrayElement(outStrings, di, str);
}
diff --git a/core/jni/android_view_DisplayEventReceiver.cpp b/core/jni/android_view_DisplayEventReceiver.cpp
index f007cc5a23bd1cfbd8a4c011b4f980b73d5ac60d..a09c405de1cd9f78e1fa847454d4ca261db4f863 100644
--- a/core/jni/android_view_DisplayEventReceiver.cpp
+++ b/core/jni/android_view_DisplayEventReceiver.cpp
@@ -67,6 +67,7 @@ static struct {
jfieldID preferredFrameTimelineIndex;
jfieldID frameTimelinesLength;
jfieldID frameTimelines;
+ jfieldID numberQueuedBuffers;
} vsyncEventDataClassInfo;
} gDisplayEventReceiverClassInfo;
@@ -165,7 +166,8 @@ static jobject createJavaVsyncEventData(JNIEnv* env, VsyncEventData vsyncEventDa
return env->NewObject(gDisplayEventReceiverClassInfo.vsyncEventDataClassInfo.clazz,
gDisplayEventReceiverClassInfo.vsyncEventDataClassInfo.init,
frameTimelineObjs.get(), vsyncEventData.preferredFrameTimelineIndex,
- vsyncEventData.frameTimelinesLength, vsyncEventData.frameInterval);
+ vsyncEventData.frameTimelinesLength, vsyncEventData.frameInterval,
+ vsyncEventData.numberQueuedBuffers);
}
void NativeDisplayEventReceiver::dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId,
@@ -188,6 +190,9 @@ void NativeDisplayEventReceiver::dispatchVsync(nsecs_t timestamp, PhysicalDispla
env->SetLongField(vsyncEventDataObj.get(),
gDisplayEventReceiverClassInfo.vsyncEventDataClassInfo.frameInterval,
vsyncEventData.frameInterval);
+ env->SetIntField(vsyncEventDataObj.get(),
+ gDisplayEventReceiverClassInfo.vsyncEventDataClassInfo.numberQueuedBuffers,
+ vsyncEventData.numberQueuedBuffers);
ScopedLocalRef
frameTimelinesObj(env,
@@ -441,7 +446,7 @@ int register_android_view_DisplayEventReceiver(JNIEnv* env) {
GetMethodIDOrDie(env, gDisplayEventReceiverClassInfo.vsyncEventDataClassInfo.clazz,
"",
"([Landroid/view/"
- "DisplayEventReceiver$VsyncEventData$FrameTimeline;IIJ)V");
+ "DisplayEventReceiver$VsyncEventData$FrameTimeline;IIJI)V");
gDisplayEventReceiverClassInfo.vsyncEventDataClassInfo.preferredFrameTimelineIndex =
GetFieldIDOrDie(env, gDisplayEventReceiverClassInfo.vsyncEventDataClassInfo.clazz,
@@ -456,6 +461,9 @@ int register_android_view_DisplayEventReceiver(JNIEnv* env) {
GetFieldIDOrDie(env, gDisplayEventReceiverClassInfo.vsyncEventDataClassInfo.clazz,
"frameTimelines",
"[Landroid/view/DisplayEventReceiver$VsyncEventData$FrameTimeline;");
+ gDisplayEventReceiverClassInfo.vsyncEventDataClassInfo.numberQueuedBuffers =
+ GetFieldIDOrDie(env, gDisplayEventReceiverClassInfo.vsyncEventDataClassInfo.clazz,
+ "numberQueuedBuffers", "I");
return res;
}
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index d3bf36e60345a6e646c5b35c80f195b9434dd585..593b982d4cf209ad53d984c7b6664522c681c70b 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -758,54 +758,64 @@ static void nativeSetLuts(JNIEnv* env, jclass clazz, jlong transactionObj, jlong
auto transaction = reinterpret_cast(transactionObj);
SurfaceControl* const ctrl = reinterpret_cast(nativeObject);
- ScopedIntArrayRW joffsets(env, joffsetArray);
- if (joffsets.get() == nullptr) {
- jniThrowRuntimeException(env, "Failed to get ScopedIntArrayRW from joffsetArray");
- return;
- }
- ScopedIntArrayRW jdimensions(env, jdimensionArray);
- if (jdimensions.get() == nullptr) {
- jniThrowRuntimeException(env, "Failed to get ScopedIntArrayRW from jdimensionArray");
- return;
- }
- ScopedIntArrayRW jsizes(env, jsizeArray);
- if (jsizes.get() == nullptr) {
- jniThrowRuntimeException(env, "Failed to get ScopedIntArrayRW from jsizeArray");
- return;
- }
- ScopedIntArrayRW jsamplingKeys(env, jsamplingKeyArray);
- if (jsamplingKeys.get() == nullptr) {
- jniThrowRuntimeException(env, "Failed to get ScopedIntArrayRW from jsamplingKeyArray");
- return;
- }
+ std::vector offsets;
+ std::vector dimensions;
+ std::vector sizes;
+ std::vector samplingKeys;
+ int32_t fd = -1;
+
+ if (jdimensionArray) {
+ jsize numLuts = env->GetArrayLength(jdimensionArray);
+ ScopedIntArrayRW joffsets(env, joffsetArray);
+ if (joffsets.get() == nullptr) {
+ jniThrowRuntimeException(env, "Failed to get ScopedIntArrayRW from joffsetArray");
+ return;
+ }
+ ScopedIntArrayRW jdimensions(env, jdimensionArray);
+ if (jdimensions.get() == nullptr) {
+ jniThrowRuntimeException(env, "Failed to get ScopedIntArrayRW from jdimensionArray");
+ return;
+ }
+ ScopedIntArrayRW jsizes(env, jsizeArray);
+ if (jsizes.get() == nullptr) {
+ jniThrowRuntimeException(env, "Failed to get ScopedIntArrayRW from jsizeArray");
+ return;
+ }
+ ScopedIntArrayRW jsamplingKeys(env, jsamplingKeyArray);
+ if (jsamplingKeys.get() == nullptr) {
+ jniThrowRuntimeException(env, "Failed to get ScopedIntArrayRW from jsamplingKeyArray");
+ return;
+ }
- jsize numLuts = env->GetArrayLength(jdimensionArray);
- std::vector offsets(joffsets.get(), joffsets.get() + numLuts);
- std::vector dimensions(jdimensions.get(), jdimensions.get() + numLuts);
- std::vector sizes(jsizes.get(), jsizes.get() + numLuts);
- std::vector samplingKeys(jsamplingKeys.get(), jsamplingKeys.get() + numLuts);
+ if (numLuts > 0) {
+ offsets = std::vector(joffsets.get(), joffsets.get() + numLuts);
+ dimensions = std::vector(jdimensions.get(), jdimensions.get() + numLuts);
+ sizes = std::vector(jsizes.get(), jsizes.get() + numLuts);
+ samplingKeys = std::vector(jsamplingKeys.get(), jsamplingKeys.get() + numLuts);
- ScopedFloatArrayRW jbuffers(env, jbufferArray);
- if (jbuffers.get() == nullptr) {
- jniThrowRuntimeException(env, "Failed to get ScopedFloatArrayRW from jbufferArray");
- return;
- }
+ ScopedFloatArrayRW jbuffers(env, jbufferArray);
+ if (jbuffers.get() == nullptr) {
+ jniThrowRuntimeException(env, "Failed to get ScopedFloatArrayRW from jbufferArray");
+ return;
+ }
- // create the shared memory and copy jbuffers
- size_t bufferSize = jbuffers.size() * sizeof(float);
- int32_t fd = ashmem_create_region("lut_shread_mem", bufferSize);
- if (fd < 0) {
- jniThrowRuntimeException(env, "ashmem_create_region() failed");
- return;
- }
- void* ptr = mmap(nullptr, bufferSize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
- if (ptr == MAP_FAILED) {
- jniThrowRuntimeException(env, "Failed to map the shared memory");
- return;
+ // create the shared memory and copy jbuffers
+ size_t bufferSize = jbuffers.size() * sizeof(float);
+ fd = ashmem_create_region("lut_shared_mem", bufferSize);
+ if (fd < 0) {
+ jniThrowRuntimeException(env, "ashmem_create_region() failed");
+ return;
+ }
+ void* ptr = mmap(nullptr, bufferSize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ if (ptr == MAP_FAILED) {
+ jniThrowRuntimeException(env, "Failed to map the shared memory");
+ return;
+ }
+ memcpy(ptr, jbuffers.get(), bufferSize);
+ // unmap
+ munmap(ptr, bufferSize);
+ }
}
- memcpy(ptr, jbuffers.get(), bufferSize);
- // unmap
- munmap(ptr, bufferSize);
transaction->setLuts(ctrl, base::unique_fd(fd), offsets, dimensions, sizes, samplingKeys);
}
@@ -1332,8 +1342,9 @@ static void nativeSetDisplaySize(JNIEnv* env, jclass clazz,
}
}
-static jobject convertDeviceProductInfoToJavaObject(
- JNIEnv* env, const std::optional& info) {
+static jobject convertDeviceProductInfoToJavaObject(JNIEnv* env,
+ const std::optional& info,
+ bool isInternal) {
using ModelYear = android::DeviceProductInfo::ModelYear;
using ManufactureYear = android::DeviceProductInfo::ManufactureYear;
using ManufactureWeekAndYear = android::DeviceProductInfo::ManufactureWeekAndYear;
@@ -1368,7 +1379,8 @@ static jobject convertDeviceProductInfoToJavaObject(
// Section 8.7 - Physical Address of HDMI Specification Version 1.3a
using android::hardware::display::IDeviceProductInfoConstants;
if (info->relativeAddress.size() != 4) {
- connectionToSinkType = IDeviceProductInfoConstants::CONNECTION_TO_SINK_UNKNOWN;
+ connectionToSinkType = isInternal ? IDeviceProductInfoConstants::CONNECTION_TO_SINK_BUILT_IN
+ : IDeviceProductInfoConstants::CONNECTION_TO_SINK_UNKNOWN;
} else if (info->relativeAddress[0] == 0) {
connectionToSinkType = IDeviceProductInfoConstants::CONNECTION_TO_SINK_BUILT_IN;
} else if (info->relativeAddress[1] == 0) {
@@ -1390,12 +1402,14 @@ static jobject nativeGetStaticDisplayInfo(JNIEnv* env, jclass clazz, jlong id) {
jobject object =
env->NewObject(gStaticDisplayInfoClassInfo.clazz, gStaticDisplayInfoClassInfo.ctor);
- env->SetBooleanField(object, gStaticDisplayInfoClassInfo.isInternal,
- info.connectionType == ui::DisplayConnectionType::Internal);
+
+ const bool isInternal = info.connectionType == ui::DisplayConnectionType::Internal;
+ env->SetBooleanField(object, gStaticDisplayInfoClassInfo.isInternal, isInternal);
env->SetFloatField(object, gStaticDisplayInfoClassInfo.density, info.density);
env->SetBooleanField(object, gStaticDisplayInfoClassInfo.secure, info.secure);
env->SetObjectField(object, gStaticDisplayInfoClassInfo.deviceProductInfo,
- convertDeviceProductInfoToJavaObject(env, info.deviceProductInfo));
+ convertDeviceProductInfoToJavaObject(env, info.deviceProductInfo,
+ isInternal));
env->SetIntField(object, gStaticDisplayInfoClassInfo.installOrientation,
static_cast(info.installOrientation));
return object;
@@ -2163,7 +2177,7 @@ static void nativeClearTrustedPresentationCallback(JNIEnv* env, jclass clazz, jl
class JankDataListenerWrapper : public JankDataListener {
public:
- JankDataListenerWrapper(JNIEnv* env, jobject onJankDataListenerObject) {
+ JankDataListenerWrapper(JNIEnv* env, jobject onJankDataListenerObject) : mRemovedVsyncId(-1) {
mOnJankDataListenerWeak = env->NewWeakGlobalRef(onJankDataListenerObject);
env->GetJavaVM(&mVm);
}
@@ -2174,6 +2188,12 @@ public:
}
bool onJankDataAvailable(const std::vector& jankData) override {
+ // Don't invoke the listener if we've been force removed and got this
+ // out-of-order callback.
+ if (mRemovedVsyncId == 0) {
+ return false;
+ }
+
JNIEnv* env = getEnv();
jobject target = env->NewLocalRef(mOnJankDataListenerWeak);
@@ -2181,8 +2201,8 @@ public:
return false;
}
- jobjectArray jJankDataArray = env->NewObjectArray(jankData.size(),
- gJankDataClassInfo.clazz, nullptr);
+ jobjectArray jJankDataArray =
+ env->NewObjectArray(jankData.size(), gJankDataClassInfo.clazz, nullptr);
for (size_t i = 0; i < jankData.size(); i++) {
// The exposed constants in SurfaceControl are simplified, so we need to translate the
// jank type we get from SF to what is exposed in Java.
@@ -2225,6 +2245,11 @@ public:
return true;
}
+ void removeListener(int64_t afterVsyncId) {
+ mRemovedVsyncId = (afterVsyncId <= 0) ? 0 : afterVsyncId;
+ JankDataListener::removeListener(afterVsyncId);
+ }
+
private:
JNIEnv* getEnv() {
@@ -2235,6 +2260,7 @@ private:
JavaVM* mVm;
jobject mOnJankDataListenerWeak;
+ int64_t mRemovedVsyncId;
};
static jlong nativeCreateJankDataListenerWrapper(JNIEnv* env, jclass clazz,
diff --git a/core/jni/com_android_internal_content_FileSystemUtils.cpp b/core/jni/com_android_internal_content_FileSystemUtils.cpp
index 6c72544a7958b6dcf664a77bd24549ca6cc5fa5a..76ead2a3ca31404f2cd5c58b38bd0eb2253796f4 100644
--- a/core/jni/com_android_internal_content_FileSystemUtils.cpp
+++ b/core/jni/com_android_internal_content_FileSystemUtils.cpp
@@ -22,7 +22,6 @@
#include
#include
#include
-#include
#include
#include
#include
@@ -204,7 +203,8 @@ bool punchHoles(const char *filePath, const uint64_t offset,
return true;
}
-bool punchHolesInElf64(const char *filePath, const uint64_t offset) {
+bool getLoadSegmentPhdrs(const char *filePath, const uint64_t offset,
+ std::vector &programHeaders) {
// Open Elf file
Elf64_Ehdr ehdr;
std::ifstream inputStream(filePath, std::ifstream::in);
@@ -227,11 +227,6 @@ bool punchHolesInElf64(const char *filePath, const uint64_t offset) {
uint64_t programHeaderOffset = ehdr.e_phoff;
uint16_t programHeaderNum = ehdr.e_phnum;
- IF_ALOGD() {
- ALOGD("Punching holes in file: %s programHeaderOffset: %" PRIu64 " programHeaderNum: %hu",
- filePath, programHeaderOffset, programHeaderNum);
- }
-
// if this is a zip file, also consider elf offset inside a file
uint64_t phOffset;
if (__builtin_add_overflow(offset, programHeaderOffset, &phOffset)) {
@@ -240,7 +235,6 @@ bool punchHolesInElf64(const char *filePath, const uint64_t offset) {
}
inputStream.seekg(phOffset);
- std::vector programHeaders;
for (int headerIndex = 0; headerIndex < programHeaderNum; headerIndex++) {
Elf64_Phdr header;
inputStream.read((char *)&header, sizeof(header));
@@ -254,6 +248,15 @@ bool punchHolesInElf64(const char *filePath, const uint64_t offset) {
programHeaders.push_back(header);
}
+ return true;
+}
+
+bool punchHolesInElf64(const char *filePath, const uint64_t offset) {
+ std::vector programHeaders;
+ if (!getLoadSegmentPhdrs(filePath, offset, programHeaders)) {
+ ALOGE("Failed to read program headers from ELF file.");
+ return false;
+ }
return punchHoles(filePath, offset, programHeaders);
}
diff --git a/core/jni/com_android_internal_content_FileSystemUtils.h b/core/jni/com_android_internal_content_FileSystemUtils.h
index 52445e2b4229531a6228c21d420d288677074c23..4a95686c5a0c1ddf40391a4a527f7d9cbadff6ad 100644
--- a/core/jni/com_android_internal_content_FileSystemUtils.h
+++ b/core/jni/com_android_internal_content_FileSystemUtils.h
@@ -15,8 +15,11 @@
*/
#pragma once
+#include
#include
+#include
+
namespace android {
/*
@@ -35,4 +38,11 @@ bool punchHolesInElf64(const char* filePath, uint64_t offset);
*/
bool punchHolesInZip(const char* filePath, uint64_t offset, uint16_t extraFieldLen);
+/*
+ * This function reads program headers from ELF file. ELF can be specified with file path directly
+ * or it should be at offset inside Apk. Program headers passed to function is populated.
+ */
+bool getLoadSegmentPhdrs(const char* filePath, const uint64_t offset,
+ std::vector& programHeaders);
+
} // namespace android
\ No newline at end of file
diff --git a/core/jni/platform/host/HostRuntime.cpp b/core/jni/platform/host/HostRuntime.cpp
index 7fca1175f3d4e62ae8694f2b364aee2945fefd1c..1a0328338980eb787e34f49eae8e751639ba5706 100644
--- a/core/jni/platform/host/HostRuntime.cpp
+++ b/core/jni/platform/host/HostRuntime.cpp
@@ -88,6 +88,7 @@ extern int register_android_os_Parcel(JNIEnv* env);
extern int register_android_os_SystemClock(JNIEnv* env);
extern int register_android_os_SystemProperties(JNIEnv* env);
extern int register_android_text_AndroidCharacter(JNIEnv* env);
+extern int register_android_text_Hyphenator(JNIEnv* env);
extern int register_android_util_EventLog(JNIEnv* env);
extern int register_android_util_Log(JNIEnv* env);
extern int register_android_util_jar_StrictJarFile(JNIEnv* env);
@@ -133,6 +134,7 @@ static const std::unordered_map gRegJNIMap = {
{"android.os.SystemClock", REG_JNI(register_android_os_SystemClock)},
{"android.os.SystemProperties", REG_JNI(register_android_os_SystemProperties)},
{"android.text.AndroidCharacter", REG_JNI(register_android_text_AndroidCharacter)},
+ {"android.text.Hyphenator", REG_JNI(register_android_text_Hyphenator)},
{"android.util.EventLog", REG_JNI(register_android_util_EventLog)},
{"android.util.Log", REG_JNI(register_android_util_Log)},
{"android.util.jar.StrictJarFile", REG_JNI(register_android_util_jar_StrictJarFile)},
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index d09802a91edc6eb6686e9f364d997016af32f40a..7fcbf19d137fb6caa9514cfb006c0eb0506300ca 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -914,13 +914,26 @@
android:featureFlag="android.provider.user_keys" />
+ android:protectionLevel="internal|role"
+ android:featureFlag="!android.provider.new_default_account_api_enabled"/>
+
+
+
@@ -1080,6 +1093,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -4144,6 +4203,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
-
+ Protection Level: signature|privileged|appop -->
+ android:protectionLevel="signature|privileged|appop"
+ android:featureFlag="com.android.settingslib.flags.write_system_preference_permission_enabled" />
@@ -5497,7 +5587,8 @@
-
@@ -7844,7 +7935,31 @@
+ android:protectionLevel="signature|installer"
+ android:featureFlag="!android.content.pm.sdk_dependency_installer" />
+
+
+
+
+
+
+
+
+
@@ -8335,6 +8450,26 @@
android:protectionLevel="signature|knownSigner"
android:knownCerts="@array/config_healthConnectMigrationKnownSigners" />
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/core/res/res/layout/notification_2025_template_header.xml b/core/res/res/layout/notification_2025_template_header.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b7fe454e09d417a81d20ab73f55ce2e86f292ab6
--- /dev/null
+++ b/core/res/res/layout/notification_2025_template_header.xml
@@ -0,0 +1,111 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/core/res/res/layout/notification_template_material_messaging_compact_heads_up.xml b/core/res/res/layout/notification_template_material_messaging_compact_heads_up.xml
index 82920bad95cd552a0e979583852bdfedc35faaf6..149a5a9568f28a827038054eeb4e6322d3b16e24 100644
--- a/core/res/res/layout/notification_template_material_messaging_compact_heads_up.xml
+++ b/core/res/res/layout/notification_template_material_messaging_compact_heads_up.xml
@@ -34,12 +34,14 @@
android:maxDrawableWidth="@dimen/notification_icon_circle_size"
android:maxDrawableHeight="@dimen/notification_icon_circle_size"
/>
- "Laat die program toe om relatiewe posisie tussen ultrabreëbandtoestelle in die omtrek te bepaal"
"om interaksie met wi‑fi-toestelle in die omtrek te hê"
"Laat die program toe om op toestelle in die omtrek te adverteer, aan hulle te koppel en hul relatiewe posisie te bepaal"
+
+
+
+
"Voorkeur-NFC-betalingdiensinligting"
"Laat die program toe om voorkeur-NFC-betalingdiensinligting soos geregistreerde hulpmiddels en roetebestemming te kry."
"beheer kortveldkommunikasie"
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 91b4ef01701443b5ac5d2154234c803818cfee1e..c30a5c853421a69caf0ce6eb39763c38d2042bdf 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -612,6 +612,10 @@
"በአቅራቢያ ባሉ ልዕለ-ሰፊ ባንድ መሣሪያዎች መካከል ያለውን አንጻራዊ አቀማመጣቸውን ለማወቅ ንዲችል ለመተግበሪያው ይፍቀዱ"
"በአቅራቢያ ካሉ የWi‑Fi መሣሪያዎች ጋር መስተጋብር መፍጠር"
"መተግበሪያው በአቅራቢያ ያሉ የWi-Fi መሣሪያዎች አንጻራዊ ቦታን እንዲያሳውቅ፣ እንዲያገናኝ እና እንዲያውቅ ያስችለዋል"
+
+
+
+
"ተመራጭ NFC የክፍያ አገልግሎት መረጃ"
"እንደ የተመዘገቡ እርዳታዎች እና የጉዞ መሥመር መዳረሻ የመሳሰለ ተመራጭ nfc የክፍያ አገልግሎት መረጃን ለማግኘት ለመተግበሪያው ያፈቅድለታል።"
"ቅርብ የግኑኙነትመስክ (NFC) ተቆጣጠር"
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 6e5dcd36fd3184b42e8f35c72fa8999edb0e851b..f2080cbbe3d912a02e443189857cacc870245278 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -616,6 +616,10 @@
"يسمح هذا الإذن للتطبيق بتحديد الموضع النسبي بين الأجهزة المجاورة التي تستخدم النطاق الواسع جدًا."
"التفاعل مع أجهزة Wi‑Fi المجاورة"
"للسماح للتطبيق بعرض الإعلانات والاتصال بالأجهزة الأخرى وتحديد الموقع النسبي لأجهزة Wi-Fi المجاورة."
+
+
+
+
"معلومات الخدمات المدفوعة باستخدام الاتصال قصير المدى NFC المفضّل"
"يسمح هذا الإذن للتطبيق بالحصول على معلومات الخدمات المدفوعة باستخدام الاتصال قصير المدى NFC المفضّل، مثلاً المساعدات المسجّلة ووجهة المسار."
"التحكم في اتصال الحقل القريب"
@@ -2435,54 +2439,30 @@
"تفعيل"
"رجوع"
"بانتظار الإزالة من الأرشيف…"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "تتوفّر الآن ميزة \"اتصالات طوارئ بالقمر الصناعي\""
+ "يمكنك مراسلة خدمات الطوارئ في حال عدم توفّر شبكة جوّال أو شبكة Wi-Fi. ولإجراء ذلك، يجب ضبط تطبيق \"رسائل Google\" ليصبح تطبيق المراسلة التلقائي."
+ "ميزة \"اتصالات طوارئ بالقمر الصناعي\" غير متاحة"
+ "ميزة \"اتصالات طوارئ بالقمر الصناعي\" غير متاحة على هذا الجهاز"
+ "لم يتم ضبط إعدادات ميزة \"اتصالات طوارئ بالقمر الصناعي\""
+ "يُرجى التأكّد من أنّ جهازك متصل بالإنترنت ومحاولة ضبط الميزة مرة أخرى"
+ "ميزة \"اتصالات طوارئ بالقمر الصناعي\" غير متوفّرة"
+ "لا تتوفّر ميزة \"اتصالات طوارئ بالقمر الصناعي\" في هذا البلد أو هذه المنطقة"
+ "لم يتم ضبط إعدادات ميزة \"اتصالات طوارئ بالقمر الصناعي\""
+ "للمراسلة عبر القمر الصناعي، عليك ضبط تطبيق \"رسائل Google\" ليصبح تطبيق المراسلة التلقائي"
+ "ميزة \"اتصالات طوارئ بالقمر الصناعي\" غير متوفّرة"
+ "لمعرفة ما إذا كانت ميزة \"اتصالات طوارئ بالقمر الصناعي\" متاحة في هذا البلد أو هذه المنطقة، فعِّل إعدادات الموقع الجغرافي"
+ "ميزة \"المراسلة عبر القمر الاصطناعي\" متاحة"
+ "يمكنك إرسال رسائل عبر القمر الصناعي في حال عدم توفّر شبكة جوّال أو شبكة Wi-Fi. ولإجراء ذلك، يجب ضبط تطبيق \"رسائل Google\" ليصبح تطبيق المراسلة التلقائي."
+ "ميزة \"المراسلة عبر القمر الاصطناعي\" غير متاحة"
+ "ميزة \"المراسلة عبر القمر الاصطناعي\" غير متاحة على هذا الجهاز"
+ "لم يتم ضبط إعدادات ميزة \"المراسلة عبر القمر الاصطناعي\""
+ "يُرجى التأكّد من أنّ جهازك متصل بالإنترنت ومحاولة ضبط الميزة مرة أخرى"
+ "ميزة \"المراسلة عبر القمر الاصطناعي\" غير متاحة"
+ "لا تتوفّر ميزة \"المراسلة عبر القمر الاصطناعي\" في هذا البلد أو هذه المنطقة"
+ "لم يتم ضبط إعدادات ميزة \"المراسلة عبر القمر الاصطناعي\""
+ "للمراسلة عبر القمر الصناعي، عليك ضبط تطبيق \"رسائل Google\" ليصبح تطبيق المراسلة التلقائي"
+ "ميزة \"المراسلة عبر القمر الاصطناعي\" غير متاحة"
+ "لمعرفة ما إذا كانت ميزة \"المراسلة عبر القمر الاصطناعي\" متاحة في هذا البلد أو هذه المنطقة، فعِّل إعدادات الموقع الجغرافي"
"إعادة إعداد ميزة \"فتح الجهاز ببصمة الإصبع\""
"لا يمكن بعد الآن التعرّف على \"%s\"."
"لا يمكن بعد الآن التعرّف على \"%1$s\" و\"%2$s\"."
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index 1af7810acfeb21b038ed08746ac0ad8ef709b9a0..1f207d571c5afd37bf5b58a9ef76617e874cb8bd 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -612,6 +612,10 @@
"এপ্টোক নিকটৱৰ্তী আল্ট্ৰা-ৱাইডবেণ্ড ডিভাইচসমূহৰ মাজৰ আপেক্ষিক স্থান নিৰ্ধাৰণ কৰিবলৈ অনুমতি দিয়ক"
"নিকটৱৰ্তী ৱাই-ফাই ডিভাইচসমূহৰ সৈতে ভাব বিনিময় কৰক"
"এপ্টোক বিজ্ঞাপন প্ৰচাৰাভিযান কৰিবলৈ, সংযোগ কৰিবলৈ আৰু নিকটৱৰ্তী ৱাই-ফাই ডিভাইচৰ আপেক্ষিক স্থান নিৰ্ধাৰণ কৰিবলৈ অনুমতি দিয়ে"
+
+
+
+
"অগ্ৰাধিকাৰ দিয়া NFC পৰিশোধ সেৱাৰ তথ্য"
"এপ্টোক অগ্ৰাধিকাৰ দিয়া nfc পৰিশোধ সেৱাৰ পঞ্জীকৃত সহায়কসমূহ আৰু পৰিশোধ কৰিব লগা লক্ষ্যস্থান দৰে তথ্য পাবলৈ অনুমতি দিয়ে।"
"নিয়েৰ ফিল্ড কমিউনিকেশ্বন নিয়ন্ত্ৰণ কৰক"
@@ -2431,54 +2435,30 @@
"অন কৰক"
"উভতি যাওক"
"বিবেচনাধীন হৈ আছে..."
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "উপগ্ৰহ SOS সুবিধাটো এতিয়া উপলব্ধ"
+ "যদি ম’বাইল বা ৱাই-ফাই নেটৱৰ্ক নাথাকিলেও আপুনি জৰুৰীকালীন সেৱাসমূহলৈ বার্তা পঠিয়াব পাৰে। Google Messages আপোনাৰ ডিফ’ল্ট বাৰ্তা আদান-প্ৰদান কৰা এপ্ হ’বই লাগিব।"
+ "উপগ্ৰহ SOS সুবিধা সমৰ্থিত নহয়"
+ "এই ডিভাইচটোত উপগ্ৰহ SOS সুবিধা সমৰ্থিত নহয়"
+ "উপগ্ৰহ SOS সুবিধা ছেট আপ কৰা হোৱা নাই"
+ "আপুনি ইণ্টাৰনেটৰ সৈতে সংযুক্ত হৈ থকাটো নিশ্চিত কৰক আৰু পুনৰ ছেটআপ কৰিবলৈ চেষ্টা কৰক"
+ "উপগ্ৰহ SOS সুবিধা উপলব্ধ নহয়"
+ "এই দেশ বা অঞ্চলত উপগ্ৰহ SOS সুবিধা উপলব্ধ নহয়"
+ "উপগ্ৰহ SOS সুবিধা ছেট আপ কৰা হোৱা নাই"
+ "উপগ্ৰহৰ জৰিয়তে বাৰ্তা পঠিয়াবলৈ, Google Messagesক আপোনাৰ ডিফ’ল্ট বাৰ্তা আদান-প্ৰদান কৰা এপ্ হিচাপে ছেট কৰক"
+ "উপগ্ৰহ SOS সুবিধা উপলব্ধ নহয়"
+ "এই দেশ বা অঞ্চলত উপগ্ৰহ SOS সুবিধা উপলব্ধ হয় নে নহয় পৰীক্ষা কৰিবলৈ, অৱস্থানৰ ছেটিং অন কৰক"
+ "উপগ্ৰহৰ দ্বাৰা বাৰ্তা বিনিময়ৰ সুবিধা উপলব্ধ"
+ "ম’বাইল বা ৱাই-ফাই নেটৱৰ্ক নাথাকিলেও আপুনি উপগ্ৰহৰ জৰিয়তে বার্তা পঠিয়াব পাৰে। Google Messages আপোনাৰ ডিফ’ল্ট বাৰ্তা আদান-প্ৰদান কৰা এপ্ হ’বই লাগিব।"
+ "উপগ্ৰহৰ দ্বাৰা বাৰ্তা বিনিময়ৰ সুবিধা সমৰ্থিত নহয়"
+ "এই ডিভাইচটোত উপগ্ৰহৰ দ্বাৰা বাৰ্তা বিনিময়ৰ সুবিধা সমৰ্থিত নহয়"
+ "উপগ্ৰহৰ দ্বাৰা বাৰ্তা বিনিময়ৰ সুবিধা ছেট আপ কৰা হোৱা নাই"
+ "আপুনি ইণ্টাৰনেটৰ সৈতে সংযুক্ত হৈ থকাটো নিশ্চিত কৰক আৰু পুনৰ ছেটআপ কৰিবলৈ চেষ্টা কৰক"
+ "উপগ্ৰহৰ দ্বাৰা বাৰ্তা বিনিময়ৰ সুবিধা উপলব্ধ নহয়"
+ "এই দেশ বা অঞ্চলত উপগ্ৰহৰ দ্বাৰা বাৰ্তা বিনিময়ৰ সুবিধা উপলব্ধ নহয়"
+ "উপগ্ৰহৰ দ্বাৰা বাৰ্তা বিনিময়ৰ সুবিধা ছেট আপ কৰা হোৱা নাই"
+ "উপগ্ৰহৰ জৰিয়তে বাৰ্তা পঠিয়াবলৈ, Google Messagesক আপোনাৰ ডিফ’ল্ট বাৰ্তা আদান-প্ৰদান কৰা এপ্ হিচাপে ছেট কৰক"
+ "উপগ্ৰহৰ দ্বাৰা বাৰ্তা বিনিময়ৰ সুবিধা উপলব্ধ নহয়"
+ "এই দেশ বা অঞ্চলত উপগ্ৰহৰ দ্বাৰা বাৰ্তা বিনিময়ৰ সুবিধা উপলব্ধ হয় নে নহয় পৰীক্ষা কৰিবলৈ, অৱস্থানৰ ছেটিং অন কৰক"
"ফিংগাৰপ্ৰিণ্ট আনলক পুনৰ ছেট আপ কৰক"
"%s আৰু চিনাক্ত কৰিব নোৱাৰি।"
"%1$s আৰু %2$s আৰু চিনাক্ত কৰিব নোৱাৰি।"
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index 1ba96fea7a197e93851caf9a43c2ecb080219ad0..07216f55bdcdd7c72c1815404f824bdf1b6adf78 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -612,6 +612,10 @@
"Tətbiqə yaxınlıqdakı Ultra Genişzolaqlı cihazları arasında nisbi mövqeyi təyin etməyə icazə verin"
"yaxınlıqdakı Wi-Fi cihazları ilə əlaqə qurmaq"
"Tətbiqə yaxınlıqdakı Wi-Fi cihazlarında reklam etmək, onlara qoşulmaq və nisbi mövqeyini təyin etmək icazəsi verir"
+
+
+
+
"Tərcih edilən NFC ödəniş xidməti məlumatı"
"Tətbiqə qeydiyyatdan keçmiş yardım və marşrut təyinatı kimi tərcih edilən nfc ödəniş xidməti məlumatını əldə etmək icazəsi verir."
"Near Field Communication\'ı kontrol et"
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index 4c78d30c874e0e78478749075381a6fd0c36cdaa..ac6a47fd8f84fd76a22e0c7cc408c9ea5f09baf7 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -613,6 +613,10 @@
"Dozvoljava aplikaciji da određuje relativnu razdaljinu između uređaja ultra-širokog pojasa u blizini"
"interakcija sa WiFi uređajima u blizini"
"Dozvoljava aplikaciji da se oglašava, povezuje i utvrđuje relativnu poziciju WiFi uređaja u blizini"
+
+
+
+
"Informacije o željenoj NFC usluzi za plaćanje"
"Dozvoljava aplikaciji da preuzima informacije o željenoj NFC usluzi za plaćanje, poput registrovanih identifikatora aplikacija i odredišta preusmeravanja."
"kontrola komunikacije u užem polju (Near Field Communication)"
@@ -2432,54 +2436,30 @@
"Uključi"
"Nazad"
"Na čekanju..."
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "Hitna pomoć preko satelita je sada dostupna"
+ "Možete da šaljete poruke hitnim službama ako nemate pristup mobilnoj ni WiFi mreži. Google Messages mora da bude podrazumevana aplikacija za razmenu poruka."
+ "Hitna pomoć preko satelita nije podržana"
+ "Hitna pomoć preko satelita nije podržana na ovom uređaju"
+ "Hitna pomoć preko satelita nije podešena"
+ "Proverite da li ste povezani na internet i probajte ponovo da podesite"
+ "Hitna pomoć preko satelita nije dostupna"
+ "Hitna pomoć preko satelita nije dostupna u ovoj zemlji ili regionu"
+ "Hitna pomoć preko satelita nije podešena"
+ "Da biste slali poruke preko satelita, podesite Google Messages kao podrazumevanu aplikaciju za razmenu poruka"
+ "Hitna pomoć preko satelita nije dostupna"
+ "Da biste proverili da li je hitna pomoć preko satelita dostupna u ovoj zemlji ili regionu, uključite podešavanja lokacije"
+ "Razmena poruka preko satelita je dostupna"
+ "Možete da šaljete poruke preko satelita ako nemate pristup mobilnoj ni WiFi mreži. Google Messages mora da bude podrazumevana aplikacija za razmenu poruka."
+ "Razmena poruka preko satelita nije podržana"
+ "Razmena poruka preko satelita nije podržana na ovom uređaju"
+ "Razmena poruka preko satelita nije podešena"
+ "Proverite da li ste povezani na internet i probajte ponovo da podesite"
+ "Razmena poruka preko satelita nije dostupna"
+ "Razmena poruka preko satelita nije dostupna u ovoj zemlji ili regionu"
+ "Razmena poruka preko satelita nije podešena"
+ "Da biste slali poruke preko satelita, podesite Google Messages kao podrazumevanu aplikaciju za razmenu poruka"
+ "Razmena poruka preko satelita nije dostupna"
+ "Da biste proverili da li je razmena poruka preko satelita dostupna u ovoj zemlji ili regionu, uključite podešavanja lokacije"
"Ponovo podesite otključavanje otiskom prsta"
"%s više ne može da se prepozna."
"%1$s i %2$s više ne mogu da se prepoznaju."
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 549ec78cc7d802055f135d1d38e89bc3dec214fd..f492bfa4cc7bb69c5677af79d5ff508477ac167c 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -614,6 +614,10 @@
"Дазволіць праграме вызначаць адлегласць паміж прыладамі паблізу, якія выкарыстоўваюць звышшырокапалосную сувязь"
"узаемадзейнічаць з прыладамі з Wi‑Fi паблізу"
"Праграма зможа адпраўляць даныя на прылады Wi-Fi паблізу, падключацца да іх і вызначаць іх месцазнаходжанне"
+
+
+
+
"Інфармацыя пра прыярытэтны сэрвіс аплаты NFC"
"Дазваляе праграме атрымаць доступ да інфармацыі пра прыярытэтны сэрвіс аплаты NFC, напрыклад зарэгістраваныя ідэнтыфікатары праграм і маршруты адпраўкі даных."
"кантроль Near Field Communication"
@@ -2433,54 +2437,30 @@
"Уключыць"
"Назад"
"У чаканні..."
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "Экстраннае спадарожнікавае падключэнне зараз даступнае"
+ "У вас ёсць магчымасць адпраўляць паведамленні ў экстранныя службы, калі адсутнічае падключэнне да мабільнай сеткі ці сеткі Wi-Fi. Упэўніцеся, што ў якасці стандартнай выбрана праграма \"Google Паведамленні\"."
+ "Экстраннае спадарожнікавае падключэнне не падтрымліваецца"
+ "Экстраннае спадарожнікавае падключэнне не падтрымліваецца на гэтай прыладзе"
+ "Экстраннае спадарожнікавае падключэнне не наладжана"
+ "Праверце падключэнне да інтэрнэту і паўтарыце наладжванне"
+ "Экстраннае спадарожнікавае падключэнне недаступнае"
+ "Функцыя экстраннага спадарожнікавага падключэння недаступная ў гэтай краіне або рэгіёне"
+ "Экстраннае спадарожнікавае падключэнне не наладжана"
+ "Каб выкарыстоўваць абмен паведамленнямі па спадарожнікавай сувязі, праграма \"Google Паведамленні\" павінна быць выбрана як стандартная праграма абмену паведамленнямі"
+ "Экстраннае спадарожнікавае падключэнне недаступнае"
+ "Уключыце налады месцазнаходжання, каб праверыць, ці даступнае экстраннае спадарожнікавае падключэнне ў гэтай краіне ці рэгіёне"
+ "Абмен паведамленнямі па спадарожнікавай сувязі даступны"
+ "Вы можаце абменьвацца паведамленнямі па спадарожнікавай сувязі, калі падключэнне да мабільнай сеткі ці сеткі Wi-Fi адсутнічае. Упэўніцеся, што ў якасці стандартнай выбрана праграма \"Google Паведамленні\"."
+ "Абмен паведамленнямі па спадарожнікавай сувязі не падтрымліваецца"
+ "Абмен паведамленнямі па спадарожнікавай сувязі не падтрымліваецца на гэтай прыладзе"
+ "Абмен паведамленнямі па спадарожнікавай сувязі не наладжаны"
+ "Праверце падключэнне да інтэрнэту і паўтарыце наладжванне"
+ "Абмен паведамленнямі па спадарожнікавай сувязі недаступны"
+ "Абмен паведамленнямі па спадарожнікавай сувязі недаступны ў гэтай краіне або рэгіёне"
+ "Абмен паведамленнямі па спадарожнікавай сувязі не наладжаны"
+ "Каб выкарыстоўваць абмен паведамленнямі па спадарожнікавай сувязі, праграма \"Google Паведамленні\" павінна быць выбрана як стандартная праграма абмену паведамленнямі"
+ "Абмен паведамленнямі па спадарожнікавай сувязі недаступны"
+ "Каб праверыць, ці даступны абмен паведамленнямі па спадарожнікавай сувязі ў гэтай краіне ці рэгіёне, уключыце налады месцазнаходжання"
"Наладзіць разблакіроўку адбіткам пальца паўторна"
"Адбітак пальца \"%s\" больш не можа быць распазнаны."
"Адбіткі пальцаў \"%1$s\" і \"%2$s\" больш не могуць быць распазнаны."
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 40aae5144448102140bcf5cb5098f6579799a5aa..c8b171af5bc99365e9ec9c346282333324863249 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -612,6 +612,10 @@
"Разрешаване на приложението да определя относителната позиция между устройствата с ултрашироколентови сигнали в близост"
"взаимодействие с устройствата с Wi-Fi в близост"
"Разрешава на приложението да рекламира, да се свързва и да определя относителната позиция на устройствата с Wi-Fi в близост"
+
+
+
+
"Информация за предпочитаната услуга за плащане чрез NFC"
"Дава възможност на приложението да получава информация за предпочитаната услуга за плащане чрез NFC, като например регистрирани помощни средства и местоназначение."
"контролиране на комуникацията в близкото поле"
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index 32077d8a43744c47cdd0f81f73ebea8ab7b9fd3a..0e103cc424b0aa4e740beb6e9f2c4e0e34cb41d9 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -612,6 +612,10 @@
"অ্যাপকে আশেপাশের Ultra-Wideband ডিভাইসগুলির আপেক্ষিক অবস্থান নির্ণয় করার অনুমতি দিন"
"আশপাশের ওয়াই-ফাই ডিভাইসের সাথে ইন্টার্যাক্ট করুন"
"এটির ফলে অ্যাপ আশপাশের ওয়াই-ফাই ডিভাইসের তথ্য দেখতে, তাদের সাথে কানেক্ট করতে এবং তা কত দূরত্বে আছে সেটি জানতে পারবে"
+
+
+
+
"পছন্দের NFC পেমেন্ট পরিষেবার তথ্য"
"অ্যাপের মাধ্যমে পছন্দসই এনএফসি পেমেন্ট পরিষেবার তথ্য, যেমন রেজিস্ট্রার করার সহায়তা এবং রুট ডেস্টিনেশন সম্পর্কিত তথ্য অ্যাক্সেস করার অনুমতি দেয়।"
"নিয়ার ফিল্ড কমিউনিকেশন নিয়ন্ত্রণ করে"
@@ -2431,54 +2435,30 @@
"চালু করুন"
"ফিরে যান"
"বাকি আছে…"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "স্যাটেলাইট SOS এখন উপলভ্য"
+ "কোনও মোবাইল বা ওয়াই-ফাই নেটওয়ার্ক না থাকলেও আপনি জরুরি পরিষেবাতে মেসেজ করতে পারবেন। Google Messages অবশ্যই আপনার ডিফল্ট মেসেজিং অ্যাপ হতে হবে।"
+ "স্যাটেলাইট SOS কাজ করে না"
+ "এই ডিভাইসে স্যাটেলাইট SOS কাজ করে না"
+ "স্যাটেলাইট SOS সেট আপ করা হয়নি"
+ "আপনার ডিভাইসে ইন্টারনেট কানেকশন আছে কিনা দেখে নিন এবং আবার সেটআপ করার চেষ্টা করুন"
+ "স্যাটেলাইট SOS উপলভ্য নেই"
+ "এই দেশ অথবা অঞ্চলে স্যাটেলাইট SOS উপলভ্য নেই"
+ "স্যাটেলাইট SOS সেট আপ করা নেই"
+ "স্যাটেলাইটের সাহায্যে মেসেজ পাঠাতে, আপনার ডিফল্ট মেসেজিং অ্যাপ হিসেবে Google Messages সেট করুন"
+ "স্যাটেলাইট SOS উপলভ্য নেই"
+ "এই দেশে বা অঞ্চলে স্যাটেলাইট SOS উপলভ্য আছে কিনা দেখতে, লোকেশন সেটিংস চালু করুন"
+ "\'স্যাটেলাইট মেসেজিং\' ফিচার উপলভ্য"
+ "কোনও মোবাইল বা ওয়াই-ফাই নেটওয়ার্ক না থাকলে, স্যাটেলাইটের মাধ্যমে মেসেজ করতে পারবেন। Google Messages অবশ্যই আপনার ডিফল্ট মেসেজিং অ্যাপ হতে হবে।"
+ "\'স্যাটেলাইট মেসেজিং\' ফিচার কাজ করে না"
+ "এই ডিভাইসে \'স্যাটেলাইট মেসেজিং\' ফিচার কাজ করে না"
+ "\'স্যাটেলাইট মেসেজিং\' ফিচার সেট আপ করা নেই"
+ "আপনার ডিভাইসে ইন্টারনেট কানেকশন আছে কিনা দেখে নিন এবং আবার সেটআপ করার চেষ্টা করুন"
+ "\'স্যাটেলাইট মেসেজিং\' ফিচার উপলভ্য নেই"
+ "এই দেশে বা অঞ্চলে \'স্যাটেলাইট মেসেজিং\' ফিচার উপলভ্য নেই"
+ "\'স্যাটেলাইট মেসেজিং\' ফিচার সেট আপ করা নেই"
+ "স্যাটেলাইটের সাহায্যে মেসেজ পাঠাতে, আপনার ডিফল্ট মেসেজিং অ্যাপ হিসেবে Google Messages সেট করুন"
+ "\'স্যাটেলাইট মেসেজিং\' ফিচার উপলভ্য নেই"
+ "\'স্যাটেলাইট মেসেজিং\' ফিচার এই দেশে বা অঞ্চলে উপলভ্য আছে কিনা দেখতে, লোকেশন সেটিংস চালু করুন"
"\'ফিঙ্গারপ্রিন্ট আনলক\' আবার সেট-আপ করুন"
"%s আর শনাক্ত করা যাবে না।"
"%1$s ও %2$s আর শনাক্ত করা যাবে না।"
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index 266dee2b984a5a7ea5ab06538817914053e05aef..202afdeb943846d36b959117021fcb017dd8aad6 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -613,6 +613,10 @@
"Dozvolite aplikaciji da odredi relativni položaj između uređaja ultra širokog opsega u blizini"
"stupanje u interakciju s WiFi uređajima u blizini"
"Dozvoljava aplikaciji da se oglašava, povezuje i određuje relativni položaj WiFi uređaja u blizini"
+
+
+
+
"Informacije o preferiranoj usluzi plaćanja putem NFC-a"
"Dozvoljava aplikaciji da dobije informacije o preferiranoj usluzi plaćanja putem NFC-a kao što su registrirana pomagala i odredište rute."
"upravljanje NFC-om"
@@ -2432,54 +2436,30 @@
"Uključi"
"Nazad"
"Na čekanju…"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "Hitna pomoć putem satelita je sada dostupna"
+ "Možete razmjenjivati poruke s hitnim službama ako nemate mobilnu ili WiFi mrežu. Google Messages mora biti zadana aplikacija za razmjenu poruka."
+ "Hitna pomoć putem satelita nije podržana"
+ "Hitna pomoć putem satelita nije podržana na uređaju"
+ "Hitna pomoć putem satelita nije postavljena"
+ "Provjerite jeste li povezani s internetom i ponovo pokušajte postaviti uslugu"
+ "Hitna pomoć putem satelita nije dostupna"
+ "Hitna pomoć putem satelita trenutno nije dostupna u ovoj zemlji ili regiji"
+ "Hitna pomoć putem satelita nije postavljena"
+ "Da razmjenjujete poruke putem satelita, postavite Google Messages kao zadanu aplikaciju za razmjenu poruka"
+ "Hitna pomoć putem satelita nije dostupna"
+ "Da provjerite je li hitna pomoć putem satelita dostupna u vašoj zemlji ili regiji, uključite postavke lokacije"
+ "Satelitska razmjena poruka je dostupna"
+ "Možete razmjenjivati poruke putem satelita ako nemate mobilnu ili WiFi mrežu. Google Messages mora biti zadana aplikacija za razmjenu poruka."
+ "Satelitska razmjena poruka nije podržana"
+ "Satelitska razmjena poruka nije podržana na uređaju"
+ "Satelitska razmjena poruka nije postavljena"
+ "Provjerite jeste li povezani s internetom i ponovo pokušajte postaviti uslugu"
+ "Satelitska razmjena poruka nije dostupna"
+ "Satelitska razmjena poruka nije dostupna u ovoj zemlji ili regiji"
+ "Satelitska razmjena poruka nije postavljena"
+ "Da razmjenjujete poruke putem satelita, postavite Google Messages kao zadanu aplikaciju za razmjenu poruka"
+ "Satelitska razmjena poruka nije dostupna"
+ "Da provjerite je li satelitska razmjena poruka dostupna u vašoj zemlji ili regiji, uključite postavke lokacije"
"Ponovo postavite otključavanje otiskom prsta"
"%s se više ne može prepoznati."
"%1$s i %2$s se više ne mogu prepoznati."
@@ -2489,7 +2469,7 @@
"Vaš model lica se više ne može prepoznati. Ponovo postavite otključavanje licem."
"Postavite"
"Ne sada"
- "Alarm za: %s"
+ "Alarm za korisnika %s"
"Prebaci na drugog korisnika"
"Isključi zvuk"
"Dodirnite da isključite zvuk"
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 691126bb58ba1e6b0375892eab7beb8402363666..8b28cd7891c846cde2ebc193fee029b35911019a 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -613,6 +613,10 @@
"Permet que l\'aplicació determini la posició relativa entre els dispositius de banda ultraampla propers"
"interaccionar amb els dispositius Wi‑Fi propers"
"Permet que l\'aplicació s\'anunciï i es connecti als dispositius Wi‑Fi propers, i en determini la posició relativa"
+
+
+
+
"Informació preferent sobre el servei de pagament per NFC"
"Permet que l\'aplicació obtingui informació preferent sobre el servei de pagament per NFC, com ara complements registrats i destinacions de rutes."
"controlar Comunicació de camp proper (NFC)"
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index f6ee489802a9fd75e3c1deaceea57c04d4716d30..f3a020bbfce48e0ea55d6d38a43b18accabd5a1d 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -614,6 +614,10 @@
"Aplikace bude moci zjišťovat vzájemnou pozici mezi ultra-širokopásmovými zařízeními v okolí"
"interakce se zařízeními Wi-Fi v okolí"
"Umožňuje aplikaci inzerovat, připojovat se a odhadovat relativní polohu zařízení Wi-Fi v okolí"
+
+
+
+
"Informace o preferované platební službě NFC"
"Umožňuje aplikaci získat informace o preferované platební službě NFC, například o registrovaných pomůckách a cíli směrování."
"ovládání technologie NFC"
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index a861e3acfb231da475dbe2078517c5c0b8241945..b481682b044878ca303ac0740ec248cb9da99bef 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -612,6 +612,10 @@
"Tillad, at appen fastlægger den relative position mellem UWB-enheder (Ultra-Wideband) i nærheden"
"interagere med Wi‑Fi-enheder i nærheden"
"Giver appen tilladelse til at informere om, oprette forbindelse til og fastslå den relative placering af Wi‑Fi-enheder i nærheden"
+
+
+
+
"Foretrukne oplysninger vedrørende NFC-betalingstjeneste"
"Tillader, at appen får foretrukne oplysninger vedrørende NFC-betalingstjeneste, f.eks. registrerede hjælpemidler og rutedestinationer."
"administrere Near Field Communication"
diff --git a/core/res/res/values-de-feminine/strings.xml b/core/res/res/values-de-feminine/strings.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ef7f3bb8d1931adebf8c5576086948a4a7944d59
--- /dev/null
+++ b/core/res/res/values-de-feminine/strings.xml
@@ -0,0 +1,24 @@
+
+
+
+
+ "Eigentümerin"
+
diff --git a/core/res/res/values-de-masculine/strings.xml b/core/res/res/values-de-masculine/strings.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f8c46e7fb174a31b2d3b6ebcb4b1e6948dc8cbc9
--- /dev/null
+++ b/core/res/res/values-de-masculine/strings.xml
@@ -0,0 +1,24 @@
+
+
+
+
+ "Eigentümer"
+
diff --git a/core/res/res/values-de-neuter/strings.xml b/core/res/res/values-de-neuter/strings.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f8c46e7fb174a31b2d3b6ebcb4b1e6948dc8cbc9
--- /dev/null
+++ b/core/res/res/values-de-neuter/strings.xml
@@ -0,0 +1,24 @@
+
+
+
+
+ "Eigentümer"
+
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 58c4c5e93ef123b8687a307ff1ef0fef8d75b358..64afb5adffc42197c28c44fb6c7d5df26198a32e 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -612,6 +612,10 @@
"Ermöglicht der App, die relative Distanz zwischen Ultrabreitband-Geräten in der Nähe zu bestimmen"
"Mit WLAN-Geräten in der Nähe interagieren"
"Erlaubt der App, Inhalte an WLAN-Geräte in der Nähe zu senden, sich mit ihnen zu verbinden und ihre relative Position zu ermitteln"
+
+
+
+
"Informationen zum bevorzugten NFC-Zahlungsdienst"
"Ermöglicht der App, Informationen zum bevorzugten NFC-Zahlungsdienst abzurufen, etwa registrierte Hilfsmittel oder das Routenziel."
"Nahfeldkommunikation steuern"
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 3a32c528d72fb236a6eb93ac4c60e9c8816f4c8e..4ad85d97201a8ee4f9ccc55326fe98536eaeea35 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -612,6 +612,10 @@
"Επιτρέψτε στην εφαρμογή να προσδιορίζει τη σχετική θέση μεταξύ κοντινών συσκευών Ultra-Wideband"
"αλληλεπίδραση με κοντινές συσκευές Wi‑Fi"
"Επιτρέπει στην εφαρμογή: προβολή διαφημίσεων, σύνδεση και καθορισμό της σχετικής τοποθεσίας των κοντινών συσκευών Wi‑Fi"
+
+
+
+
"Πληροφορίες προτιμώμενης υπηρεσίας πληρωμών NFC"
"Επιτρέπει στην εφαρμογή να λαμβάνει πληροφορίες προτιμώμενης υπηρεσίας πληρωμής NFC, όπως καταχωρημένα βοηθήματα και προορισμό διαδρομής."
"ελέγχει την Επικοινωνία κοντινού πεδίου (FNC)"
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 84cc4095457dcf99e5c463fba38d44531a6349fd..a82b567a087e683c198c479e3f29c027958aad7d 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -612,6 +612,10 @@
"Allow the app to determine relative position between nearby ultra-wideband devices"
"interact with nearby Wi‑Fi devices"
"Allows the app to advertise, connect and determine the relative position of nearby Wi‑Fi devices"
+
+
+
+
"Preferred NFC payment service information"
"Allows the app to get preferred NFC payment service information, such as registered aids and route destination."
"control Near-Field Communication"
@@ -2431,54 +2435,30 @@
"Turn on"
"Go back"
"Pending…"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "Satellite SOS is now available"
+ "You can message emergency services if there\'s no mobile or Wi-Fi network. Google Messages must be your default messaging app."
+ "Satellite SOS isn\'t supported"
+ "Satellite SOS isn\'t supported on this device"
+ "Satellite SOS isn\'t set up"
+ "Make sure that you\'re connected to the Internet and try setup again"
+ "Satellite SOS isn\'t available"
+ "Satellite SOS isn\'t available in this country or region"
+ "Satellite SOS not set up"
+ "To message by satellite, set Google Messages as your default messaging app"
+ "Satellite SOS isn\'t available"
+ "To check if satellite SOS is available in this country or region, turn on location settings"
+ "Satellite messaging available"
+ "You can message by satellite if there\'s no mobile or Wi-Fi network. Google Messages must be your default messaging app."
+ "Satellite messaging not supported"
+ "Satellite messaging isn\'t supported on this device"
+ "Satellite messaging not set up"
+ "Make sure that you\'re connected to the Internet and try setup again"
+ "Satellite messaging not available"
+ "Satellite messaging isn\'t available in this country or region"
+ "Satellite messaging not set up"
+ "To message by satellite, set Google Messages as your default messaging app"
+ "Satellite messaging not available"
+ "To check if satellite messaging is available in this country or region, turn on location settings"
"Set up Fingerprint Unlock again"
"%s can no longer be recognised."
"%1$s and %2$s can no longer be recognised."
@@ -2488,7 +2468,7 @@
"Your face model can no longer be recognised. Set up Face Unlock again."
"Set up"
"Not now"
- "Alarm for: %s"
+ "Alarm for %s"
"Switch user"
"Mute"
"Tap to mute sound"
diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml
index 42250049636a96da3694c6a7dae0621c3368d35d..b09a79a63039bc052898640729fd8e90a5d9413b 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -612,6 +612,8 @@
"Allow the app to determine relative position between nearby Ultra-Wideband devices"
"interact with nearby Wi‑Fi devices"
"Allows the app to advertise, connect, and determine the relative position of nearby Wi‑Fi devices"
+ "determine relative position between nearby devices"
+ "Allow the app to determine relative position between nearby devices"
"Preferred NFC Payment Service Information"
"Allows the app to get preferred nfc payment service information like registered aids and route destination."
"control Near Field Communication"
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index a80d0674d2651fcce7e96d77d472b71a3145b489..bf3b985ae6e84dfe33ff84ef0993851639840065 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -612,6 +612,10 @@
"Allow the app to determine relative position between nearby ultra-wideband devices"
"interact with nearby Wi‑Fi devices"
"Allows the app to advertise, connect and determine the relative position of nearby Wi‑Fi devices"
+
+
+
+
"Preferred NFC payment service information"
"Allows the app to get preferred NFC payment service information, such as registered aids and route destination."
"control Near-Field Communication"
@@ -2431,54 +2435,30 @@
"Turn on"
"Go back"
"Pending…"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "Satellite SOS is now available"
+ "You can message emergency services if there\'s no mobile or Wi-Fi network. Google Messages must be your default messaging app."
+ "Satellite SOS isn\'t supported"
+ "Satellite SOS isn\'t supported on this device"
+ "Satellite SOS isn\'t set up"
+ "Make sure that you\'re connected to the Internet and try setup again"
+ "Satellite SOS isn\'t available"
+ "Satellite SOS isn\'t available in this country or region"
+ "Satellite SOS not set up"
+ "To message by satellite, set Google Messages as your default messaging app"
+ "Satellite SOS isn\'t available"
+ "To check if satellite SOS is available in this country or region, turn on location settings"
+ "Satellite messaging available"
+ "You can message by satellite if there\'s no mobile or Wi-Fi network. Google Messages must be your default messaging app."
+ "Satellite messaging not supported"
+ "Satellite messaging isn\'t supported on this device"
+ "Satellite messaging not set up"
+ "Make sure that you\'re connected to the Internet and try setup again"
+ "Satellite messaging not available"
+ "Satellite messaging isn\'t available in this country or region"
+ "Satellite messaging not set up"
+ "To message by satellite, set Google Messages as your default messaging app"
+ "Satellite messaging not available"
+ "To check if satellite messaging is available in this country or region, turn on location settings"
"Set up Fingerprint Unlock again"
"%s can no longer be recognised."
"%1$s and %2$s can no longer be recognised."
@@ -2488,7 +2468,7 @@
"Your face model can no longer be recognised. Set up Face Unlock again."
"Set up"
"Not now"
- "Alarm for: %s"
+ "Alarm for %s"
"Switch user"
"Mute"
"Tap to mute sound"
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index c123499b6883a2fdc3eace72762bda5f8f152681..5c9c521487509cf911a4981149ed275c55ea180c 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -612,6 +612,10 @@
"Allow the app to determine relative position between nearby ultra-wideband devices"
"interact with nearby Wi‑Fi devices"
"Allows the app to advertise, connect and determine the relative position of nearby Wi‑Fi devices"
+
+
+
+
"Preferred NFC payment service information"
"Allows the app to get preferred NFC payment service information, such as registered aids and route destination."
"control Near-Field Communication"
@@ -2431,54 +2435,30 @@
"Turn on"
"Go back"
"Pending…"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "Satellite SOS is now available"
+ "You can message emergency services if there\'s no mobile or Wi-Fi network. Google Messages must be your default messaging app."
+ "Satellite SOS isn\'t supported"
+ "Satellite SOS isn\'t supported on this device"
+ "Satellite SOS isn\'t set up"
+ "Make sure that you\'re connected to the Internet and try setup again"
+ "Satellite SOS isn\'t available"
+ "Satellite SOS isn\'t available in this country or region"
+ "Satellite SOS not set up"
+ "To message by satellite, set Google Messages as your default messaging app"
+ "Satellite SOS isn\'t available"
+ "To check if satellite SOS is available in this country or region, turn on location settings"
+ "Satellite messaging available"
+ "You can message by satellite if there\'s no mobile or Wi-Fi network. Google Messages must be your default messaging app."
+ "Satellite messaging not supported"
+ "Satellite messaging isn\'t supported on this device"
+ "Satellite messaging not set up"
+ "Make sure that you\'re connected to the Internet and try setup again"
+ "Satellite messaging not available"
+ "Satellite messaging isn\'t available in this country or region"
+ "Satellite messaging not set up"
+ "To message by satellite, set Google Messages as your default messaging app"
+ "Satellite messaging not available"
+ "To check if satellite messaging is available in this country or region, turn on location settings"
"Set up Fingerprint Unlock again"
"%s can no longer be recognised."
"%1$s and %2$s can no longer be recognised."
@@ -2488,7 +2468,7 @@
"Your face model can no longer be recognised. Set up Face Unlock again."
"Set up"
"Not now"
- "Alarm for: %s"
+ "Alarm for %s"
"Switch user"
"Mute"
"Tap to mute sound"
diff --git a/core/res/res/values-es-rUS-feminine/strings.xml b/core/res/res/values-es-rUS-feminine/strings.xml
new file mode 100644
index 0000000000000000000000000000000000000000..bf181d022f9ade0dbf29addf8cb2582c8bec7d4a
--- /dev/null
+++ b/core/res/res/values-es-rUS-feminine/strings.xml
@@ -0,0 +1,24 @@
+
+
+
+
+ "Propietaria"
+
diff --git a/core/res/res/values-es-rUS-masculine/strings.xml b/core/res/res/values-es-rUS-masculine/strings.xml
new file mode 100644
index 0000000000000000000000000000000000000000..4b67970f668b530cd7556f3760d00d8fbe7bbeb4
--- /dev/null
+++ b/core/res/res/values-es-rUS-masculine/strings.xml
@@ -0,0 +1,24 @@
+
+
+
+
+ "Propietario"
+
diff --git a/core/res/res/values-es-rUS-neuter/strings.xml b/core/res/res/values-es-rUS-neuter/strings.xml
new file mode 100644
index 0000000000000000000000000000000000000000..4b67970f668b530cd7556f3760d00d8fbe7bbeb4
--- /dev/null
+++ b/core/res/res/values-es-rUS-neuter/strings.xml
@@ -0,0 +1,24 @@
+
+
+
+
+ "Propietario"
+
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 26b4dfa4f2f4be96d31d39feeea47a8252100d53..ab6f6ce07c1d3ac12f7769bee91f8ed1149b7244 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -613,6 +613,10 @@
"Permite que la app determine la posición relativa con dispositivos Ultra Wideband cercanos"
"interactuar con dispositivos Wi-Fi cercanos"
"Permite que la app muestre anuncios, se conecte y determine la posición relativa de los dispositivos Wi-Fi cercanos"
+
+
+
+
"Información sobre servicio de pago NFC preferido"
"Permite que la app reciba información del servicio de pago NFC preferido, como el servicio de asistencia registrado y el destino de la ruta."
"controlar la Transmisión de datos en proximidad"
@@ -2432,54 +2436,30 @@
"Activar"
"Atrás"
"Pendiente…"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "La función SOS por satélite ya está disponible"
+ "Puedes enviar mensajes a los servicios de emergencia si no hay una red móvil o Wi-Fi. Tu app de mensajería predeterminada debe ser Mensajes de Google."
+ "No se admite la función SOS por satélite"
+ "Este dispositivo no admite la función SOS por satélite"
+ "No se configuró la función SOS por satélite"
+ "Asegúrate de tener conexión a Internet y vuelve a intentar la configuración"
+ "La función SOS por satélite no está disponible"
+ "La función SOS por satélite no está disponible en este país o región"
+ "No se configuró la función SOS por satélite"
+ "Para enviar mensajes por satélite, establece Mensajes de Google como tu app de mensajería predeterminada"
+ "La función SOS por satélite no está disponible"
+ "Para verificar si la función SOS por satélite está disponible en este país o región, activa la configuración de ubicación"
+ "La Mensajería satelital está disponible"
+ "Puedes enviar mensajes por satélite si no hay una red móvil o Wi-Fi. Tu app de mensajería predeterminada debe ser Mensajes de Google."
+ "No se admite la Mensajería satelital"
+ "Este dispositivo no admite la Mensajería satelital"
+ "No se configuró la Mensajería satelital"
+ "Asegúrate de tener conexión a Internet y vuelve a intentar la configuración"
+ "La Mensajería satelital no disponible"
+ "La Mensajería satelital no está disponible en este país o región"
+ "No se configuró la Mensajería satelital"
+ "Para enviar mensajes por satélite, establece Mensajes de Google como tu app de mensajería predeterminada"
+ "La Mensajería satelital no disponible"
+ "Para verificar si la Mensajería satelital está disponible en este país o región, activa la configuración de ubicación"
"Vuelve a configurar el Desbloqueo con huellas dactilares"
"Ya no se puede reconocer %s."
"Ya no se pueden reconocer %1$s y %2$s."
@@ -2489,7 +2469,7 @@
"Ya no se puede reconocer tu modelo de rostro. Vuelve a configurar el Desbloqueo facial."
"Configurar"
"Ahora no"
- "Alarma para: %s"
+ "Alarma para %s"
"Cambiar de usuario"
"Silenciar"
"Presiona para silenciar el sonido"
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 166e2dac1366d45382fe30e9411b1fb145294bfc..23e1ae63573029e4740140f6768b9621656b1bc7 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -613,6 +613,10 @@
"Permite que la aplicación determine la posición relativa de los dispositivos de banda ultraancha cercanos"
"interactuar con dispositivos Wi-Fi cercanos"
"Permite a la aplicación emitir y conectarse a dispositivos Wi-Fi cercanos y determinar su posición relativa"
+
+
+
+
"Información sobre el servicio de pago por NFC preferido"
"Permite que la aplicación obtenga información sobre el servicio de pago por NFC preferido, como identificadores de aplicación registrados y destinos de rutas."
"controlar Comunicación de campo cercano (NFC)"
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index fed97a191c87aca3e79b5ec422afd507d22c2602..d22c93b30ac9c773f7d5c190bc9b8f710d21802d 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -612,6 +612,10 @@
"Võimaldab rakendusel määrata lähedalasuvate ülilairibaühendust kasutavate seadmete suhtelise kauguse üksteisest"
"Läheduses olevate WiFi-seadmetega suhtlemine"
"Lubab rakendusel läheduses olevatele WiFi-seadmetele reklaamida, nendega ühenduse luua ja määrata nende suhteline asend"
+
+
+
+
"Eelistatud NFC-makseteenuse teave"
"Võimaldab rakendusel hankida eelistatud NFC-makseteenuse teavet (nt registreeritud abi ja marsruudi sihtkoht)."
"lähiväljaside juhtimine"
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index 26e41140f3915e9befd4e87ff97ca5c64e9b6ea9..914dfb72c06e3092b1292ba40cc130e8096497c2 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -612,6 +612,10 @@
"Banda ultrazabala darabilten inguruko gailuen arteko distantzia erlatiboa zehazteko baimena ematen dio aplikazioari"
"inguruko wifi-gailuekin interakzioan jardun"
"Inguruko wifi-gailuetan iragartzeko, haiekin konektatzeko eta haien kokapena zehazteko baimena ematen dio aplikazioari"
+
+
+
+
"NFC bidezko ordainketa-zerbitzu lehenetsiari buruzko informazioa"
"NFC bidezko ordainketa-zerbitzu lehenetsiari buruzko informazioa jasotzeko baimena ematen dio aplikazioari, hala nola erregistratutako laguntzaileak eta ibilbidearen helmuga."
"kontrolatu Near Field Communication komunikazioa"
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index a8659eb289de453d55e4cfa0491f5c2af3077342..c3e4b4680752f9abff38391b97ea6883d2cd57da 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -612,6 +612,10 @@
"به برنامه اجازه داده میشود موقعیت نسبی بین دستگاههای «فراپهنباند» اطراف را مشخص کند"
"برقراری تعامل با دستگاههای Wi-Fi اطراف"
"به برنامه اجازه میدهد در دستگاههای Wi-Fi اطراف تبلیغ کند، به آنها متصل شود، و موقعیت نسبی آنها را تشخیص دهد"
+
+
+
+
"اطلاعات ترجیحی سرویس پرداخت NFC"
"به برنامه اجازه میدهد اطلاعات ترجیحی سرویس پرداخت NFC، مانند کمکهای ثبتشده و مقصد مسیر را دریافت کند."
"کنترل ارتباط راه نزدیک"
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 1f4372abb677de0cc6285369067937dfcf003f34..fb7c4fed3f476781633e71d3f03be1fa8da7026b 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -612,6 +612,10 @@
"Sallii sovelluksen määrittää UVB-taajuutta käyttävien laitteiden sijainnin suhteessa toisiinsa"
"käyttää lähellä olevia Wi-Fi-laitteita"
"Sallii sovelluksen ilmoittaa ja määrittää lähellä olevien Wi-Fi-laitteiden suhteellisen sijainnin sekä yhdistää niihin"
+
+
+
+
"Ensisijaiset NFC-maksupalvelutiedot"
"Sallii sovelluksen noutaa tietoja rekisteröidyistä sovellustunnuksista, maksureitin kohteesta ja muita ensisijaisia NFC-maksupalvelutietoja."
"hallitse Near Field Communication -tunnistusta"
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index f7f1474fca7b17a12f8c395029750abdfc1bf7da..18ef10995e90bebe0935bb11757ed39e33b1c9da 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -613,6 +613,10 @@
"Autorisez l\'appli à déterminer la position relative entre des appareils à bande ultralarge à proximité"
"interagir avec les appareils Wi-Fi à proximité"
"Permet à l\'appli de diffuser des annonces, de se connecter et de déterminer la position relative des appareils Wi-Fi à proximité"
+
+
+
+
"Information sur le service préféré de paiement CCP"
"Permet à l\'appli d\'obtenir de l\'information sur le service préféré de paiement CCP comme les aides enregistrées et la route de destination."
"gérer la communication en champ proche"
@@ -2432,54 +2436,30 @@
"Activer"
"Retour"
"En attente…"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "SOS par satellite est maintenant accessible"
+ "Vous pouvez envoyer un message aux services d\'urgence s\'il n\'y a pas de réseau mobile ou Wi-Fi. Messages de Google doit être votre appli de messagerie par défaut."
+ "SOS par satellite n\'est pas prise en charge"
+ "SOS par satellite n\'est pas prise en charge sur cet appareil"
+ "SOS par satellite n\'est pas configurée"
+ "Assurez-vous que vous êtes connecté à Internet et réessayez d\'effectuer la configuration"
+ "SOS par satellite n\'est pas accessible"
+ "SOS par satellite n\'est pas accessible dans ce pays ou cette région"
+ "SOS par satellite n\'est pas configurée"
+ "Pour envoyer des messages par satellite, définissez Messages de Google comme appli de messagerie par défaut"
+ "SOS par satellite n\'est pas accessible"
+ "Pour vérifier si SOS par satellite est accessible dans ce pays ou cette région, activez les paramètres de localisation"
+ "La messagerie par satellite est accessible"
+ "Vous pouvez envoyer des messages par satellite s\'il n\'y a pas de réseau mobile ou Wi-Fi. Messages de Google doit être votre appli de messagerie par défaut."
+ "La messagerie par satellite n\'est pas prise en charge"
+ "La messagerie par satellite n\'est pas prise en charge sur cet appareil"
+ "La messagerie par satellite n\'est pas configurée"
+ "Assurez-vous que vous êtes connecté à Internet et réessayez d\'effectuer la configuration"
+ "La messagerie par satellite n\'est pas accessible"
+ "La messagerie par satellite n\'est pas accessible dans ce pays ou cette région"
+ "La messagerie par satellite n\'est pas configurée"
+ "Pour envoyer des messages par satellite, définissez Messages de Google comme appli de messagerie par défaut"
+ "La messagerie par satellite n\'est pas accessible"
+ "Pour vérifier si la messagerie par satellite est accessible dans ce pays ou cette région, activez les paramètres de localisation"
"Configurer le Déverrouillage par empreinte digitale à nouveau"
"L\'empreinte digitale %s ne peut plus être reconnue."
"Les empreintes digitales %1$s et %2$s ne peuvent plus être reconnues."
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index bed2927867c4b26e57ec4c552cdf9f975c186763..bd064d1dc61e55c21c59b0fd5a7dfa153a7de827 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -613,6 +613,10 @@
"Autoriser l\'appli à déterminer la position relative entre des appareils ultra-wideband à proximité"
"interagir avec les appareils Wi-Fi à proximité"
"Permet à l\'appli de déterminer la position approximative des appareils Wi‑Fi à proximité, de les afficher et de s\'y connecter"
+
+
+
+
"Informations sur le service de paiement NFC préféré"
"Permet à l\'application d\'obtenir des informations sur le service de paiement NFC préféré, y compris les ID d\'applications et les destinations de routage enregistrés."
"contrôler la communication en champ proche"
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index 532c078801001708bb2baa21900e8c1a657d2330..292a952b1d46b617f8aa2bcf6dc623d630f735ec 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -612,6 +612,10 @@
"Permite que a aplicación determine a posición relativa entre os dispositivos próximos que usen banda ultralarga"
"interactuar con dispositivos wifi próximos"
"Permítelle á aplicación enviar anuncios e conectarse a dispositivos wifi próximos, e determinar a súa posición relativa"
+
+
+
+
"Información do servizo de pagos de NFC preferido"
"Permite que a aplicación obteña información do servizo de pagos de NFC preferido, como as axudas rexistradas e o destino da ruta."
"controlar Near Field Communication"
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index 7e36c616e81602d70ee0137d8d0c00dcd54f1669..70454a307791117c4528b6179c92ae774fbedf5e 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -612,6 +612,10 @@
"ઍપને નજીકના અલ્ટ્રા-વાઇડબૅન્ડ ડિવાઇસની વચ્ચેનું સંબંધિત અંતર નક્કી કરવાની મંજૂરી આપો"
"નજીકના વાઇ-ફાઇ ડિવાઇસ સાથે ક્રિયાપ્રતિક્રિયા કરો"
"ઍપને નજીકના વાઇ-ફાઇ ડિવાઇસની માહિતી બતાવવાની, તેની સાથે કનેક્ટ કરવાની અને તેની સંબંધિત સ્થિતિ નક્કી કરવાની મંજૂરી આપો"
+
+
+
+
"પસંદગીની NFC ચુકવણીની સેવા વિશે માહિતી"
"આ મંજૂરીને આપવાથી, ઍપ તમારી પસંદગીની NFC ચુકવણીની સેવા વિશે માહિતી મેળવી શકે છે, જેમ કે રજિસ્ટર થયેલી સહાય અને નિર્ધારિત સ્થાન."
"નિઅર ફીલ્ડ કમ્યુનિકેશન નિયંત્રિત કરો"
@@ -1663,7 +1667,7 @@
"હેડફોન"
"USB"
"સિસ્ટમ"
- "બ્લૂટૂથ ઑડિઓ"
+ "બ્લૂટૂથ ઑડિયો"
"વાયરલેસ ડિસ્પ્લે"
"કાસ્ટ કરો"
"ઉપકરણ સાથે કનેક્ટ કરો"
@@ -2058,7 +2062,7 @@
"કોન્ફરન્સ કૉલ"
"ટૂલટિપ"
"રમતો"
- "સંગીત અને ઑડિયો"
+ "મ્યુઝિક અને ઑડિયો"
"મૂવી અને વીડિઓ"
"ફોટો અને છબીઓ"
"સામાજિક અને સંચાર"
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 38e79b1988dc30b5c2c9de3f2b452dc61ee836e7..5422f1befc40224180afb9be1f732ba59c34bdf7 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -612,6 +612,10 @@
"ऐप्लिकेशन को आस-पास मौजूद Ultra-Wideband डिवाइसों के बीच की दूरी का पता लगाने की अनुमति दें"
"आस-पास मौजूद वाई-फ़ाई डिवाइसों से इंटरैक्ट करें"
"इससे, ऐप्लिकेशन आस-पास मौजूद वाई-फ़ाई डिवाइसों की जानकारी दिखा पाएगा, उनसे कनेक्ट कर पाएगा, और उनकी दूरी पता लगा पाएगा"
+
+
+
+
"NFC का इस्तेमाल करने वाली पैसे चुकाने की पसंदीदा सेवा की जानकारी"
"अगर ऐप्लिकेशन को अनुमति दी जाती है, तो वह पैसे चुकाने की आपकी उस पसंदीदा सेवा के बारे में जानकारी पा सकता है जो NFC का इस्तेमाल करती है. इसमें रजिस्टर किए गए डिवाइस और उनके आउटपुट के रूट जैसी जानकारी शामिल होती है."
"नियर फ़ील्ड कम्यूनिकेशन नियंत्रित करें"
@@ -2431,54 +2435,30 @@
"चालू करें"
"रद्द करें"
"प्रोसेस जारी है..."
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "सैटलाइट एसओएस की सुविधा अब उपलब्ध है"
+ "मोबाइल या वाई-फ़ाई नेटवर्क न होने पर भी, आपातकालीन सेवाओं को मैसेज भेजा जा सकता है. इसके लिए, आपको Google Messages को अपने डिवाइस के डिफ़ॉल्ट मैसेजिंग ऐप्लिकेशन के तौर पर सेट करना होगा."
+ "सैटलाइट एसओएस की सुविधा उपलब्ध नहीं है"
+ "इस डिवाइस पर सैटलाइट एसओएस की सुविधा काम नहीं करती"
+ "सैटलाइट एसओएस सेट अप नहीं किया गया है"
+ "पक्का करें कि आपका डिवाइस, इंटरनेट से कनेक्ट है या नहीं. इसके बाद, फिर से सेटअप करने की कोशिश करें"
+ "सैटलाइट एसओएस की सुविधा उपलब्ध नहीं है"
+ "इस देश या इलाके में सैटलाइट एसओएस की सुविधा उपलब्ध नहीं है"
+ "सैटलाइट एसओएस की सुविधा सेट अप नहीं की गई"
+ "सैटलाइट से मैसेज भेजने के लिए, Google Messages को डिफ़ॉल्ट मैसेजिंग ऐप्लिकेशन के तौर पर सेट करें"
+ "सैटलाइट एसओएस की सुविधा उपलब्ध नहीं है"
+ "जगह की जानकारी की सेटिंग चालू करें. इससे यह देखा जा सकता है कि इस देश या इलाके में सैटलाइट एसओएस की सुविधा उपलब्ध है या नहीं"
+ "सैटलाइट के ज़रिए मैसेज भेजने की सुविधा उपलब्ध है"
+ "मोबाइल या वाई-फ़ाई नेटवर्क न होने पर भी, सैटलाइट के ज़रिए मैसेज भेजा जा सकता है. इसके लिए, आपको Google Messages को अपने डिवाइस के डिफ़ॉल्ट मैसेजिंग ऐप्लिकेशन के तौर पर सेट करना होगा."
+ "सैटलाइट के ज़रिए मैसेज भेजने की सुविधा काम नहीं करती"
+ "इस डिवाइस पर सैटलाइट के ज़रिए मैसेज भेजने की सुविधा काम नहीं करती"
+ "सैटलाइट के ज़रिए मैसेज भेजने की सुविधा सेट अप नहीं की गई"
+ "पक्का करें कि आपका डिवाइस, इंटरनेट से कनेक्ट है या नहीं. इसके बाद, फिर से सेटअप करने की कोशिश करें"
+ "सैटलाइट के ज़रिए मैसेज भेजने की सुविधा उपलब्ध नहीं है"
+ "इस देश या इलाके में सैटलाइट के ज़रिए मैसेज भेजने की सुविधा उपलब्ध नहीं है"
+ "सैटलाइट के ज़रिए मैसेज भेजने की सुविधा सेट अप नहीं की गई"
+ "सैटलाइट से मैसेज भेजने के लिए, Google Messages को डिफ़ॉल्ट मैसेजिंग ऐप्लिकेशन के तौर पर सेट करें"
+ "सैटलाइट के ज़रिए मैसेज भेजने की सुविधा उपलब्ध नहीं है"
+ "जगह की जानकारी की सेटिंग चालू करें. इससे यह देखा जा सकता है कि इस देश या इलाके में सैटलाइट के ज़रिए मैसेज भेजने की सुविधा उपलब्ध है या नहीं"
"फ़िंगरप्रिंट अनलॉक की सुविधा दोबारा सेट अप करें"
"अब %s की पहचान नहीं की जा सकती."
"अब %1$s और %2$s की पहचान नहीं की जा सकती."
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 90e228e65afaa0fc97678d2989de7d049da9cc90..0594788fa9ceada00faac651661ca9d2ce2b037f 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -613,6 +613,10 @@
"Dopušta aplikaciji da odredi približni položaj između uređaja u blizini koji upotrebljavaju ultraširokopojasno povezivanje"
"interakcija s Wi-Fi uređajima u blizini"
"Aplikaciji omogućuje oglašavanje, povezivanje i određivanje približnog položaja Wi-Fi uređaja u blizini"
+
+
+
+
"Informacije o preferiranoj usluzi plaćanja NFC"
"Omogućuje aplikaciji primanje informacija o preferiranoj usluzi plaćanja NFC kao što su registrirana pomagala i odredište."
"upravljanje beskontaktnom komunikacijom (NFC)"
@@ -2432,54 +2436,30 @@
"Uključi"
"Natrag"
"Na čekanju..."
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "SOS putem satelita sad je dostupan"
+ "Možete slati poruke hitnim službama ako mobilna ili Wi-Fi mreža nije dostupna. Google poruke moraju biti vaša zadana aplikacija za slanje poruka."
+ "SOS putem satelita nije podržan"
+ "SOS putem satelita nije podržan na ovom uređaju"
+ "SOS putem satelita nije postavljen"
+ "Provjerite jeste li povezani s internetom i pokušajte ponovo s postavljanjem"
+ "SOS putem satelita nije dostupan"
+ "SOS putem satelita nije dostupan u ovoj državi ili regiji"
+ "SOS putem satelita nije postavljen"
+ "Da biste slali poruke putem satelita, postavite Google poruke kao zadanu aplikaciju za slanje poruka"
+ "SOS putem satelita nije dostupan"
+ "Da biste provjerili je li SOS putem satelita dostupan u ovoj državi ili regiji, uključite postavke lokacije"
+ "Slanje poruka putem satelita je dostupno"
+ "Možete slati poruke putem satelita ako mobilna ili Wi-Fi mreža nije dostupna. Google poruke moraju biti vaša zadana aplikacija za slanje poruka."
+ "Slanje poruka putem satelita nije podržano"
+ "Slanje poruka putem satelita nije podržano na ovom uređaju"
+ "Slanje poruka putem satelita nije postavljeno"
+ "Provjerite jeste li povezani s internetom i pokušajte ponovo s postavljanjem"
+ "Slanje poruka putem satelita nije dostupno"
+ "Slanje poruka putem satelita nije dostupno u ovoj državi ili regiji"
+ "Slanje poruka putem satelita nije postavljeno"
+ "Da biste slali poruke putem satelita, postavite Google poruke kao zadanu aplikaciju za slanje poruka"
+ "Slanje poruka putem satelita nije dostupno"
+ "Da biste provjerili je li slanje poruka putem satelita dostupno u ovoj državi ili regiji, uključite postavke lokacije"
"Ponovno postavite otključavanje otiskom prsta"
"%s više se ne prepoznaje."
"%1$s i %2$s više se ne prepoznaju."
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index d5a28f8e21983ceeaf61276a0d6c04c1edbfd43b..8adb234830aac646c9735894c4e47385a3af1f41 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -612,6 +612,10 @@
"Az alkalmazás meghatározhatja a közeli, ultraszélessávú eszközök közötti relatív pozíciót"
"műveletek végrehajtása a közeli Wi‑Fi-eszközökkel"
"Engedélyezi az alkalmazás számára, hogy közzétegye és meghatározza a közeli Wi-Fi-eszközök viszonylagos helyzetét, és csatlakozzon hozzájuk."
+
+
+
+
"Preferált NFC fizetési szolgáltatási információk"
"Lehetővé teszi az alkalmazás számára preferált NFC fizetési szolgáltatási információk (pl. regisztrált alkalmazásazonosítók és útvonali cél) lekérését."
"NFC technológia vezérlése"
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index 14534a7ca2a8187e641cb59b1d859c66dc9577c2..4a16d2f37194c2c2e568af48c8f271298277f652 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -612,6 +612,10 @@
"Թույլատրել հավելվածին որոշել գերլայնաշերտ կապի տեխնոլոգիան աջակցող մոտակա սարքերի միջև հարաբերական դիրքավորումը"
"փոխներգործել մոտակա Wi‑Fi սարքերի հետ"
"Թույլ է տալիս հավելվածին տվյալներ փոխանցել մոտակա Wi‑Fi սարքերին, միանալ դրանց և որոշել դրանց մոտավոր դիրքը։"
+
+
+
+
"Տեղեկություններ NFC վճարային ծառայության մասին"
"Թույլ է տալիս հավելվածին ստանալ նախընտրելի NFC վճարային ծառայության մասին տեղեկություններ (օր․՝ գրանցված լրացուցիչ սարքերի և երթուղու նպատակակետի մասին տվյալներ)։"
"վերահսկել Մոտ Տարածությամբ Հաղորդակցումը"
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 360102f13139dd5308555d23c4a044b4ea6c8b0f..e90137fd761f6645aec9c663dba0338aa83cc93d 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -612,6 +612,10 @@
"Mengizinkan aplikasi menentukan posisi relatif antar-perangkat Ultra-Wideband di sekitar"
"berinteraksi dengan perangkat Wi-Fi di sekitar"
"Mengizinkan aplikasi menampilkan, menghubungkan, dan menentukan posisi relatif perangkat Wi-Fi di sekitar"
+
+
+
+
"Informasi Layanan Pembayaran NFC Pilihan"
"Mengizinkan aplikasi untuk mendapatkan informasi layanan pembayaran NFC pilihan seperti bantuan terdaftar dan tujuan rute."
"kontrol NFC"
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index 9d3e2e42fb119f72f77c126a4c2590514e6c472c..9ca5731ad1eb33887d3c82146b7e844d65ac52f5 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -612,6 +612,10 @@
"Leyfa forritinu að ákvarða fjarlægð milli nálægra tækja með ofurbreiðband"
"eiga í samskiptum við nálæg WiFi-tæki"
"Leyfir forritinu að auglýsa, tengja og áætla staðsetningu nálægra WiFi-tækja"
+
+
+
+
"Upplýsingar um valda NFC-greiðsluþjónustu"
"Gerir forritinu kleift að fá valda NFC-greiðsluþjónustu, svo sem skráða aðstoð og áfangastað leiðar."
"stjórna nándarsamskiptum (NFC)"
@@ -2431,54 +2435,30 @@
"Kveikja"
"Til baka"
"Í bið…"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "Nú er gervihnattar-SOS tiltækt"
+ "Þú getur sent neyðarþjónustu skilaboð, jafnvel þótt farsímakerfi eða WiFi-tenging sé ekki til staðar. Google Messages verður að vera stillt sem sjálfgefið skilaboðaforrit."
+ "Gervihnattar-SOS er ekki stutt"
+ "Gervihnattar-SOS er ekki stutt í þessu tæki"
+ "Gervihnattar-SOS er ekki uppsett"
+ "Gakktu úr skugga um að þú sért með nettengingu og reyndu uppsetningu aftur"
+ "Gervihnattar-SOS er ekki tiltækt"
+ "Gervihnattar-SOS er ekki tiltækt í þessu landi eða landsvæði"
+ "Gervihnattar-SOS er ekki uppsett"
+ "Til að senda skilaboð í gegnum gervihnött skaltu stilla Google Messages sem sjálfgefið skilaboðaforrit"
+ "Gervihnattar-SOS er ekki tiltækt"
+ "Til að athuga hvort gervihnattar-SOS eru tiltæk í þessu landi eða á þessu svæði skaltu kveikja á staðsetningarstillingum"
+ "Skilaboð í gegnum gervihnött eru tiltæk"
+ "Þú getur sent skilaboð um gervihnött ef það er ekkert farsímakerfi eða WiFi-net. Google Messages verður að vera stillt sem sjálfgefið skilaboðaforrit."
+ "Skilaboð í gegnum gervihnött eru ekki studd"
+ "Skilaboð í gegnum gervihnött eru ekki studd í þessu tæki"
+ "Skilaboð í gegnum gervihnött eru ekki uppsett"
+ "Gakktu úr skugga um að þú sért með nettengingu og reyndu uppsetningu aftur"
+ "Skilaboð í gegnum gervihnött eru ekki tiltæk"
+ "Skilaboð í gegnum gervihnött eru ekki tiltæk í þessu landi eða á þessu svæði"
+ "Skilaboð í gegnum gervihnött eru ekki uppsett"
+ "Til að senda skilaboð í gegnum gervihnött skaltu stilla Google Messages sem sjálfgefið skilaboðaforrit"
+ "Skilaboð í gegnum gervihnött eru ekki tiltæk"
+ "Til að athuga hvort skilaboð í gegnum gervihnött eru tiltæk í þessu landi eða á þessu svæði skaltu kveikja á staðsetningarstillingum"
"Setja upp fingrafarskenni aftur"
"Ekki er hægt að bera kennsl á %s lengur."
"Ekki er hægt að bera kennsl á %1$s og %2$s lengur."
@@ -2488,7 +2468,7 @@
"Ekki er hægt að bera kennsl á andlitslíkanið þitt lengur. Settu upp andlitskenni aftur."
"Setja upp"
"Ekki núna"
- "Viðvörun fyrir: %s"
+ "Viðvörun: %s"
"Skipta um notanda"
"Þagga"
"Ýttu til að þagga hljóð"
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index ee7f08db3e51b90b5056d59ebd1293d8953ccd99..ac0e4580b7a051c357597083874a14476be3dc8a 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -613,6 +613,10 @@
"Consenti all\'app di stabilire la posizione relativa tra dispositivi a banda ultralarga nelle vicinanze"
"Interazione con dispositivi Wi-Fi vicini"
"Consente all\'app di trasmettere annunci e connettersi a dispositivi Wi‑Fi vicini e di stabilirne la posizione relativa."
+
+
+
+
"Informazioni del servizio di pagamento NFC preferito"
"Consente all\'app di recuperare informazioni del servizio di pagamento NFC preferito, quali destinazione della route e identificatori applicazione registrati."
"controllo Near Field Communication"
@@ -2489,7 +2493,7 @@
"Il tuo modello del volto non può più essere riconosciuto. Riconfigura lo Sblocco con il Volto."
"Configura"
"Non ora"
- "Sveglia per: %s"
+ "Sveglia per %s"
"Cambia utente"
"Disattiva audio"
"Tocca per disattivare l\'audio"
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index e3f2a7cab5ebce99cdf3e6645cc74024394903b2..386f5318f53a0dac7fe6c1df70f80253ccdedd5c 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -613,6 +613,10 @@
"האפליקציה תזהה את המיקום היחסי בין מכשירים קרובים שמשדרים בטכנולוגיית Ultra Wideband (UWB)"
"אינטראקציה עם מכשירי Wi-Fi בקרבת מקום"
"האפליקציה תוכל לפרסם במכשירי Wi-Fi בקרבת מקום, להתחבר אליהם ולהעריך את המיקום היחסי שלהם"
+
+
+
+
"פרטים על שירות תשלום מועדף ב-NFC"
"מאפשרת לאפליקציה לקבל פרטים על שירות תשלום מועדף ב-NFC, כמו עזרים רשומים ויעד של נתיב."
"שליטה בתקשורת מטווח קצר"
@@ -2432,54 +2436,30 @@
"הפעלה"
"חזרה"
"בהמתנה..."
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "התכונה \"תקשורת לוויינית למצב חירום\" זמינה עכשיו"
+ "אפשר לשלוח הודעות לשירותי החירום כשאין חיבור לרשת סלולרית או לרשת Wi-Fi. חובה להגדיר את Google Messages כאפליקציית ברירת המחדל להודעות."
+ "התכונה \"תקשורת לוויינית למצב חירום\" לא נתמכת"
+ "המכשיר הזה לא תומך בתכונה \"תקשורת לוויינית למצב חירום\""
+ "התכונה \"תקשורת לוויינית למצב חירום\" לא מוגדרת"
+ "צריך לוודא שיש חיבור לאינטרנט ולנסות שוב את תהליך ההגדרה"
+ "התכונה \"תקשורת לוויינית למצב חירום\" לא זמינה"
+ "התכונה \"תקשורת לוויינית למצב חירום\" לא זמינה במדינה הזו או באזור הזה"
+ "התכונה \"תקשורת לוויינית למצב חירום\" לא מוגדרת"
+ "כדי להעביר הודעות באמצעות לוויין, צריך להגדיר את Google Messages כאפליקציית ברירת המחדל להודעות"
+ "התכונה \"תקשורת לוויינית למצב חירום\" לא זמינה"
+ "כדי לבדוק אם התכונה \"תקשורת לוויינית למצב חירום\" זמינה במדינה או באזור שלך, צריך להפעיל את הגדרות המיקום"
+ "התכונה \"העברת הודעות באמצעות לוויין\" זמינה"
+ "כשאין חיבור לרשת סלולרית או לרשת Wi-Fi, אפשר להעביר הודעות בתקשורת לוויינית. חובה להגדיר את Google Messages כאפליקציית ברירת המחדל להודעות."
+ "התכונה \"העברת הודעות באמצעות לוויין\" לא נתמכת"
+ "המכשיר הזה לא תומך בתכונה \"העברת הודעות באמצעות לוויין\""
+ "התכונה \"העברת הודעות באמצעות לוויין\" לא מוגדרת"
+ "צריך לוודא שיש חיבור לאינטרנט ולנסות שוב את תהליך ההגדרה"
+ "התכונה \"העברת הודעות באמצעות לוויין\" לא זמינה"
+ "התכונה \"העברת הודעות באמצעות לוויין\" לא זמינה במדינה הזו או באזור הזה"
+ "התכונה \"העברת הודעות באמצעות לוויין\" לא מוגדרת"
+ "כדי להעביר הודעות באמצעות לוויין, צריך להגדיר את Google Messages כאפליקציית ברירת המחדל להודעות"
+ "התכונה \"העברת הודעות באמצעות לוויין\" לא זמינה"
+ "כדי לבדוק אם התכונה \"העברת הודעות באמצעות לוויין\" זמינה במדינה או באזור שלך, צריך להפעיל את הגדרות המיקום"
"הגדרה חוזרת של \'ביטול הנעילה בטביעת אצבע\'"
"כבר לא ניתן לזהות את %s."
"כבר לא ניתן לזהות את %1$s ואת %2$s."
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 0d3a80c9b69a6f174d1827f1e8ae3f17ce137cf2..339144611afd0229da833719fbe3273f38340b5c 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -612,6 +612,10 @@
"付近の Ultra Wideband デバイス間の相対位置の特定をアプリに許可します"
"付近の Wi-Fi デバイスとの通信"
"付近の Wi-Fi デバイスについて、情報の表示、接続、相対位置の確認をアプリに許可します"
+
+
+
+
"優先される NFC お支払いサービスの情報"
"登録されている支援やルートの目的地など、優先される NFC お支払いサービスの情報を取得することをアプリに許可します。"
"NFCの管理"
@@ -2431,54 +2435,30 @@
"ON にする"
"戻る"
"保留中..."
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "衛星 SOS を利用できるようになりました"
+ "モバイル ネットワークや Wi-Fi ネットワークがなくても、緊急サービスにメッセージを送信できます。Google メッセージがデフォルトのメッセージ アプリに設定されている必要があります。"
+ "衛星 SOS に対応していません"
+ "このデバイスは衛星 SOS に対応していません"
+ "衛星 SOS が設定されていません"
+ "インターネットに接続していることを確認してから、もう一度設定してみてください"
+ "衛星 SOS を利用できません"
+ "この国または地域では衛星 SOS を利用できません"
+ "衛星 SOS が設定されていません"
+ "衛星経由でメッセージを送受信するには、Google メッセージをデフォルトのメッセージ アプリに設定してください"
+ "衛星 SOS を利用できません"
+ "この国または地域で衛星 SOS を利用できるかどうかを確認するには、位置情報の設定を ON にしてください"
+ "衛星通信メッセージを利用できます"
+ "モバイル ネットワークや Wi-Fi ネットワークがなくても、衛星経由でメッセージを送受信できます。Google メッセージがデフォルトのメッセージ アプリに設定されている必要があります。"
+ "衛星通信メッセージに対応していません"
+ "このデバイスは衛星通信メッセージに対応していません"
+ "衛星通信メッセージが設定されていません"
+ "インターネットに接続していることを確認してから、もう一度設定してみてください"
+ "衛星通信メッセージを利用できません"
+ "この国または地域では衛星通信メッセージを利用できません"
+ "衛星通信メッセージが設定されていません"
+ "衛星経由でメッセージを送受信するには、Google メッセージをデフォルトのメッセージ アプリに設定してください"
+ "衛星通信メッセージを利用できません"
+ "この国または地域で衛星通信メッセージを利用できるかどうかを確認するには、位置情報の設定を ON にしてください"
"指紋認証をもう一度設定してください"
"%sを認識できなくなりました。"
"%1$sと%2$sを認識できなくなりました。"
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index 19177d65a991d7deccd642a429e113b48e3e9f93..58f78901ef5e067e8d2f37b31129a6963c0517ea 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -612,6 +612,10 @@
"ნებას რთავს აპს, დაადგინოს შედარებითი პოზიცია ახლომახლო ულტრაფართო სიხშირის მოწყობილობების შესახებ"
"ინტერაქცია ახლომახლო Wi-Fi მოწყობილობებთან"
"საშუალებას აძლევს აპს, განაცხადოს ახლომახლო Wi-Fi მოწყობილობების შესახებ, დაუკავშირდეს მათ და განსაზღვროს მათი შედარებითი პოზიცია"
+
+
+
+
"უპირატესი NFC გადახდის სერვისის ინფორმაცია"
"საშუალებას აძლევს აპს, მიიღოს უპირატესი NFC გადახდის სერვისის ინფორმაცია, მაგალითად, რეგისტრირებული დახმარება და დანიშნულება."
"ახლო მოქმედების რადიოკავშირი (NFC) მართვა"
@@ -2431,54 +2435,30 @@
"ჩართვა"
"უკან დაბრუნება"
"მომლოდინე..."
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "სატელიტური SOS ახლა ხელმისაწვდომია"
+ "შეგიძლიათ, შეტყობინება გაუგზავნოთ გადაუდებელი დახმარების სამსახურებს, თუ მობილური ან Wi-Fi ქსელი არ არის ხელმისაწვდომი. საჭიროა, რომ Google Messages იყოს თქვენი ნაგულისხმევი შეტყობინებების აპი."
+ "სატელიტური SOS არ არის მხარდაჭერილი"
+ "სატელიტური SOS არ არის მხარდაჭერილი ამ მოწყობილობაზე"
+ "სატელიტური SOS არ არის დაყენებული"
+ "დარწმუნდით, რომ დაკავშირებული ხართ ინტერნეტთან და ცადეთ ხელახლა დაყენება"
+ "სატელიტური SOS არ არის ხელმისაწვდომი"
+ "სატელიტური SOS ამ ქვეყანასა თუ რეგიონში არ არის ხელმისაწვდომი"
+ "სატელიტური SOS არ არის დაყენებული"
+ "შეტყობინებების სატელიტური მიმოცვლისთვის თქვენს ნაგულისხმევ შეტყობინებების აპად დააყენეთ Google Messages"
+ "სატელიტური SOS არ არის ხელმისაწვდომი"
+ "ამ ქვეყანაში ან რეგიონში სატელიტური SOS-ის ხელმისაწვდომობის შესამოწმებლად ჩართეთ მდებარეობის პარამეტრები"
+ "შეტყობინებების სატელიტური მიმოცვლა ხელმისაწვდომია"
+ "შეტყობინების გაგზავნა სატელიტის საშუალებით შეგიძლიათ, თუ მობილურზე ან Wi-Fi ქსელზე წვდომა არ გაქვთ. საჭიროა, რომ Google Messages იყოს თქვენი ნაგულისხმევი შეტყობინებების აპი."
+ "შეტყობინებების სატელიტური მიმოცვლა მხარდაჭერილი არ არის"
+ "ამ მოწყობილობაზე შეტყობინებების სატელიტური მიმოცვლა არ არის მხარდაჭერილი"
+ "შეტყობინებების სატელიტური მიმოცვლა დაყენებული არ არის"
+ "დარწმუნდით, რომ დაკავშირებული ხართ ინტერნეტთან და ცადეთ ხელახლა დაყენება"
+ "შეტყობინებების სატელიტური მიმოცვლა მიუწვდომელია"
+ "ამ ქვეყანაში ან რეგიონში შეტყობინებების სატელიტური მიმოცვლა მიუწვდომელია"
+ "შეტყობინებების სატელიტური მიმოცვლა დაყენებული არ არის"
+ "შეტყობინებების სატელიტური მიმოცვლისთვის თქვენს ნაგულისხმევ შეტყობინებების აპად დააყენეთ Google Messages"
+ "შეტყობინებების სატელიტური მიმოცვლა მიუწვდომელია"
+ "ამ ქვეყანაში ან რეგიონში შეტყობინებების სატელიტური მიმოცვლის ხელმისაწვდომობის შესამოწმებლად ჩართეთ მდებარეობის პარამეტრები"
"ანაბეჭდით განბლოკვის ხელახლა დაყენება"
"%s-ის ამოცნობა ვეღარ ხერხდება."
"%1$s-ისა და %2$s-ის ამოცნობა ვეღარ ხერხდება."
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index 70774d6cafe14bbaca3cf6b6fabf22d9e89ca8b4..737f950567a1f12c035e31e6a33e74e9a88e0146 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -612,6 +612,10 @@
"Қолданбаға маңайдағы кең жолақты құрылғылардың бір-біріне қатысты орнын анықтауға мүмкіндік береді."
"маңайдағы Wi-Fi құрылғыларымен байланысу"
"Қолданба маңайдағы Wi‑Fi құрылғыларына жарнама беріп, оларға қосылып, шамамен орналасқан жерін анықтай алады."
+
+
+
+
"Таңдаулы NFC төлеу қызметі туралы ақпарат"
"Қолданба тіркелген көмектер және баратын жер маршруты сияқты таңдаулы NFC төлеу қызметі туралы ақпаратты ала алатын болады."
"NFC функциясын басқару"
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index c758e0501aa87cd9a9c987eade16c0e97c6f0e07..0ecad8f60fe15d8d41b9f00b42f2c07c8f44bbd4 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -612,6 +612,10 @@
"អនុញ្ញាតឱ្យកម្មវិធីកំណត់ចម្ងាយពាក់ព័ន្ធរវាងឧបករណ៍ Ultra-Wideband ដែលនៅជិត"
"ធ្វើអន្តរកម្មជាមួយឧបករណ៍ Wi‑Fi ដែលនៅជិត"
"អនុញ្ញាតឱ្យកម្មវិធីផ្សាយពាណិជ្ជកម្ម ភ្ជាប់ និងកំណត់ទីតាំងពាក់ព័ន្ធរបស់ឧបករណ៍ Wi‑Fi ដែលនៅជិត"
+
+
+
+
"ព័ត៌មានអំពីសេវាបង់ប្រាក់តាម NFC ជាអាទិភាព"
"អនុញ្ញាតឱ្យកម្មវិធីទទួលបានព័ត៌មានអំពីសេវាបង់ប្រាក់តាម nfc ជាអាទិភាពដូចជា គោលដៅផ្លូវ និងព័ត៌មានកំណត់អត្តសញ្ញាណកម្មវិធី ដែលបានចុះឈ្មោះជាដើម។"
"ពិនិត្យការទាក់ទងនៅក្បែរ (NFC)"
@@ -2431,54 +2435,30 @@
"បើក"
"ថយក្រោយ"
"កំពុងរង់ចាំ..."
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "ឥឡូវនេះ អាចប្រើការប្រកាសអាសន្នតាមផ្កាយរណបបានហើយ"
+ "អ្នកអាចផ្ញើសារទៅសេវាសង្គ្រោះបន្ទាន់ ប្រសិនបើមិនមានបណ្ដាញឧបករណ៍ចល័ត ឬ Wi-Fi ទេ។ Google Messages ត្រូវតែជាកម្មវិធីផ្ញើសារលំនាំដើមរបស់អ្នក។"
+ "មិនអាចប្រើការប្រកាសអាសន្នតាមផ្កាយរណបបានទេ"
+ "មិនអាចប្រើការប្រកាសអាសន្នតាមផ្កាយរណបនៅលើឧបករណ៍នេះបានទេ"
+ "ការប្រកាសអាសន្នតាមផ្កាយរណបមិនត្រូវបានរៀបចំទេ"
+ "សូមប្រាកដថា អ្នកបានភ្ជាប់អ៊ីនធឺណិត រួចសាកល្បងរៀបចំម្ដងទៀត"
+ "មិនអាចប្រើការប្រកាសអាសន្នតាមផ្កាយរណបបានទេ"
+ "មិនអាចប្រើការប្រកាសអាសន្នតាមផ្កាយរណនៅក្នុងប្រទេស ឬតំបន់នេះបានទេ"
+ "មិនបានរៀបចំការប្រកាសអាសន្នតាមផ្កាយរណបទេ"
+ "ដើម្បីផ្ញើសារតាមផ្កាយរណប សូមកំណត់ Google Messages ជាកម្មវិធីផ្ញើសារលំនាំដើមរបស់អ្នក"
+ "មិនអាចប្រើការប្រកាសអាសន្នតាមផ្កាយរណបបានទេ"
+ "ដើម្បីពិនិត្យមើលថាតើអាចប្រើការប្រកាសអាសន្នតាមផ្កាយរណបនៅក្នុងប្រទេស ឬតំបន់នេះបានឬអត់ សូមបើកការកំណត់ទីតាំង"
+ "អាចផ្ញើសារតាមផ្កាយរណបបាន"
+ "អ្នកអាចផ្ញើសារតាមផ្កាយរណប ប្រសិនបើមិនមានបណ្ដាញឧបករណ៍ចល័ត ឬ Wi-Fi ទេ។ Google Messages ត្រូវតែជាកម្មវិធីផ្ញើសារលំនាំដើមរបស់អ្នក។"
+ "មិនអាចផ្ញើសារតាមផ្កាយរណបបានទេ"
+ "មិនអាចផ្ញើសារតាមផ្កាយរណបនៅលើឧបករណ៍នេះបានទេ"
+ "មិនបានរៀបចំការផ្ញើសារតាមផ្កាយរណបទេ"
+ "សូមប្រាកដថា អ្នកបានភ្ជាប់អ៊ីនធឺណិត រួចសាកល្បងរៀបចំម្ដងទៀត"
+ "មិនអាចផ្ញើសារតាមផ្កាយរណបបានទេ"
+ "មិនអាចផ្ញើសារតាមផ្កាយរណបនៅក្នុងប្រទេស ឬតំបន់នេះបានទេ"
+ "មិនបានរៀបចំការផ្ញើសារតាមផ្កាយរណបទេ"
+ "ដើម្បីផ្ញើសារតាមផ្កាយរណប សូមកំណត់ Google Messages ជាកម្មវិធីផ្ញើសារលំនាំដើមរបស់អ្នក"
+ "មិនអាចផ្ញើសារតាមផ្កាយរណបបានទេ"
+ "ដើម្បីពិនិត្យមើលថាតើអាចផ្ញើសារតាមផ្កាយរណបនៅក្នុងប្រទេស ឬតំបន់នេះបានឬអត់ សូមបើកការកំណត់ទីតាំង"
"រៀបចំការដោះសោដោយស្កេនស្នាមម្រាមដៃម្ដងទៀត"
"លែងអាចសម្គាល់ %s បានទៀតហើយ។"
"លែងអាចសម្គាល់ %1$s និង %2$s បានទៀតហើយ។"
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index 8efcd08693031aa8af74e46e2a22fc35cf0ddb5a..c64f6ec1e7a70f4b48dc054766a4f42bb7c600a1 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -612,6 +612,10 @@
"ಸಮೀಪದಲ್ಲಿರುವ ಅಲ್ಟ್ರಾ-ವೈಡ್ಬ್ಯಾಂಡ್ ಸಾಧನಗಳ ನಡುವೆ ಸಂಬಂಧಿತ ಸ್ಥಾನವನ್ನು ನಿರ್ಧರಿಸಲು ಆ್ಯಪ್ಗೆ ಅನುಮತಿಸಿ"
"ಹತ್ತಿರದ ವೈ -ಫೈ ಸಾಧನಗಳ ಜೊತೆಗೆ ಸಂವಹನ ನಡೆಸಿ"
"ಹತ್ತಿರದ ವೈ -ಫೈ ಸಾಧನಗಳ ಸಂಬಂಧಿತ ಸ್ಥಾನವನ್ನು ಸೂಚಿಸಲು, ಕನೆಕ್ಟ್ ಮಾಡಲು ಮತ್ತು ನಿರ್ಧರಿಸಲು ಆ್ಯಪ್ಗೆ ಅನುಮತಿಸುತ್ತದೆ"
+
+
+
+
"ಆದ್ಯತೆಯ NFC ಪಾವತಿ ಸೇವಾ ಮಾಹಿತಿ"
"ನೋಂದಾಯಿತ ಆ್ಯಪ್ ಗುರುತಿಸುವಿಕೆಗಳು ಮತ್ತು ಮಾರ್ಗ ಗಮ್ಯಸ್ಥಾನಗಳಂತಹ ಆದ್ಯತೆಯ NFC ಪಾವತಿ ಸೇವೆಗಳ ಬಗ್ಗೆ ಮಾಹಿತಿಯನ್ನು ಪಡೆಯಲು ಆ್ಯಪ್ಗೆ ಅನುಮತಿಸುತ್ತದೆ."
"ಸಮೀಪ ಕ್ಷೇತ್ರ ಸಂವಹನವನ್ನು ನಿಯಂತ್ರಿಸಿ"
@@ -2431,54 +2435,30 @@
"ಆನ್ ಮಾಡಿ"
"ಹಿಂದಿರುಗಿ"
"ಬಾಕಿ ಉಳಿದಿದೆ..."
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "ಸ್ಯಾಟಲೈಟ್ SOS ಈಗ ಲಭ್ಯವಿದೆ"
+ "ಮೊಬೈಲ್ ಅಥವಾ ವೈ-ಫೈ ನೆಟ್ವರ್ಕ್ ಇಲ್ಲದಿದ್ದರೆ ನೀವು ತುರ್ತು ಸೇವೆಗಳಿಗೆ ಸಂದೇಶ ಕಳುಹಿಸಬಹುದು. Google Messages ನಿಮ್ಮ ಡೀಫಾಲ್ಟ್ ಮೆಸೇಜಿಂಗ್ ಆ್ಯಪ್ ಆಗಿರಬೇಕು."
+ "ಸ್ಯಾಟಲೈಟ್ SOS ಬೆಂಬಲಿತವಾಗಿಲ್ಲ"
+ "ಈ ಸಾಧನದಲ್ಲಿ ಸ್ಯಾಟಲೈಟ್ SOS ಬೆಂಬಲಿತವಾಗಿಲ್ಲ"
+ "ಸ್ಯಾಟಲೈಟ್ SOS ಅನ್ನು ಸೆಟಪ್ ಮಾಡಲಾಗಿಲ್ಲ"
+ "ನೀವು ಇಂಟರ್ನೆಟ್ಗೆ ಕನೆಕ್ಟ್ ಆಗಿರುವಿರಿ ಎಂಬುದನ್ನು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳಿ ಮತ್ತು ಪುನಃ ಸೆಟಪ್ ಮಾಡಲು ಪ್ರಯತ್ನಿಸಿ"
+ "ಸ್ಯಾಟಲೈಟ್ SOS ಲಭ್ಯವಿಲ್ಲ"
+ "ಈ ದೇಶ ಅಥವಾ ಪ್ರದೇಶದಲ್ಲಿ ಸ್ಯಾಟಲೈಟ್ SOS ಲಭ್ಯವಿಲ್ಲ"
+ "ಸ್ಯಾಟಲೈಟ್ SOS ಸೆಟಪ್ ಆಗಿಲ್ಲ"
+ "ಸ್ಯಾಟಲೈಟ್ ಮೂಲಕ ಸಂದೇಶ ಕಳುಹಿಸಲು, Google Messages ಅನ್ನು ನಿಮ್ಮ ಡೀಫಾಲ್ಟ್ ಮೆಸೇಜಿಂಗ್ ಆ್ಯಪ್ನಂತೆ ಸೆಟ್ ಮಾಡಿ"
+ "ಸ್ಯಾಟಲೈಟ್ SOS ಲಭ್ಯವಿಲ್ಲ"
+ "ಈ ದೇಶ ಅಥವಾ ಪ್ರದೇಶದಲ್ಲಿ ಸ್ಯಾಟಲೈಟ್ SOS ಲಭ್ಯವಿದೆಯೇ ಎಂದು ಪರಿಶೀಲಿಸಲು, ಸ್ಥಳ ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ಆನ್ ಮಾಡಿ"
+ "ಸ್ಯಾಟಲೈಟ್ ಮೆಸೇಜಿಂಗ್ ಲಭ್ಯವಿದೆ"
+ "ಮೊಬೈಲ್ ಅಥವಾ ವೈ-ಫೈ ನೆಟ್ವರ್ಕ್ ಇಲ್ಲದಿದ್ದರೆ ನೀವು ಸ್ಯಾಟಲೈಟ್ ಮೂಲಕ ಸಂದೇಶ ಕಳುಹಿಸಬಹುದು. Google Messages ನಿಮ್ಮ ಡೀಫಾಲ್ಟ್ ಮೆಸೇಜಿಂಗ್ ಆ್ಯಪ್ ಆಗಿರಬೇಕು."
+ "ಸ್ಯಾಟಲೈಟ್ ಮೆಸೇಜಿಂಗ್ ಗೆ ಬೆಂಬಲವಿಲ್ಲ"
+ "ಈ ಸಾಧನದಲ್ಲಿ ಸ್ಯಾಟಲೈಟ್ ಮೆಸೇಜಿಂಗ್ ಬೆಂಬಲಿಸುವುದಿಲ್ಲ"
+ "ಸ್ಯಾಟಲೈಟ್ ಮೆಸೇಜಿಂಗ್ ಸೆಟಪ್ ಮಾಡಲಾಗಿಲ್ಲ"
+ "ನೀವು ಇಂಟರ್ನೆಟ್ಗೆ ಕನೆಕ್ಟ್ ಆಗಿರುವಿರಿ ಎಂಬುದನ್ನು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳಿ ಮತ್ತು ಪುನಃ ಸೆಟಪ್ ಮಾಡಲು ಪ್ರಯತ್ನಿಸಿ"
+ "ಸ್ಯಾಟಲೈಟ್ ಮೆಸೇಜಿಂಗ್ ಕಳುಹಿಸುವಿಕೆ ಲಭ್ಯವಿಲ್ಲ"
+ "ಈ ದೇಶ ಅಥವಾ ಪ್ರದೇಶದಲ್ಲಿ ಸ್ಯಾಟಲೈಟ್ ಮೆಸೇಜಿಂಗ್ ಲಭ್ಯವಿಲ್ಲ"
+ "ಸ್ಯಾಟಲೈಟ್ ಮೆಸೇಜಿಂಗ್ ಸೆಟಪ್ ಮಾಡಲಾಗಿಲ್ಲ"
+ "ಸ್ಯಾಟಲೈಟ್ ಮೂಲಕ ಸಂದೇಶ ಕಳುಹಿಸಲು, Google Messages ಅನ್ನು ನಿಮ್ಮ ಡೀಫಾಲ್ಟ್ ಮೆಸೇಜಿಂಗ್ ಆ್ಯಪ್ನಂತೆ ಸೆಟ್ ಮಾಡಿ"
+ "ಸ್ಯಾಟಲೈಟ್ ಮೆಸೇಜಿಂಗ್ ಕಳುಹಿಸುವಿಕೆ ಲಭ್ಯವಿಲ್ಲ"
+ "ಈ ದೇಶ ಅಥವಾ ಪ್ರದೇಶದಲ್ಲಿ ಸ್ಯಾಟಲೈಟ್ ಮೆಸೇಜಿಂಗ್ ಲಭ್ಯವಿದೆಯೇ ಎಂದು ಪರಿಶೀಲಿಸಲು, ಸ್ಥಳ ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ಆನ್ ಮಾಡಿ"
"ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಅನ್ಲಾಕ್ ಅನ್ನು ಮತ್ತೊಮ್ಮೆ ಸೆಟಪ್ ಮಾಡಿ"
"%s ಅನ್ನು ಇನ್ನು ಮುಂದೆ ಗುರುತಿಸಲಾಗುವುದಿಲ್ಲ."
"%1$s ಮತ್ತು %2$s ಅನ್ನು ಇನ್ನು ಮುಂದೆ ಗುರುತಿಸಲಾಗುವುದಿಲ್ಲ."
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index a069805148f519a3274d73725c653b41f9be7175..d63d43e4cddd5fe02f7a7616159e9790aeeb5c72 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -612,6 +612,10 @@
"앱이 근처의 초광대역 기기 간 상대적 위치를 파악하도록 허용"
"근처 Wi‑Fi 기기와 상호작용"
"앱이 광역 신호를 보내 근처에 있는 Wi‑Fi 기기의 상대적인 위치를 확인하고 연결할 수 있도록 허용합니다."
+
+
+
+
"기본 NFC 결제 서비스 정보"
"앱이 등록된 AID와 경로 목적지 같은 기본 NFC 결제 서비스 정보를 확인하도록 허용합니다."
"NFC(Near Field Communication) 제어"
@@ -2431,54 +2435,30 @@
"사용"
"뒤로"
"대기 중…"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "이제 위성 긴급 SOS를 사용할 수 있음"
+ "모바일 또는 Wi-Fi 네트워크가 없는 경우 응급 서비스로 메시지를 보낼 수 있습니다. Google 메시지가 기본 메시지 앱으로 설정되어 있어야 합니다."
+ "위성 긴급 SOS가 지원되지 않음"
+ "이 기기에서는 위성 긴급 SOS가 지원되지 않습니다."
+ "위성 긴급 SOS가 설정되지 않음"
+ "인터넷에 연결되어 있는지 확인한 후 다시 설정해 보세요."
+ "위성 긴급 SOS를 사용할 수 없음"
+ "이 국가 또는 지역에서는 위성 긴급 SOS를 사용할 수 없습니다."
+ "위성 긴급 SOS가 설정되지 않음"
+ "위성으로 메시지를 보내려면 Google 메시지를 기본 메시지 앱으로 설정하세요."
+ "위성 긴급 SOS를 사용할 수 없음"
+ "이 국가 또는 지역에서 위성 긴급 SOS를 사용할 수 있는지 확인하려면 위치 설정을 사용 설정하세요."
+ "위성 메시지 사용 가능"
+ "모바일 또는 Wi-Fi 네트워크가 없는 경우 위성으로 메시지를 보낼 수 있습니다. Google 메시지가 기본 메시지 앱으로 설정되어 있어야 합니다."
+ "위성 메시지가 지원되지 않음"
+ "이 기기에서는 위성 메시지가 지원되지 않습니다."
+ "위성 메시지가 설정되지 않음"
+ "인터넷에 연결되어 있는지 확인한 후 다시 설정해 보세요."
+ "위성 메시지를 사용할 수 없음"
+ "이 국가 또는 지역에서는 위성 메시지를 사용할 수 없습니다."
+ "위성 메시지가 설정되지 않음"
+ "위성으로 메시지를 보내려면 Google 메시지를 기본 메시지 앱으로 설정하세요."
+ "위성 메시지를 사용할 수 없음"
+ "이 국가 또는 지역에서 위성 메시지를 사용할 수 있는지 확인하려면 위치 설정을 사용 설정하세요."
"지문 잠금 해제 다시 설정"
"%s 지문을 더 이상 인식할 수 없습니다."
"%1$s 및 %2$s 지문을 더 이상 인식할 수 없습니다."
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index ec0059bb31f679635c4c981dd2f507429ed8730a..e09036a1b679185b3393b83cff83bd4172074d54 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -612,6 +612,10 @@
"Колдонмо кең тилкелүү тармак аркылуу туташа турган жакын жердеги түзмөктөрдү аныктай алат"
"Жакын жердеги Wi‑Fi түзмөктөрүнө байланышуу"
"Колдонмо жакын жердеги Wi-Fi түзмөктөргө туташып, алардын жайгашкан жерин аныктап, ар кандай нерселерди өткөрө алат."
+
+
+
+
"Тандалган NFC төлөм кызматы жөнүндө маалымат"
"Колдонмого катталган жардам же көздөлгөн жерге маршрут сыяктуу тандалган nfc төлөм кызматы жөнүндө маалыматты алууга уруксат берүү."
"Near Field Communication көзөмөлү"
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index 3962f09f0bacd802ab413e562a4a4c02d1babd5d..a9ebcd76550237948481da7acce10574f2159555 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -612,6 +612,10 @@
"ອະນຸຍາດໃຫ້ແອັບກຳນົດຕຳແໜ່ງທີ່ສຳພັນກັນລະຫວ່າງອຸປະກອນ Ultra-Wideband ທີ່ຢູ່ໃກ້ຄຽງ"
"ໂຕ້ຕອບກັບອຸປະກອນ Wi‑Fi ທີ່ຢູ່ໃກ້ຄຽງ"
"ອະນຸຍາດໃຫ້ແອັບໂຄສະນາ, ເຊື່ອມຕໍ່ ແລະ ກຳນົດຕຳແໜ່ງສຳພັນຂອງອຸປະກອນ Wi-Fi ທີ່ຢູ່ໃກ້ຄຽງໄດ້"
+
+
+
+
"ຂໍ້ມູນບໍລິການການຈ່າຍເງິນ NFC ທີ່ຕ້ອງການ"
"ອະນຸຍາດໃຫ້ແອັບຮັບຂໍ້ມູນບໍລິການການຈ່າຍເງິນ NFC ທີ່ຕ້ອງການໄດ້ ເຊັ່ນ: ການຊ່ວຍເຫຼືອແບບລົງທະບຽນ ແລະ ປາຍທາງເສັ້ນທາງ."
"ຄວບຄຸມ Near Field Communication"
@@ -2431,54 +2435,30 @@
"ເປີດໃຊ້"
"ກັບຄືນ"
"ລໍຖ້າດຳເນີນການ..."
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "ຕອນນີ້ SOS ດາວທຽມພ້ອມໃຫ້ບໍລິການແລ້ວ"
+ "ທ່ານສາມາດສົ່ງຂໍ້ຄວາມໄປຫາບໍລິການສຸກເສີນໄດ້ໃນກໍລະນີທີ່ບໍ່ມີເຄືອຂ່າຍມືຖື ຫຼື Wi-Fi. ຕ້ອງຕັ້ງຄ່າ Google Messages ເປັນແອັບຮັບສົ່ງຂໍ້ຄວາມເລີ່ມຕົ້ນຂອງທ່ານ."
+ "ບໍ່ຮອງຮັບ SOS ດາວທຽມ"
+ "ອຸປະກອນນີ້ບໍ່ຮອງຮັບ SOS ດາວທຽມ"
+ "ບໍ່ໄດ້ຕັ້ງຄ່າ SOS ດາວທຽມ"
+ "ກະລຸນາກວດສອບໃຫ້ໝັ້ນໃຈວ່າທ່ານໄດ້ເຊື່ອມຕໍ່ອິນເຕີເນັດແລ້ວ ແລະ ລອງຕັ້ງຄ່າອີກຄັ້ງ"
+ "SOS ດາວທຽມບໍ່ພ້ອມໃຫ້ບໍລິການ"
+ "SOS ດາວທຽມບໍ່ພ້ອມໃຫ້ບໍລິການໃນປະເທດ ຫຼື ພາກພື້ນນີ້"
+ "ບໍ່ໄດ້ຕັ້ງຄ່າ SOS ດາວທຽມ"
+ "ເພື່ອຮັບສົ່ງຂໍ້ຄວາມຜ່ານດາວທຽມ, ໃຫ້ຕັ້ງ Google Messages ເປັນແອັບຮັບສົ່ງຂໍ້ຄວາມເລີ່ມຕົ້ນຂອງທ່ານ"
+ "SOS ດາວທຽມບໍ່ພ້ອມໃຫ້ບໍລິການ"
+ "ເພື່ອກວດສອບວ່າ SOS ດາວທຽມພ້ອມໃຫ້ບໍລິການໃນປະເທດ ຫຼື ພາກພື້ນນີ້ຫຼືບໍ່, ໃຫ້ເປີດການຕັ້ງຄ່າສະຖານທີ່"
+ "ການຮັບສົ່ງຂໍ້ຄວາມຜ່ານດາວທຽມພ້ອມໃຫ້ບໍລິການ"
+ "ທ່ານສາມາດຮັບສົ່ງຂໍ້ຄວາມຜ່ານດາວທຽມໄດ້ໃນກໍລະນີທີ່ບໍ່ມີເຄືອຂ່າຍມືຖື ຫຼື Wi-Fi. ຕ້ອງຕັ້ງຄ່າ Google Messages ເປັນແອັບຮັບສົ່ງຂໍ້ຄວາມເລີ່ມຕົ້ນຂອງທ່ານ."
+ "ບໍ່ຮອງຮັບການຮັບສົ່ງຂໍ້ຄວາມຜ່ານດາວທຽມ"
+ "ອຸປະກອນນີ້ບໍ່ຮອງຮັບການຮັບສົ່ງຂໍ້ຄວາມຜ່ານດາວທຽມ"
+ "ບໍ່ໄດ້ຕັ້ງຄ່າການຮັບສົ່ງຂໍ້ຄວາມຜ່ານດາວທຽມ"
+ "ກະລຸນາກວດສອບໃຫ້ໝັ້ນໃຈວ່າທ່ານໄດ້ເຊື່ອມຕໍ່ອິນເຕີເນັດແລ້ວ ແລະ ລອງຕັ້ງຄ່າອີກຄັ້ງ"
+ "ການຮັບສົ່ງຂໍ້ຄວາມຜ່ານດາວທຽມບໍ່ພ້ອມໃຫ້ບໍລິການ"
+ "ການຮັບສົ່ງຂໍ້ຄວາມຜ່ານດາວທຽມບໍ່ພ້ອມໃຫ້ບໍລິການໃນປະເທດ ຫຼື ພາກພື້ນນີ້"
+ "ບໍ່ໄດ້ຕັ້ງຄ່າການຮັບສົ່ງຂໍ້ຄວາມຜ່ານດາວທຽມ"
+ "ເພື່ອຮັບສົ່ງຂໍ້ຄວາມຜ່ານດາວທຽມ, ໃຫ້ຕັ້ງ Google Messages ເປັນແອັບຮັບສົ່ງຂໍ້ຄວາມເລີ່ມຕົ້ນຂອງທ່ານ"
+ "ການຮັບສົ່ງຂໍ້ຄວາມຜ່ານດາວທຽມບໍ່ພ້ອມໃຫ້ບໍລິການ"
+ "ເພື່ອກວດສອບວ່າການຮັບສົ່ງຂໍ້ຄວາມຜ່ານດາວທຽມພ້ອມໃຫ້ບໍລິການໃນປະເທດ ຫຼື ພາກພື້ນນີ້ຫຼືບໍ່, ໃຫ້ເປີດການຕັ້ງຄ່າສະຖານທີ່"
"ຕັ້ງຄ່າການປົດລັອກດ້ວຍລາຍນິ້ວມືຄືນໃໝ່"
"ບໍ່ສາມາດຈຳແນກ %s ໄດ້ອີກຕໍ່ໄປ."
"ບໍ່ສາມາດຈຳແນກ %1$s ແລະ %2$s ໄດ້ອີກຕໍ່ໄປ."
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index c88b6635fab1c652e66d881ffaf2328ad672ad2d..21fddd010ca4c029818ebaf9fbb81c963dbcae27 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -614,6 +614,10 @@
"Leisti programai nustatyti apytikslę netoliese esančių itin plataus dažnio juostos įrenginių poziciją"
"sąveikauti su „Wi‑Fi“ įrenginiais netoliese"
"Leidžiama programai reklamuoti, prisijungti ir nustatyti apytikslę netoliese esančių „Wi-Fi“ įrenginių poziciją"
+
+
+
+
"Pageidaujama ARL mokėjimo paslaugos informacija"
"Programai leidžiama gauti pageidaujamą ARL mokamos paslaugos informaciją, pvz., užregistruotą pagalbą ir maršrutų tikslus."
"valdyti artimo lauko perdavimą (angl. „Near Field Communication“)"
@@ -2433,54 +2437,30 @@
"Įjungti"
"Grįžti"
"Laukiama..."
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "Prisijungimas prie palydovo kritiniu atveju nepasiekiamas"
+ "Galite siųsti pranešimus pagalbos tarnyboms, kai nėra mobiliojo ryšio ar „Wi-Fi“ tinklo. „Google Messages“ turi būti jūsų numatytoji pranešimų programa."
+ "Prisijungimo prie palydovo kritiniu atveju funkcija nepalaikoma"
+ "Šiame įrenginyje nepalaikoma prisijungimo prie palydovo kritiniu atveju funkcija"
+ "Prisijungimo prie palydovo kritiniu atveju funkcija nenustatyta"
+ "Įsitikinkite, kad esate prisijungę prie interneto ir bandykite nustatyti dar kartą"
+ "Prisijungimo prie palydovo kritiniu atveju funkcija nepasiekiama"
+ "Prisijungimo prie palydovo kritiniu atveju funkcija nepasiekiama šioje šalyje arba regione"
+ "Prisijungimo prie palydovo kritiniu atveju funkcija nenustatyta"
+ "Jei norite siųsti pranešimus per palydovą, nustatykite „Google Messages“ kaip numatytąją pranešimų programą"
+ "Prisijungimo prie palydovo kritiniu atveju funkcija nepasiekiama"
+ "Jei norite patikrinti, ar prisijungimo prie palydovo kritiniu atveju funkcija pasiekiama šioje šalyje ar regione, įjunkite vietovės nustatymus"
+ "Pasiekiama susirašinėjimo palydoviniais pranešimais paslauga"
+ "Galite siųsti pranešimus palydoviniu ryšiu, kai nėra mobiliojo ryšio ar „Wi-Fi“ tinklo. „Google Messages“ turi būti jūsų numatytoji pranešimų programa."
+ "Susirašinėjimo palydoviniais pranešimais paslauga nepalaikoma"
+ "Šiame įrenginyje nepalaikoma susirašinėjimo palydoviniais pranešimais paslauga"
+ "Susirašinėjimo palydoviniais pranešimais paslauga nenustatyta"
+ "Įsitikinkite, kad esate prisijungę prie interneto ir bandykite nustatyti dar kartą"
+ "Susirašinėjimo palydoviniais pranešimais paslauga nepasiekiama"
+ "Susirašinėjimo palydoviniais pranešimais paslauga nepasiekiama šioje šalyje ar regione"
+ "Susirašinėjimo palydoviniais pranešimais paslauga nenustatyta"
+ "Jei norite siųsti pranešimus per palydovą, nustatykite „Google Messages“ kaip numatytąją pranešimų programą"
+ "Susirašinėjimo palydoviniais pranešimais paslauga nepasiekiama"
+ "Jei norite patikrinti, ar susirašinėjimo palydoviniais pranešimais paslauga pasiekiama šioje šalyje ar regione, įjunkite vietovės nustatymus"
"Atrakinimo piršto atspaudu nustatymas dar kartą"
"%s nebegalima atpažinti."
"%1$s ir %2$s nebegalima atpažinti."
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 38d1891b13e27fd8e994c59e1f819cfdeda89cc2..15ee04a5f1d72c9245ff1e6ce1f82c717782b399 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -613,6 +613,10 @@
"Atļaut lietotnei noteikt relatīvo atrašanās vietu starp tuvumā esošām ultraplatjoslas ierīcēm"
"Mijiedarbība ar tuvumā esošām Wi‑Fi ierīcēm"
"Atļauj lietotnei nodot datus tuvumā esošām Wi‑Fi ierīcē, izveidot savienojumu ar tām un noteikt to relatīvo pozīciju."
+
+
+
+
"Informācija par vēlamo NFC maksājumu pakalpojumu"
"Ļauj lietotnei iegūt informāciju par vēlamo NFC maksājumu pakalpojumu, piemēram, par reģistrētajiem lietojumprogrammu ID un maršruta galamērķi."
"kontrolē tuvlauka saziņu"
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index 87fd79928298b87913ae570b8498cc6d5774d500..b5187726028b746d387c39d2e1fb8b50ea7d156b 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -612,6 +612,10 @@
"Дозволува апликацијата да ја одреди релативната положба помеѓу уредите со ултраширок појас во близина"
"да има интеракција со уредите со Wi‑Fi во близина"
"Дозволува апликацијата да рекламира, да се поврзува и да ја одредува релативната положба на уреди со Wi‑Fi во близина"
+
+
+
+
"Информации за претпочитаната услуга за плаќање преку NFC"
"Дозволува апликацијата да добие информации за претпочитаната услуга за плаќање преку NFC, како регистрирани помагала и дестинација на маршрутата."
"контролирај комуникација на блиско поле"
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index 086ebe1fcaa5e729302c12b8308ee8634b039a32..aabeb9b986463d9f065029d28fc8ff7086bacfdc 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -612,6 +612,10 @@
"സമീപമുള്ള അൾട്രാ-വെെഡ്ബാൻഡ് ഉപകരണങ്ങൾ തമ്മിലുള്ള ആപേക്ഷിക സ്ഥാനം നിർണ്ണയിക്കാൻ ആപ്പിനെ അനുവദിക്കുക"
"സമീപമുള്ള വൈഫൈ ഉപകരണങ്ങളുമായി ഇടപഴകുക"
"സമീപമുള്ള വൈഫൈ ഉപകരണങ്ങൾ കാണിക്കാനും അവയിലേക്ക് കണക്റ്റ് ചെയ്യാനും അവയുടെ ആപേക്ഷിക സ്ഥാനം നിർണ്ണയിക്കാനും ആപ്പിനെ അനുവദിക്കൂ"
+
+
+
+
"തിരഞ്ഞെടുത്ത NFC പേയ്മെന്റ് സേവനത്തെ സംബന്ധിച്ച വിവരങ്ങൾ"
"റൂട്ട് ലക്ഷ്യസ്ഥാനം, രജിസ്റ്റർ ചെയ്തിരിക്കുന്ന സഹായങ്ങൾ എന്നിവ പോലുള്ള, തിരഞ്ഞെടുത്ത NFC പേയ്മെന്റ് സേവനത്തെ സംബന്ധിച്ച വിവരങ്ങൾ ലഭിക്കാൻ ആപ്പിനെ അനുവദിക്കുന്നു."
"സമീപ ഫീൽഡുമായുള്ള ആശയവിനിമയം നിയന്ത്രിക്കുക"
@@ -2431,54 +2435,30 @@
"ഓണാക്കുക"
"മടങ്ങുക"
"തീർപ്പാക്കിയിട്ടില്ല..."
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "സാറ്റലൈറ്റ് SOS ഇപ്പോൾ ലഭ്യമാണ്"
+ "മൊബൈൽ അല്ലെങ്കിൽ വൈഫൈ നെറ്റ്വർക്ക് ലഭ്യമല്ലെങ്കിൽ നിങ്ങൾക്ക് അടിയന്തര സേവനങ്ങൾക്ക് സന്ദേശമയയ്ക്കാം. നിങ്ങളുടെ ഡിഫോൾട്ട് സന്ദേശമയയ്ക്കൽ ആപ്പ് Google Messages ആയിരിക്കണം."
+ "സാറ്റലൈറ്റ് SOS പിന്തുണയ്ക്കുന്നില്ല"
+ "ഈ ഉപകരണത്തിൽ സാറ്റലൈറ്റ് SOS പിന്തുണയ്ക്കുന്നില്ല"
+ "സാറ്റലൈറ്റ് SOS സജ്ജീകരിച്ചിട്ടില്ല"
+ "നിങ്ങൾ ഇന്റർനെറ്റിലേക്ക് കണക്റ്റ് ചെയ്തിട്ടുണ്ടെന്ന് ഉറപ്പാക്കിയ ശേഷം സജ്ജീകരിക്കാൻ വീണ്ടും ശ്രമിക്കുക"
+ "സാറ്റലൈറ്റ് SOS ലഭ്യമല്ല"
+ "ഈ രാജ്യത്ത് അല്ലെങ്കിൽ പ്രദേശത്ത് സാറ്റലൈറ്റ് SOS ലഭ്യമല്ല"
+ "സാറ്റലൈറ്റ് SOS സജ്ജീകരിച്ചിട്ടില്ല"
+ "സാറ്റലൈറ്റ് വഴി സന്ദേശമയയ്ക്കാൻ, നിങ്ങളുടെ ഡിഫോൾട്ട് സന്ദേശമയയ്ക്കൽ ആപ്പായി Google Messages സജ്ജീകരിക്കുക"
+ "സാറ്റലൈറ്റ് SOS ലഭ്യമല്ല"
+ "ഈ രാജ്യത്ത് അല്ലെങ്കിൽ പ്രദേശത്ത് സാറ്റലൈറ്റ് SOS ലഭ്യമാണോയെന്ന് പരിശോധിക്കുന്നതിന്, ലൊക്കേഷൻ ക്രമീകരണം ഓണാക്കുക"
+ "സാറ്റലൈറ്റ് സഹായത്തോടെ സന്ദേശമയയ്ക്കൽ ലഭ്യമാണ്"
+ "മൊബൈൽ അല്ലെങ്കിൽ വൈഫൈ നെറ്റ്വർക്ക് ഇല്ലെങ്കിൽ നിങ്ങൾക്ക് സാറ്റലൈറ്റ് വഴി സന്ദേശമയയ്ക്കാം. നിങ്ങളുടെ ഡിഫോൾട്ട് സന്ദേശമയയ്ക്കൽ ആപ്പ് Google Messages ആയിരിക്കണം."
+ "സാറ്റലൈറ്റ് സഹായത്തോടെ സന്ദേശമയയ്ക്കൽ പിന്തുണയ്ക്കുന്നില്ല"
+ "ഈ ഉപകരണത്തിൽ സാറ്റലൈറ്റ് സഹായത്തോടെ സന്ദേശമയയ്ക്കൽ പിന്തുണയ്ക്കുന്നില്ല"
+ "സാറ്റലൈറ്റ് സഹായത്തോടെ സന്ദേശമയയ്ക്കൽ സജ്ജീകരിച്ചിട്ടില്ല"
+ "നിങ്ങൾ ഇന്റർനെറ്റിലേക്ക് കണക്റ്റ് ചെയ്തിട്ടുണ്ടെന്ന് ഉറപ്പാക്കിയ ശേഷം സജ്ജീകരിക്കാൻ വീണ്ടും ശ്രമിക്കുക"
+ "സാറ്റലൈറ്റ് സഹായത്തോടെ സന്ദേശമയയ്ക്കൽ ലഭ്യമല്ല"
+ "ഈ രാജ്യത്ത് അല്ലെങ്കിൽ പ്രദേശത്ത് സാറ്റലൈറ്റ് സഹായത്തോടെ സന്ദേശമയയ്ക്കൽ ലഭ്യമല്ല"
+ "സാറ്റലൈറ്റ് സഹായത്തോടെ സന്ദേശമയയ്ക്കൽ സജ്ജീകരിച്ചിട്ടില്ല"
+ "സാറ്റലൈറ്റ് വഴി സന്ദേശമയയ്ക്കാൻ, നിങ്ങളുടെ ഡിഫോൾട്ട് സന്ദേശമയയ്ക്കൽ ആപ്പായി Google Messages സജ്ജീകരിക്കുക"
+ "സാറ്റലൈറ്റ് സഹായത്തോടെ സന്ദേശമയയ്ക്കൽ ലഭ്യമല്ല"
+ "ഈ രാജ്യത്ത് അല്ലെങ്കിൽ പ്രദേശത്ത് സാറ്റലൈറ്റ് സഹായത്തോടെ സന്ദേശമയയ്ക്കൽ ലഭ്യമാണോയെന്ന് പരിശോധിക്കാൻ, ലൊക്കേഷൻ ക്രമീകരണം ഓണാക്കുക"
"ഫിംഗർപ്രിന്റ് അൺലോക്ക് വീണ്ടും സജ്ജീകരിക്കുക"
"%s ഇനി തിരിച്ചറിയാനാകില്ല."
"%1$s, %2$s എന്നിവ ഇനി തിരിച്ചറിയാനാകില്ല."
@@ -2498,7 +2478,7 @@
"SMS"
"സംഗീതം"
"കലണ്ടർ"
- "കാൽക്കുലേറ്റർ"
+ "Calculator"
"Maps"
"ആപ്പുകൾ"
"നിങ്ങളുടെ ഫിംഗർപ്രിന്റുകൾ ഇനി തിരിച്ചറിയാനാകില്ല. ഫിംഗർപ്രിന്റ് അൺലോക്ക് വീണ്ടും സജ്ജീകരിക്കുക."
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 42db4c97ace41ba96f623642c4983cc6159ac349..c625d31dbd79ab9348e8712e0ae0d7a641d27f3f 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -612,6 +612,10 @@
"Аппад ойролцоох ультра өргөн зурвасын төхөөрөмжүүдийн хоорондох холбоотой байрлалыг тодорхойлохыг зөвшөөрөх"
"ойролцоох Wi-Fi төхөөрөмжүүдтэй харилцах"
"Аппад ойролцоох Wi-Fi төхөөрөмжүүдтэй холбоотой байрлалыг мэдэгдэх, холбох, тодорхойлохыг зөвшөөрнө"
+
+
+
+
"Сонгосон NFC төлбөрийн үйлчилгээний мэдээлэл"
"Бүртгүүлсэн төхөөрөмж болон маршрутын хүрэх цэг зэрэг сонгосон nfc төлбөрийн үйлчилгээний мэдээллийг авахыг аппад зөвшөөрдөг."
"ойролцоо талбарын холбоог удирдах"
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index 2cfeaa2adab91a3fef5b71fc78e1f167a6ed9b20..3240d59140562328a4d39d478423e03eb677a035 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -612,6 +612,10 @@
"ॲपला जवळच्या अल्ट्रा-वाइडबँड डिव्हाइसदरम्यानचे संबंधित स्थान निर्धारित करण्याची अनुमती द्या"
"जवळपासच्या वाय-फाय डिव्हाइसशी संवाद साधा"
"ॲपला जाहिरात करण्याची, कनेक्ट करण्याची आणि जवळपासच्या वाय-फाय डिव्हाइसचे संबंधित स्थान निर्धारित करण्याची परवानगी देते"
+
+
+
+
"प्राधान्यकृत NFC पेमेंट सेवा माहिती"
"नोंदणीकृत एड्स आणि मार्ग गंतव्यस्थान सारखी प्राधान्यकृत एनएफसी पेमेंट सेवेची माहिती मिळवण्यासाठी अॅपला अनुमती देते."
"फील्ड जवळील कम्युनिकेशन नियंत्रित करा"
@@ -2431,54 +2435,30 @@
"सुरू करा"
"मागे जा"
"प्रलंबित आहे..."
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "सॅटेलाइट SOS आता उपलब्ध आहे"
+ "कोणतेही मोबाइल किंवा वाय-फाय नेटवर्क उपलब्ध नसल्यास, तुम्ही आणीबाणी सेवांना मेसेज पाठवू शकता. Google Messages हे तुमचे डीफॉल्ट मेसेजिंग ॲप असणे आवश्यक आहे."
+ "सॅटेलाइट SOS ला सपोर्ट नाही"
+ "या डिव्हाइसवर सॅटेलाइट SOS ला सपोर्ट नाही"
+ "सॅटेलाइट SOS सेट केलेले नाही"
+ "तुम्ही इंटरनेटशी कनेक्ट केले असल्याची खात्री करा आणि पुन्हा सेटअप करून पहा"
+ "सॅटेलाइट SOS उपलब्ध नाही"
+ "या देशात किंवा प्रदेशात सॅटेलाइट SOS उपलब्ध नाही"
+ "सॅटेलाइट SOS सेट केलेले नाही"
+ "सॅटेलाइटद्वारे मेसेज करण्यासाठी, Google Messages ला तुमचे डीफॉल्ट मेसेजिंग ॲप म्हणून सेट करा"
+ "सॅटेलाइट SOS उपलब्ध नाही"
+ "या देशात किंवा प्रदेशात सॅटेलाइट SOS उपलब्ध आहे का हे तपासण्यासाठी, स्थान सेटिंग्ज सुरू करा"
+ "सॅटेलाइट मेसेजिंग उपलब्ध आहे"
+ "मोबाईल किंवा वाय-फाय नेटवर्क नसल्यास, तुम्ही सॅटेलाइटद्वारे मेसेज पाठवू शकता. Google Messages हे तुमचे डीफॉल्ट मेसेजिंग ॲप असणे आवश्यक आहे."
+ "सॅटेलाइट मेसेजिंगला सपोर्ट नाही"
+ "या डिव्हाइसवर सॅटेलाइट मेसेजिंगला सपोर्ट नाही"
+ "सॅटेलाइट मेसेजिंग सेट केलेले नाही"
+ "तुम्ही इंटरनेटशी कनेक्ट केले असल्याची खात्री करा आणि पुन्हा सेटअप करून पहा"
+ "सॅटेलाइट मेसेजिंग उपलब्ध नाही"
+ "या देशामध्ये किंवा प्रदेशामध्ये सॅटेलाइट मेसेजिंग उपलब्ध नाही"
+ "सॅटेलाइट मेसेजिंग सेट केलेले नाही"
+ "सॅटेलाइटद्वारे मेसेज करण्यासाठी, Google Messages ला तुमचे डीफॉल्ट मेसेजिंग ॲप म्हणून सेट करा"
+ "सॅटेलाइट मेसेजिंग उपलब्ध नाही"
+ "या देशात किंवा प्रदेशात सॅटेलाइट मेसेजिंग उपलब्ध आहे का हे तपासण्यासाठी, स्थान सेटिंग्ज सुरू करा"
"फिंगरप्रिंट अनलॉक पुन्हा सेट करा"
"%s यापुढे ओळखता येणार नाही."
"%1$s आणि %2$s यापुढे ओळखता येणार नाहीत."
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 6f5d5e7c36589b4a2dcecb4565610ac149b3f259..bd780ae0be928e5772d0b260451d507c6cbd1b7e 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -612,6 +612,10 @@
"Benarkan apl menentukan kedudukan relatif antara peranti Ultrajalur Lebar berdekatan"
"berinteraksi dengan peranti Wi-Fi berdekatan"
"Membenarkan apl mengiklankan, menyambung dan menentukan kedudukan relatif peranti Wi-Fi berdekatan"
+
+
+
+
"Maklumat Perkhidmatan Pembayaran NFC Pilihan"
"Membenarkan apl mendapatkan maklumat perkhidmatan pembayaran nfc pilihan seperti bantuan berdaftar dan destinasi laluan."
"mengawal Komunikasi Medan Dekat"
@@ -2431,54 +2435,30 @@
"Hidupkan"
"Kembali"
"Belum selesai..."
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "SOS via Satelit kini tersedia"
+ "Anda boleh menghantar mesej kepada perkhidmatan kecemasan jika tiada rangkaian mudah alih atau Wi-Fi. Google Messages mestilah ditetapkan sebagai apl pemesejan lalai anda."
+ "SOS via Satelit tidak disokong"
+ "SOS via Satelit tidak disokong pada peranti ini"
+ "SOS via Satelit tidak disediakan"
+ "Pastikan anda disambungkan kepada Internet dan cuba buat persediaan sekali lagi"
+ "SOS via Satelit tidak tersedia"
+ "SOS via Satelit tidak tersedia di negara atau rantau ini"
+ "SOS via Satelit tidak disediakan"
+ "Untuk menghantar mesej melalui satelit, tetapkan Google Messages sebagai apl pemesejan lalai anda"
+ "SOS via Satelit tidak tersedia"
+ "Untuk menyemak sama ada SOS via Satelit tersedia di negara atau rantau ini, hidupkan tetapan lokasi"
+ "Permesejan satelit tersedia"
+ "Anda boleh menghantar mesej melalui satelit jika tiada rangkaian mudah alih atau Wi-Fi. Google Messages mestilah ditetapkan sebagai apl pemesejan lalai anda."
+ "Permesejan satelit tidak disokong"
+ "Permesejan satelit tidak disokong pada peranti ini"
+ "Permesejan satelit tidak disediakan"
+ "Pastikan anda disambungkan kepada Internet dan cuba buat persediaan sekali lagi"
+ "Permesejan satelit tidak tersedia"
+ "Permesejan satelit tidak tersedia di negara atau rantau ini"
+ "Permesejan satelit tidak disediakan"
+ "Untuk menghantar mesej melalui satelit, tetapkan Google Messages sebagai apl pemesejan lalai anda"
+ "Permesejan satelit tidak tersedia"
+ "Untuk menyemak sama ada permesejan satelit tersedia di negara atau rantau ini, hidupkan tetapan lokasi"
"Sediakan Buka Kunci Cap Jari sekali lagi"
"%s tidak dapat dicam lagi."
"%1$s dan %2$s tidak dapat dicam lagi."
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index 9e7e78f98c6421b9875855505bffd8bf55f59353..e4c2acaba9f5f7b78384fce7fabba40e5ad41cd5 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -612,6 +612,10 @@
"အနီးရှိ ‘အလွန်ကျယ်ပြန့်သော လှိုင်းအလျားသုံးစက်များ’ ကြား မှန်းခြေနေရာကို သတ်မှတ်ရန် အက်ပ်ကို ခွင့်ပြုမည်"
"အနီးရှိ Wi-Fi စက်များနှင့် ပြန်လှန်တုံ့ပြန်ခြင်း"
"ကြော်ငြာရန်၊ ချိတ်ဆက်ရန်နှင့် အနီးတစ်ဝိုက်ရှိ Wi-Fi စက်များ၏ နေရာကို သတ်မှတ်ရန် အက်ပ်ကို ခွင့်ပြုသည်"
+
+
+
+
"ဦးစားပေး NFC ငွေပေးချေမှုဆိုင်ရာ ဝန်ဆောင်မှု အချက်အလက်များ"
"အက်ပ်အား ဦစားပေး NFC ငွေပေးချေမှုဆိုင်ရာ ဝန်ဆောင်မှု အချက်အလက်များဖြစ်သည့် မှတ်ပုံတင်ထားသော အကူအညီများနှင့် သွားလာရာ လမ်းကြောင်းတို့ကို ရယူရန် ခွင့်ပြုသည်။"
"Near Field Communicationအား ထိန်းချုပ်ရန်"
@@ -2431,54 +2435,30 @@
"ဖွင့်ရန်"
"နောက်သို့"
"ဆိုင်းငံ့ထားသည်…"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "Satellite SOS ကို ယခုသုံးနိုင်ပြီ"
+ "မိုဘိုင်း (သို့) Wi-Fi ကွန်ရက် မရှိပါက အရေးပေါ်ဝန်ဆောင်မှု ဌာနများသို့ မက်ဆေ့ဂျ်ပို့နိုင်သည်။ Google Messages သည် သင်၏ မူရင်းမက်ဆေ့ဂျ်ပို့ရန်အက်ပ် ဖြစ်ရမည်။"
+ "Satellite SOS ကို ပံ့ပိုးမထားပါ"
+ "Satellite SOS ကို ဤစက်တွင် ပံ့ပိုးမထားပါ"
+ "Satellite SOS ကို စနစ်ထည့်သွင်းမထားပါ"
+ "အင်တာနက်နှင့် ချိတ်ဆက်ထားခြင်း ရှိ၊ မရှိ စစ်ဆေးပြီး စနစ်ထပ်မံထည့်သွင်းကြည့်ပါ"
+ "Satellite SOS မရနိုင်ပါ"
+ "Satellite SOS ကို ဤနိုင်ငံ (သို့) ဒေသတွင် မရနိုင်ပါ"
+ "Satellite SOS ကို စနစ်ထည့်သွင်းမထားပါ"
+ "ဂြိုဟ်တုမှတစ်ဆင့် မက်ဆေ့ဂျ်ပို့ရန် Google Messages ကို သင်၏ မက်ဆေ့ဂျ်ပို့ရန် မူရင်းအက်ပ်အဖြစ် သတ်မှတ်ပါ"
+ "Satellite SOS မရနိုင်ပါ"
+ "satellite SOS ကို ဤနိုင်ငံ (သို့) ဒေသတွင် ရနိုင်ခြင်းရှိ၊ မရှိ စစ်ဆေးရန် တည်နေရာပြ ဆက်တင်များကို ဖွင့်ပါ"
+ "ဂြိုဟ်တုမှတစ်ဆင့် မက်ဆေ့ဂျ်ပို့ခြင်း ရနိုင်သည်"
+ "မိုဘိုင်း (သို့) Wi-Fi ကွန်ရက် မရှိသည့်အခါ ဂြိုဟ်တုမှတစ်ဆင့် မက်ဆေ့ဂျ်ပို့နိုင်သည်။ Google Messages သည် သင်၏ မူရင်းမက်ဆေ့ဂျ်ပို့ရန်အက်ပ် ဖြစ်ရမည်။"
+ "ဂြိုဟ်တုမှတစ်ဆင့် မက်ဆေ့ဂျ်ပို့ခြင်းကို ပံ့ပိုးမထားပါ"
+ "ဂြိုဟ်တုမှတစ်ဆင့် မက်ဆေ့ဂျ်ပို့ခြင်းကို ဤစက်တွင် ပံ့ပိုးမထားပါ"
+ "ဂြိုဟ်တုမှတစ်ဆင့် မက်ဆေ့ဂျ်ပို့ခြင်းကို စနစ်ထည့်သွင်းမထားပါ"
+ "အင်တာနက်နှင့် ချိတ်ဆက်ထားခြင်း ရှိ၊ မရှိ စစ်ဆေးပြီး စနစ်ထပ်မံထည့်သွင်းကြည့်ပါ"
+ "ဂြိုဟ်တုမှတစ်ဆင့် မက်ဆေ့ဂျ်ပို့ခြင်းကို မရနိုင်ပါ"
+ "ဂြိုဟ်တုမှတစ်ဆင့် မက်ဆေ့ဂျ်ပို့ခြင်းကို ဤနိုင်ငံ (သို့) ဒေသတွင် မရနိုင်ပါ"
+ "ဂြိုဟ်တုမှတစ်ဆင့် မက်ဆေ့ဂျ်ပို့ခြင်းကို စနစ်ထည့်သွင်းမထားပါ"
+ "ဂြိုဟ်တုမှတစ်ဆင့် မက်ဆေ့ဂျ်ပို့ရန် Google Messages ကို သင်၏ မက်ဆေ့ဂျ်ပို့ရန် မူရင်းအက်ပ်အဖြစ် သတ်မှတ်ပါ"
+ "ဂြိုဟ်တုမှတစ်ဆင့် မက်ဆေ့ဂျ်ပို့ခြင်းကို မရနိုင်ပါ"
+ "ဂြိုဟ်တုမှတစ်ဆင့် မက်ဆေ့ဂျ်ပို့ခြင်းကို ဤနိုင်ငံ (သို့) ဒေသတွင် ရနိုင်ခြင်းရှိ၊ မရှိ စစ်ဆေးရန် တည်နေရာပြ ဆက်တင်များကို ဖွင့်ပါ"
"‘လက်ဗွေသုံး လော့ခ်ဖွင့်ခြင်း’ ကို စနစ်ထပ်မံထည့်သွင်းပါ"
"%s ကို မသိရှိနိုင်တော့ပါ။"
"%1$s နှင့် %2$s ကို မသိရှိနိုင်တော့ပါ။"
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 683ca2661b6b42b4a1e88976fad737d71e87656d..ec4cd961faee2787cde8e28c7921ef5ee9922a08 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -612,6 +612,10 @@
"tillate at appen fastslår den relative posisjonen mellom enheter i nærheten som bruker ultrabredbånd"
"samhandle med wifi-enheter i nærheten"
"Lar appen annonsere, koble til og fastslå den relative posisjonen til wifi-enheter i nærheten"
+
+
+
+
"Informasjon om prioritert NFC-betalingstjeneste"
"Gir appen tilgang til informasjon om prioritert NFC-betalingstjeneste, for eksempel registrerte hjelpemidler og destinasjon."
"kontroller overføring av data med NFC-teknologi"
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index ffeecb1cf0ba03f7949cd6b52ad1aacb1709c555..0dc0bd3d04a982756888d352a73b11877ba676c0 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -293,7 +293,7 @@
"खाताको स्थिति"
"विकासकर्ताका म्यासेजहरू"
"विकासकर्तासम्बन्धी महत्त्वपूर्ण म्यासेजहरू"
- "अद्यावधिकहरू"
+ "अपडेटहरू"
"नेटवर्कको स्थिति"
"नेटवर्कका अलर्टहरू"
"नेटवर्क उपलब्ध छ"
@@ -612,6 +612,10 @@
"यो एपलाई नजिकै रहेका अल्ट्रा-वाइडब्यान्ड चल्ने डिभाइसहरूबिचको तुलनात्मक स्थान पत्ता लगाउन दिनुहोस्"
"Wi-Fi चल्ने नजिकै रहेका डिभाइसहरूमा चलाउन दिन्छ"
"यसले एपलाई Wi-Fi चल्ने नजिकै रहेका डिभाइसहरूमा विज्ञापन गर्न, कनेक्ट गर्न र सापेक्ष स्थिति निर्धारण गर्न दिन्छ"
+
+
+
+
"NFC भुक्तानी सेवासम्बन्धी रुचाइएको जानकारी"
"यसले एपलाई दर्ता गरिएका सहायता तथा मार्गको गन्तव्य जस्ता रुचाइएका NFC भुक्तानी सेवासम्बन्धी जानकारी प्राप्त गर्न दिन्छ।"
"नजिक क्षेत्र संचार नियन्त्रणहरू"
@@ -2431,54 +2435,30 @@
"अन गर्नुहोस्"
"पछाडि जानुहोस्"
"विचाराधीन..."
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "स्याटलाइट SOS अब उपलब्ध भएको छ"
+ "मोबाइल वा Wi-Fi नेटवर्क नभएका खण्डमा तपाईं आपत्कालीन सेवामा म्यासेज पठाउन सक्नुहुन्छ। Google Messages अनिवार्य रूपमा तपाईंको डिफल्ट म्यासेजिङ एप हुनु पर्छ।"
+ "स्याटलाइट SOS प्रयोग गर्न मिल्दैन"
+ "यो डिभाइसमा स्याटलाइट SOS प्रयोग गर्न मिल्दैन"
+ "स्याटलाइट SOS सेटअप गरिएको छैन"
+ "तपाईंको डिभाइस इन्टरनेटमा कनेक्ट गरिएको छ भन्ने कुरा सुनिश्चित गर्नुहोस् र फेरि सेटअप गरी हेर्नुहोस्"
+ "स्याटलाइट SOS उपलब्ध छैन"
+ "यो देश वा क्षेत्रमा स्याटलाइट SOS उपलब्ध छैन"
+ "स्याटलाइट SOS सेटअप गरिएको छैन"
+ "स्याटलाइटमार्फत म्यासेज पठाउन Google Messages लाई डिफल्ट म्यासेजिङ एपका रूपमा सेट गर्नुहोस्"
+ "स्याटलाइट SOS उपलब्ध छैन"
+ "यो देश वा क्षेत्रमा स्याटलाइट SOS उपलब्ध छ कि छैन भन्ने कुरा जाँच्न लोकेसन सेटिङ अन गर्नुहोस्"
+ "स्याटलाइटमार्फत म्यासेज पठाउने सुविधा उपलब्ध छ"
+ "तपाईं मोबाइल वा Wi-Fi नेटवर्क उपलब्ध नभएका खण्डमा स्याटलाइटमार्फत म्यासेज पठाउन सक्नुहुन्छ। Google Messages अनिवार्य रूपमा तपाईंको डिफल्ट म्यासेजिङ एप हुनु पर्छ।"
+ "स्याटलाइटमार्फत म्यासेज पठाउने सुविधा प्रयोग गर्न मिल्दैन"
+ "यो डिभाइसमा स्याटलाइटमार्फत म्यासेज पठाउने सुविधा प्रयोग गर्न मिल्दैन"
+ "स्याटलाइटमार्फत म्यासेज पठाउने सुविधा सेटअप गरिएको छैन"
+ "तपाईंको डिभाइस इन्टरनेटमा कनेक्ट गरिएको छ भन्ने कुरा सुनिश्चित गर्नुहोस् र फेरि सेटअप गरी हेर्नुहोस्"
+ "स्याटलाइटमार्फत म्यासेज पठाउने सुविधा उपलब्ध छैन"
+ "यो देश वा क्षेत्रमा स्याटलाइटमार्फत म्यासेज पठाउने सुविधा उपलब्ध छैन"
+ "स्याटलाइटमार्फत म्यासेज पठाउने सुविधा सेटअप गरिएको छैन"
+ "स्याटलाइटमार्फत म्यासेज पठाउन Google Messages लाई डिफल्ट म्यासेजिङ एपका रूपमा सेट गर्नुहोस्"
+ "स्याटलाइटमार्फत म्यासेज पठाउने सुविधा उपलब्ध छैन"
+ "यो देश वा क्षेत्रमा स्याटलाइटमार्फत म्यासेज पठाउने सुविधा उपलब्ध छ कि छैन भन्ने कुरा जाँच्न लोकेसन सेटिङ अन गर्नुहोस्"
"फिंगरप्रिन्ट अनलक फेरि सेटअप गर्नुहोस्"
"%s अब पहिचान गर्न सकिँदैन।"
"%1$s र %2$s अब पहिचान गर्न सकिँदैन।"
diff --git a/core/res/res/values-night/colors_dynamic.xml b/core/res/res/values-night/colors_dynamic.xml
new file mode 100644
index 0000000000000000000000000000000000000000..7e95ff4f409e492c9260dd2d9b027a24ac6e9c18
--- /dev/null
+++ b/core/res/res/values-night/colors_dynamic.xml
@@ -0,0 +1,103 @@
+
+
+
+
+
+ @color/system_background_dark
+ @color/system_control_activated_dark
+ @color/system_control_highlight_dark
+ @color/system_control_normal_dark
+ @color/system_error_dark
+ @color/system_error_container_dark
+ @color/system_inverse_on_surface_dark
+ @color/system_inverse_primary_dark
+ @color/system_inverse_surface_dark
+ @color/system_on_background_dark
+ @color/system_on_error_dark
+ @color/system_on_error_container_dark
+ @color/system_on_primary_dark
+ @color/system_on_primary_container_dark
+ @color/system_on_secondary_dark
+ @color/system_on_secondary_container_dark
+ @color/system_on_surface_dark
+ @color/system_on_surface_variant_dark
+ @color/system_on_tertiary_dark
+ @color/system_on_tertiary_container_dark
+ @color/system_outline_dark
+ @color/system_outline_variant_dark
+ @color/system_palette_key_color_neutral_dark
+ @color/system_palette_key_color_neutral_variant_dark
+ @color/system_palette_key_color_primary_dark
+ @color/system_palette_key_color_secondary_dark
+ @color/system_palette_key_color_tertiary_dark
+ @color/system_primary_dark
+ @color/system_primary_container_dark
+ @color/system_scrim_dark
+ @color/system_secondary_dark
+ @color/system_secondary_container_dark
+ @color/system_shadow_dark
+ @color/system_surface_dark
+ @color/system_surface_bright_dark
+ @color/system_surface_container_dark
+ @color/system_surface_container_high_dark
+ @color/system_surface_container_highest_dark
+ @color/system_surface_container_low_dark
+ @color/system_surface_container_lowest_dark
+ @color/system_surface_dim_dark
+ @color/system_surface_tint_dark
+ @color/system_surface_variant_dark
+ @color/system_tertiary_dark
+ @color/system_tertiary_container_dark
+ @color/system_text_hint_inverse_dark
+ @color/system_text_primary_inverse_dark
+ @color/system_text_primary_inverse_disable_only_dark
+ @color/system_text_secondary_and_tertiary_inverse_dark
+ @color/system_text_secondary_and_tertiary_inverse_disabled_dark
+ @color/system_on_primary_fixed
+ @color/system_on_primary_fixed_variant
+ @color/system_on_secondary_fixed
+ @color/system_on_secondary_fixed_variant
+ @color/system_on_tertiary_fixed
+ @color/system_on_tertiary_fixed_variant
+ @color/system_primary_fixed
+ @color/system_primary_fixed_dim
+ @color/system_secondary_fixed
+ @color/system_secondary_fixed_dim
+ @color/system_tertiary_fixed
+ @color/system_tertiary_fixed_dim
+ @color/system_brand_a_dark
+ @color/system_brand_b_dark
+ @color/system_brand_c_dark
+ @color/system_brand_d_dark
+ @color/system_clock_hour_dark
+ @color/system_clock_minute_dark
+ @color/system_clock_second_dark
+ @color/system_on_shade_active_dark
+ @color/system_on_shade_active_variant_dark
+ @color/system_on_shade_inactive_dark
+ @color/system_on_shade_inactive_variant_dark
+ @color/system_on_theme_app_dark
+ @color/system_overview_background_dark
+ @color/system_shade_active_dark
+ @color/system_shade_disabled_dark
+ @color/system_shade_inactive_dark
+ @color/system_theme_app_dark
+ @color/system_theme_app_ring_dark
+ @color/system_theme_notif_dark
+ @color/system_under_surface_dark
+ @color/system_weather_temp_dark
+ @color/system_widget_background_dark
+
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 5f77e7304cdbfb7b41d2281a643d64e57ec3662e..e553347407786187e8549b6566e2c6c3624dab48 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -612,6 +612,10 @@
"De app toestaan om de relatieve positie tussen ultrabreedbandapparaten in de buurt te bepalen"
"interactie met wifi-apparaten in de buurt"
"Hiermee kan de app uitzenden, verbindingen maken en de relatieve positie bepalen van wifi-apparaten in de buurt"
+
+
+
+
"Informatie over voorkeursservice voor NFC-betaling"
"Hiermee kun je zorgen dat de app informatie krijgt over de voorkeursservice voor NFC-betaling, zoals geregistreerde hulpmiddelen en routebestemmingen."
"Near Field Communication regelen"
@@ -2431,54 +2435,30 @@
"Aanzetten"
"Terug"
"In behandeling…"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "SOS via satelliet is nu beschikbaar"
+ "Je kunt berichten sturen naar de hulpdiensten als er geen mobiel of wifi-netwerk beschikbaar is. Google Berichten moet je standaard berichten-app zijn."
+ "SOS via satelliet wordt niet ondersteund"
+ "SOS via satelliet wordt niet ondersteund op dit apparaat"
+ "SOS via satelliet is niet ingesteld"
+ "Zorg dat je verbinding hebt met internet en probeer het opnieuw"
+ "SOS via satelliet is niet beschikbaar"
+ "SOS via satelliet is niet beschikbaar in dit land of deze regio"
+ "SOS via satelliet niet ingesteld"
+ "Stel Google Berichten in als je standaard berichten-app om via satelliet berichten te sturen"
+ "SOS via satelliet is niet beschikbaar"
+ "Zet locatie-instellingen aan om te checken of SOS via satelliet beschikbaar is in dit land of deze regio"
+ "Satellietberichten beschikbaar"
+ "Je kunt via satelliet berichten sturen als er geen mobiel of wifi-netwerk beschikbaar is. Google Berichten moet je standaard berichten-app zijn."
+ "Satellietberichten niet ondersteund"
+ "Satellietberichten worden niet ondersteund op dit apparaat"
+ "Satellietberichten niet ingesteld"
+ "Zorg dat je verbinding hebt met internet en probeer het opnieuw"
+ "Satellietberichten niet beschikbaar"
+ "Satellietberichten zijn niet beschikbaar in dit land of deze regio"
+ "Satellietberichten niet ingesteld"
+ "Stel Google Berichten in als je standaard berichten-app om via satelliet berichten te sturen"
+ "Satellietberichten niet beschikbaar"
+ "Zet locatie-instellingen aan om te checken of satellietberichten beschikbaar zijn in dit land of deze regio"
"Ontgrendelen met vingerafdruk weer instellen"
"%s wordt niet meer herkend."
"%1$s en %2$s worden niet meer herkend."
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
index b4f924b7d9dbf2b07bf7db75bd4a17dd8bc6b303..2515bb5052eb798c460e0811bba1847f2151ea42 100644
--- a/core/res/res/values-or/strings.xml
+++ b/core/res/res/values-or/strings.xml
@@ -612,6 +612,10 @@
"ଆଖପାଖର ଅଲଟ୍ରା-ୱାଇଡବ୍ୟାଣ୍ଡ ଡିଭାଇସଗୁଡ଼ିକ ମଧ୍ୟରେ ଆପେକ୍ଷିକ ଅବସ୍ଥିତିକୁ ନିର୍ଦ୍ଧାରଣ କରିବା ପାଇଁ ଆପକୁ ଅନୁମତି ଦିଅନ୍ତୁ"
"ଆଖପାଖର ୱାଇ-ଫାଇ ଡିଭାଇସଗୁଡ଼ିକ ସହ ଇଣ୍ଟରାକ୍ଟ କରନ୍ତୁ"
"ଆଖପାଖର ୱାଇ-ଫାଇ ଡିଭାଇସରେ ବିଜ୍ଞାପନ ଦେବା, ତା ସହ ସଂଯୋଗ କରିବା ଓ ତା’ର ଆପେକ୍ଷିକ ଅବସ୍ଥିତି ନିର୍ଦ୍ଧାରଣ କରିବା ପାଇଁ ଆପକୁ ଅନୁମତି ଦିଏ"
+
+
+
+
"ପସନ୍ଦର NFC ପେମେଣ୍ଟ ସେବା ସୂଚନା"
"ପଞ୍ଜିକୃତ ଯନ୍ତ୍ର ଏବଂ ମାର୍ଗ ଲକ୍ଷସ୍ଥଳ ପରି ପସନ୍ଦର nfc ପେମେଣ୍ଟ ସେବା ସୂଚନା ପାଇବାକୁ ଆପ୍ ଅନୁମତି କରିଥାଏ।"
"ନିଅର୍ ଫିଲ୍ଡ କମ୍ୟୁନିକେଶନ୍ ଉପରେ ନିୟନ୍ତ୍ରଣ ରଖନ୍ତୁ"
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index fae806c4decab7d8afeedbaa6b86ac0903b584fc..574d991b9dfcaf34fb842fbb57d6e8ce21ad014c 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -612,6 +612,10 @@
"ਐਪ ਨੂੰ ਨਜ਼ਦੀਕੀ ਅਲਟ੍ਰਾ-ਵਾਈਡਬੈਂਡ ਡੀਵਾਈਸਾਂ ਦੇ ਵਿਚਾਲੇ ਸੰਬੰਧਿਤ ਸਥਿਤੀ ਨੂੰ ਨਿਰਧਾਰਿਤ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਦਿਓ"
"ਨਜ਼ਦੀਕੀ ਵਾਈ-ਫਾਈ ਡੀਵਾਈਸਾਂ ਨਾਲ ਅੰਤਰਕਿਰਿਆ ਕਰੋ"
"ਐਪ ਨੂੰ ਨਜ਼ਦੀਕੀ ਵਾਈ-ਫਾਈ ਡੀਵਾਈਸਾਂ \'ਤੇ ਵਿਗਿਆਪਨ ਦੇਣ, ਕਨੈਕਟ ਕਰਨ ਅਤੇ ਉਨ੍ਹਾਂ ਦੀ ਸੰਬੰਧਿਤ ਸਥਿਤੀ ਨੂੰ ਨਿਰਧਾਰਿਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੱਤੀ ਜਾਂਦੀ ਹੈ"
+
+
+
+
"ਤਰਜੀਹੀ NFC ਭੁਗਤਾਨਸ਼ੁਦਾ ਸੇਵਾ ਜਾਣਕਾਰੀ"
"ਐਪ ਨੂੰ ਤਰਜੀਹੀ NFC ਭੁਗਤਾਨਸ਼ੁਦਾ ਸੇਵਾ ਜਾਣਕਾਰੀ ਪ੍ਰਾਪਤ ਕਰਨ ਦਿੰਦਾ ਹੈ ਜਿਵੇਂ ਕਿ ਰਜਿਸਟਰ ਕੀਤੇ ਸਾਧਨ ਅਤੇ ਮੰਜ਼ਿਲ ਰਸਤਾ।"
"ਨਜ਼ਦੀਕੀ ਖੇਤਰ ਸੰਚਾਰ ਤੇ ਨਿਯੰਤਰਣ ਪਾਓ"
@@ -2431,54 +2435,30 @@
"ਚਾਲੂ ਕਰੋ"
"ਵਾਪਸ ਜਾਓ"
"ਵਿਚਾਰ-ਅਧੀਨ..."
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "ਸੈਟੇਲਾਈਟ SOS ਦੀ ਸੁਵਿਧਾ ਹੁਣ ਉਪਲਬਧ ਹੈ"
+ "ਮੋਬਾਈਲ ਜਾਂ ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕ ਨਾ ਹੋਣ \'ਤੇ, ਤੁਸੀਂ ਐਮਰਜੈਂਸੀ ਸੇਵਾਵਾਂ ਨੂੰ ਸੁਨੇਹਾ ਭੇਜ ਸਕਦੇ ਹੋ। Google Messages ਤੁਹਾਡੀ ਪੂਰਵ-ਨਿਰਧਾਰਿਤ ਸੁਨੇਹਾ ਐਪ ਹੋਣੀ ਲਾਜ਼ਮੀ ਹੈ।"
+ "ਸੈਟੇਲਾਈਟ SOS ਦੀ ਸੁਵਿਧਾ ਸਮਰਥਿਤ ਨਹੀਂ ਹੈ"
+ "ਸੈਟੇਲਾਈਟ SOS ਦੀ ਸੁਵਿਧਾ ਇਸ ਡੀਵਾਈਸ \'ਤੇ ਸਮਰਥਿਤ ਨਹੀਂ ਹੈ"
+ "ਸੈਟੇਲਾਈਟ SOS ਦੀ ਸੁਵਿਧਾ ਦਾ ਸੈੱਟ ਅੱਪ ਨਹੀਂ ਕੀਤਾ ਗਿਆ ਹੈ"
+ "ਪੱਕਾ ਕਰੋ ਕਿ ਤੁਸੀਂ ਇੰਟਰਨੈੱਟ ਨਾਲ ਕਨੈਕਟ ਹੋ ਅਤੇ ਦੁਬਾਰਾ ਸੈੱਟਅੱਪ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕਰੋ"
+ "ਸੈਟੇਲਾਈਟ SOS ਦੀ ਸੁਵਿਧਾ ਉਪਲਬਧ ਨਹੀਂ ਹੈ"
+ "ਸੈਟੇਲਾਈਟ SOS ਦੀ ਸੁਵਿਧਾ ਇਸ ਦੇਸ਼ ਜਾਂ ਖੇਤਰ ਵਿੱਚ ਉਪਲਬਧ ਨਹੀਂ ਹੈ"
+ "ਸੈਟੇਲਾਈਟ SOS ਦੀ ਸੁਵਿਧਾ ਦਾ ਸੈੱਟ ਅੱਪ ਨਹੀਂ ਹੋਇਆ"
+ "ਸੈਟੇਲਾਈਟ ਰਾਹੀਂ ਸੁਨੇਹਾ ਭੇਜਣ ਲਈ, Google Messages ਨੂੰ ਆਪਣੀ ਪੂਰਵ-ਨਿਰਧਾਰਿਤ ਸੁਨੇਹਾ ਐਪ ਵਜੋਂ ਸੈੱਟ ਕਰੋ"
+ "ਸੈਟੇਲਾਈਟ SOS ਦੀ ਸੁਵਿਧਾ ਉਪਲਬਧ ਨਹੀਂ ਹੈ"
+ "ਇਸਦੀ ਜਾਂਚ ਕਰਨ ਲਈ ਕਿ ਇਸ ਦੇਸ਼ ਜਾਂ ਖੇਤਰ ਵਿੱਚ ਸੈਟੇਲਾਈਟ SOS ਦੀ ਸੁਵਿਧਾ ਉਪਲਬਧ ਹੈ, ਟਿਕਾਣਾ ਸੈਟਿੰਗਾਂ ਨੂੰ ਚਾਲੂ ਕਰੋ"
+ "ਸੈਟੇਲਾਈਟ ਸੁਨੇਹੇ ਦੀ ਸੁਵਿਧਾ ਉਪਲਬਧ ਹੈ"
+ "ਮੋਬਾਈਲ ਜਾਂ ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕ ਨਾ ਹੋਣ \'ਤੇ, ਤੁਸੀਂ ਸੈਟੇਲਾਈਟ ਰਾਹੀਂ ਸੁਨੇਹੇ ਭੇਜ ਸਕਦੇ ਹੋ। Google Messages ਤੁਹਾਡੀ ਪੂਰਵ-ਨਿਰਧਾਰਿਤ ਸੁਨੇਹਾ ਐਪ ਹੋਣੀ ਲਾਜ਼ਮੀ ਹੈ।"
+ "ਸੈਟੇਲਾਈਟ ਸੁਨੇਹੇ ਦੀ ਸੁਵਿਧਾ ਸਮਰਥਿਤ ਨਹੀਂ ਹੈ"
+ "ਸੈਟੇਲਾਈਟ ਸੁਨੇਹੇ ਦੀ ਸੁਵਿਧਾ ਇਸ ਡੀਵਾਈਸ \'ਤੇ ਸਮਰਥਿਤ ਨਹੀਂ ਹੈ"
+ "ਸੈਟੇਲਾਈਟ ਸੁਨੇਹੇ ਦੀ ਸੁਵਿਧਾ ਦਾ ਸੈੱਟਅੱਪ ਨਹੀਂ ਕੀਤਾ ਗਿਆ ਹੈ"
+ "ਪੱਕਾ ਕਰੋ ਕਿ ਤੁਸੀਂ ਇੰਟਰਨੈੱਟ ਨਾਲ ਕਨੈਕਟ ਹੋ ਅਤੇ ਦੁਬਾਰਾ ਸੈੱਟਅੱਪ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕਰੋ"
+ "ਸੈਟੇਲਾਈਟ ਸੁਨੇਹੇ ਦੀ ਸੁਵਿਧਾ ਉਪਲਬਧ ਨਹੀਂ ਹੈ"
+ "ਇਸ ਦੇਸ਼ ਜਾਂ ਖੇਤਰ ਵਿੱਚ ਸੈਟੇਲਾਈਟ ਸੁਨੇਹੇ ਦੀ ਸੁਵਿਧਾ ਉਪਲਬਧ ਨਹੀਂ ਹੈ"
+ "ਸੈਟੇਲਾਈਟ ਸੁਨੇਹੇ ਦੀ ਸੁਵਿਧਾ ਦਾ ਸੈੱਟਅੱਪ ਨਹੀਂ ਕੀਤਾ ਗਿਆ ਹੈ"
+ "ਸੈਟੇਲਾਈਟ ਰਾਹੀਂ ਸੁਨੇਹਾ ਭੇਜਣ ਲਈ, Google Messages ਨੂੰ ਆਪਣੀ ਪੂਰਵ-ਨਿਰਧਾਰਿਤ ਸੁਨੇਹਾ ਐਪ ਵਜੋਂ ਸੈੱਟ ਕਰੋ"
+ "ਸੈਟੇਲਾਈਟ ਸੁਨੇਹੇ ਦੀ ਸੁਵਿਧਾ ਉਪਲਬਧ ਨਹੀਂ ਹੈ"
+ "ਇਹ ਜਾਂਚ ਕਰਨ ਲਈ ਕਿ ਇਸ ਦੇਸ਼ ਜਾਂ ਖੇਤਰ ਵਿੱਚ ਸੈਟੇਲਾਈਟ ਸੁਨੇਹੇ ਦੀ ਸੁਵਿਧਾ ਉਪਲਬਧ ਹੈ ਜਾਂ ਨਹੀਂ, ਟਿਕਾਣਾ ਸੈਟਿੰਗਾਂ ਨੂੰ ਚਾਲੂ ਕਰੋ"
"ਫਿੰਗਰਪ੍ਰਿੰਟ ਅਣਲਾਕ ਦਾ ਦੁਬਾਰਾ ਸੈੱਟਅੱਪ ਕਰੋ"
"%s ਦੀ ਹੁਣ ਪਛਾਣ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕਦੀ।"
"%1$s ਅਤੇ %2$s ਦੀ ਹੁਣ ਪਛਾਣ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕਦੀ।"
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index cf758feb97ae182e9d4b3ca0695aeacdc20958b1..f267877b3a18f3e4e13952f620abe5b660cb795a 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -590,7 +590,7 @@
"Pozwala aplikacji na odbieranie pakietów wysyłanych przez sieć Wi-Fi do wszystkich urządzeń, a nie tylko do Twojego tabletu, przy użyciu adresów połączeń grupowych. Powoduje większe zapotrzebowanie na energię niż w trybie innym niż grupowy."
"Pozwala aplikacji odbierać pakiety wysyłane przez sieć Wi-Fi do wszystkich urządzeń (a nie tylko do Twojego urządzenia z Androidem TV) przy użyciu adresów połączeń grupowych. Powoduje większe zapotrzebowanie na energię niż w innych trybach."
"Pozwala aplikacji na odbieranie pakietów wysyłanych przez sieć Wi-Fi do wszystkich urządzeń, a nie tylko do Twojego telefonu, przy użyciu adresów połączeń grupowych. Powoduje większe zapotrzebowanie na energię niż w trybie innym niż grupowy."
- "uzyskiwanie dostępu do ustawień Bluetooth"
+ "uzyskiwanie dostępu do ustawień Bluetootha"
"Pozwala aplikacji na konfigurowanie lokalnego tabletu z funkcją Bluetooth oraz na wykrywanie urządzeń zdalnych i parowanie z nimi."
"Pozwala aplikacji konfigurować Bluetootha na urządzeniu z Androidem TV oraz wykrywać urządzenia zdalne i przeprowadzać parowanie z nimi."
"Pozwala aplikacji na konfigurowanie lokalnego telefonu z funkcją Bluetooth oraz na wykrywanie urządzeń zdalnych i parowanie z nimi."
@@ -614,6 +614,10 @@
"Zezwól na określanie przez aplikację względnego położenia urządzeń ultraszerokopasmowych w pobliżu"
"interakcje z urządzeniami Wi-Fi w pobliżu"
"Zezwala aplikacji na przesyłanie informacji o sobie, łączenie się z urządzeniami Wi‑Fi w pobliżu i określanie ich względnego położenia"
+
+
+
+
"Informacje o preferowanych usługach płatniczych NFC"
"Pozwala aplikacji uzyskiwać informacje o preferowanych usługach płatniczych NFC, np. zarejestrowanych pomocach i miejscach docelowych tras."
"kontrolowanie łączności Near Field Communication"
@@ -2433,54 +2437,30 @@
"Włącz"
"Wróć"
"Oczekiwanie…"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "Satelitarne połączenie alarmowe jest już dostępne"
+ "Możesz wysłać wiadomość do służb ratunkowych, jeśli masz problem z połączeniem się z siecią komórkową lub Wi-Fi. Wiadomości Google muszą być domyślną aplikacją do SMS-ów."
+ "Satelitarne połączenie alarmowe nie jest obsługiwane"
+ "To urządzenie nie obsługuje satelitarnego połączenia alarmowego"
+ "Satelitarne połączenie alarmowe nie jest skonfigurowane"
+ "Upewnij się, że masz połączenie z internetem, i spróbuj ponownie"
+ "Satelitarne połączenie alarmowe nie jest dostępne"
+ "Satelitarne połączenie alarmowe nie jest dostępne w tym kraju lub regionie"
+ "Satelitarne połączenie alarmowe nie zostało skonfigurowane"
+ "Aby wysyłać wiadomości przez satelitę, ustaw Wiadomości Google jako domyślną aplikację do obsługi SMS-ów"
+ "Satelitarne połączenie alarmowe nie jest dostępne"
+ "Aby sprawdzić, czy satelitarne połączenie alarmowe jest dostępne w tym kraju lub regionie, włącz ustawienia lokalizacji"
+ "Przesyłanie wiadomości przez satelitę jest dostępne"
+ "Możesz wysyłać wiadomości przez satelitę, jeśli nie masz dostępu do sieci komórkowej lub Wi-Fi. Wiadomości Google muszą być domyślną aplikacją do SMS-ów."
+ "Przesyłanie wiadomości przez satelitę nie jest obsługiwane"
+ "To urządzenie nie obsługuje przesyłania wiadomości przez satelitę"
+ "Nie skonfigurowano przesyłania wiadomości przez satelitę"
+ "Upewnij się, że masz połączenie z internetem, i spróbuj ponownie"
+ "Przesyłanie wiadomości przez satelitę jest niedostępne"
+ "Przesyłanie wiadomości przez satelitę nie jest dostępne w tym kraju lub regionie"
+ "Nie skonfigurowano przesyłania wiadomości przez satelitę"
+ "Aby wysyłać wiadomości przez satelitę, ustaw Wiadomości Google jako domyślną aplikację do obsługi SMS-ów"
+ "Przesyłanie wiadomości przez satelitę jest niedostępne"
+ "Aby sprawdzić, czy przesyłanie wiadomości przez satelitę jest dostępne w tym kraju lub regionie, włącz ustawienia lokalizacji"
"Skonfiguruj ponownie odblokowywanie odciskiem palca"
"Ten odcisk palca (%s) nie jest już rozpoznawany."
"Te odciski palców (%1$s i %2$s) nie są już rozpoznawane."
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index 71b334e89eafc796d4b2aed3d69fd3221e5399e4..1719648d10f04e31ae41cae3387ffdbe7b3ffca3 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -613,6 +613,10 @@
"Permitir que o app determine o posicionamento relativo entre dispositivos de banda ultralarga por perto"
"interagir com dispositivos Wi-Fi por perto"
"Permite que o app divulgue, faça conexão e determine a posição relativa de dispositivos Wi-Fi por perto."
+
+
+
+
"Informações preferidas de serviço de pagamento por NFC"
"Permite que o app acesse as informações preferidas de serviço de pagamento por NFC, como auxílios registrados ou destinos de trajetos."
"controlar a comunicação a curta distância"
@@ -1755,7 +1759,7 @@
"Usar atalho"
"Inversão de cores"
"Correção de cor"
- "Modo uma mão"
+ "Modo para uma mão"
"Escurecer ainda mais a tela"
"Aparelhos auditivos"
"Teclas de volume pressionadas. Serviço %1$s ativado."
@@ -2432,54 +2436,30 @@
"Ativar"
"Voltar"
"Pendente…"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "O SOS via satélite já está disponível"
+ "Você poderá enviar uma mensagem para serviços de emergência se não houver uma rede móvel ou Wi-Fi. O Google Mensagens precisa ser seu app de mensagens padrão."
+ "Incompatível com o SOS via satélite"
+ "Este dispositivo não é compatível com o SOS via satélite"
+ "O SOS via satélite não foi configurado"
+ "Verifique sua conexão de Internet e tente configurar de novo"
+ "SOS via satélite indisponível"
+ "O SOS via satélite não está disponível neste país ou região"
+ "SOS via satélite não configurado"
+ "Para enviar mensagens via satélite, defina o Google Mensagens como seu app de mensagens padrão"
+ "SOS via satélite indisponível"
+ "Para verificar se o SOS via satélite está disponível neste país ou região, ative as configurações de localização"
+ "Mensagem via satélite disponível"
+ "É possível trocar mensagens por satélite caso não haja uma rede móvel ou Wi-Fi. O Google Mensagens precisa ser seu app de mensagens padrão."
+ "Incompatível com mensagem via satélite"
+ "Este dispositivo não é compatível com mensagem via satélite"
+ "Mensagem via satélite não configurada"
+ "Verifique sua conexão de Internet e tente configurar de novo"
+ "Mensagem via satélite indisponível"
+ "A mensagem via satélite não está disponível neste país ou região"
+ "Mensagem via satélite não configurada"
+ "Para enviar mensagens via satélite, defina o Google Mensagens como seu app de mensagens padrão"
+ "Mensagem via satélite indisponível"
+ "Para verificar se a mensagem via satélite está disponível neste país ou região, ative as configurações de localização"
"Configurar o Desbloqueio por impressão digital de novo"
"A impressão digital %s não é mais reconhecida."
"As impressões digitais %1$s e %2$s não são mais reconhecidas."
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 4d5ff474c84f90be2ae240655cf0314c19381593..b8fc6a96f7834e787e800061829d7a6140ad765f 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -613,6 +613,10 @@
"Permita que a app determine a posição relativa entre os dispositivos de banda ultralarga próximos"
"interagir com dispositivos Wi‑Fi próximos"
"Permite que a app anuncie, estabeleça ligação e determine a posição relativa de dispositivos Wi‑Fi próximos"
+
+
+
+
"Informações de serviços de pagamento com NFC preferenciais"
"Permite que a app obtenha informações de serviços de pagamento com NFC preferenciais, como apoios registados e destino da rota."
"controlo Near Field Communication"
@@ -2432,54 +2436,30 @@
"Ativar"
"Retroceder"
"Pendente…"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "O Satélite SOS já está disponível"
+ "Pode enviar mensagens aos serviços de emergência se não tiver uma rede móvel nem Wi-Fi. A app Mensagens Google tem de ser a sua app de mensagens predefinida."
+ "O Satélite SOS não é compatível"
+ "O Satélite SOS não é compatível com este dispositivo"
+ "O Satélite SOS não está configurado"
+ "Certifique-se de que tem ligação à Internet e tente configurar novamente"
+ "O Satélite SOS não está disponível"
+ "O Satélite SOS não está disponível neste país ou região"
+ "Satélite SOS não configurado"
+ "Para enviar mensagens por satélite, defina a app Mensagens Google como a sua app de mensagens predefinida"
+ "O Satélite SOS não está disponível"
+ "Para verificar se o Satélite SOS está disponível neste país ou região, ative as definições de localização"
+ "Mensagens por satélite disponíveis"
+ "Pode enviar mensagens por satélite se não tiver uma rede móvel nem Wi-Fi. A app Mensagens Google tem de ser a sua app de mensagens predefinida."
+ "As mensagens por satélite não são compatíveis"
+ "As mensagens por satélite não são compatíveis com este dispositivo"
+ "Mensagens por satélite não configuradas"
+ "Certifique-se de que tem ligação à Internet e tente configurar novamente"
+ "Mensagens por satélite não disponíveis"
+ "As mensagens por satélite não estão disponíveis neste país ou região"
+ "Mensagens por satélite não configuradas"
+ "Para enviar mensagens por satélite, defina a app Mensagens Google como a sua app de mensagens predefinida"
+ "Mensagens por satélite não disponíveis"
+ "Para verificar se as mensagens por satélite estão disponíveis neste país ou região, ative as definições de localização"
"Configure o Desbloqueio por impressão digital novamente"
"Já não é possível reconhecer %s."
"Já não é possível reconhecer %1$s e %2$s."
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 71b334e89eafc796d4b2aed3d69fd3221e5399e4..1719648d10f04e31ae41cae3387ffdbe7b3ffca3 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -613,6 +613,10 @@
"Permitir que o app determine o posicionamento relativo entre dispositivos de banda ultralarga por perto"
"interagir com dispositivos Wi-Fi por perto"
"Permite que o app divulgue, faça conexão e determine a posição relativa de dispositivos Wi-Fi por perto."
+
+
+
+
"Informações preferidas de serviço de pagamento por NFC"
"Permite que o app acesse as informações preferidas de serviço de pagamento por NFC, como auxílios registrados ou destinos de trajetos."
"controlar a comunicação a curta distância"
@@ -1755,7 +1759,7 @@
"Usar atalho"
"Inversão de cores"
"Correção de cor"
- "Modo uma mão"
+ "Modo para uma mão"
"Escurecer ainda mais a tela"
"Aparelhos auditivos"
"Teclas de volume pressionadas. Serviço %1$s ativado."
@@ -2432,54 +2436,30 @@
"Ativar"
"Voltar"
"Pendente…"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "O SOS via satélite já está disponível"
+ "Você poderá enviar uma mensagem para serviços de emergência se não houver uma rede móvel ou Wi-Fi. O Google Mensagens precisa ser seu app de mensagens padrão."
+ "Incompatível com o SOS via satélite"
+ "Este dispositivo não é compatível com o SOS via satélite"
+ "O SOS via satélite não foi configurado"
+ "Verifique sua conexão de Internet e tente configurar de novo"
+ "SOS via satélite indisponível"
+ "O SOS via satélite não está disponível neste país ou região"
+ "SOS via satélite não configurado"
+ "Para enviar mensagens via satélite, defina o Google Mensagens como seu app de mensagens padrão"
+ "SOS via satélite indisponível"
+ "Para verificar se o SOS via satélite está disponível neste país ou região, ative as configurações de localização"
+ "Mensagem via satélite disponível"
+ "É possível trocar mensagens por satélite caso não haja uma rede móvel ou Wi-Fi. O Google Mensagens precisa ser seu app de mensagens padrão."
+ "Incompatível com mensagem via satélite"
+ "Este dispositivo não é compatível com mensagem via satélite"
+ "Mensagem via satélite não configurada"
+ "Verifique sua conexão de Internet e tente configurar de novo"
+ "Mensagem via satélite indisponível"
+ "A mensagem via satélite não está disponível neste país ou região"
+ "Mensagem via satélite não configurada"
+ "Para enviar mensagens via satélite, defina o Google Mensagens como seu app de mensagens padrão"
+ "Mensagem via satélite indisponível"
+ "Para verificar se a mensagem via satélite está disponível neste país ou região, ative as configurações de localização"
"Configurar o Desbloqueio por impressão digital de novo"
"A impressão digital %s não é mais reconhecida."
"As impressões digitais %1$s e %2$s não são mais reconhecidas."
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 6e43d317e0f05f878be4a53379e637775153cfed..7843bbe1e9f1b945ef3cf2b8c4111cf2d0947227 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -613,6 +613,10 @@
"Permite-i aplicației să stabilească poziția relativă dintre dispozitivele Ultra-Wideband din apropiere"
"să interacționeze cu dispozitive Wi‑Fi din apropiere"
"Permite aplicației să se conecteze la dispozitive Wi-Fi din apropiere, să transmită anunțuri și să stabilească poziția relativă a acestora"
+
+
+
+
"Informații despre serviciul de plăți NFC preferat"
"Permite aplicației să obțină informații despre serviciul de plăți NFC preferat, de exemplu, identificatorii de aplicație înregistrați și destinația traseului."
"controlare schimb de date prin Near Field Communication"
@@ -2432,54 +2436,30 @@
"Activează"
"Înapoi"
"În așteptare..."
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "Funcția SOS prin satelit este acum disponibilă"
+ "Poți să trimiți mesaje serviciilor de urgență dacă nu este disponibilă o rețea mobilă sau Wi-Fi. Mesaje Google trebuie să fie aplicația ta pentru mesaje prestabilită."
+ "Funcția SOS prin satelit nu este acceptată"
+ "Funcția SOS prin satelit nu este acceptată pe acest dispozitiv"
+ "Funcția SOS prin satelit nu este configurată"
+ "Asigură-te că te-ai conectat la internet și încearcă din nou configurarea"
+ "Funcția SOS prin satelit nu este disponibilă"
+ "Funcția SOS prin satelit nu este disponibilă în această țară sau regiune"
+ "Funcția SOS prin satelit nu este configurată"
+ "Pentru a trimite mesaje prin satelit, setează Mesaje Google ca aplicație pentru mesaje prestabilită"
+ "Funcția SOS prin satelit nu este disponibilă"
+ "Pentru a verifica dacă funcția SOS prin satelit este disponibilă în această țară sau regiune, activează setările privind locația"
+ "Mesajele prin satelit sunt disponibile"
+ "Dacă nu este disponibilă o rețea mobilă sau Wi-Fi, poți să trimiți mesaje prin satelit. Mesaje Google trebuie să fie aplicația ta pentru mesaje prestabilită."
+ "Mesajele prin satelit nu sunt acceptate"
+ "Mesajele prin satelit nu sunt acceptate pe acest dispozitiv"
+ "Mesajele prin satelit nu sunt configurate"
+ "Asigură-te că te-ai conectat la internet și încearcă din nou configurarea"
+ "Mesajele prin satelit nu sunt disponibile"
+ "Mesajele prin satelit nu sunt disponibile în această țară sau regiune"
+ "Mesajele prin satelit nu sunt configurate"
+ "Pentru a trimite mesaje prin satelit, setează Mesaje Google ca aplicație pentru mesaje prestabilită"
+ "Mesajele prin satelit nu sunt disponibile"
+ "Pentru a verifica dacă mesajele prin satelit sunt disponibile în această țară sau regiune, activează setările privind locația"
"Configurează din nou Deblocarea cu amprenta"
"%s nu mai poate fi recunoscută."
"%1$s și %2$s nu mai pot fi recunoscute."
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index b23a44bcc9fc40d99be8afb8860f08cf65958eaa..8caa8b60c120ce021ec421f96d641d8777e81d71 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -614,6 +614,10 @@
"Приложение сможет определять относительное позиционирование устройств с технологией сверхширокополосной связи поблизости"
"Взаимодействие с устройствами Wi‑Fi поблизости"
"Приложение сможет передавать данные на устройства Wi‑Fi рядом, подключаться к ним и определять их примерное местоположение."
+
+
+
+
"Сведения о предпочтительном платежном сервисе NFC"
"Приложение сможет получать сведения о предпочтительном платежном сервисе NFC (например, зарегистрированные идентификаторы AID и конечный пункт маршрута)."
"Управление NFC-модулем"
@@ -2433,54 +2437,30 @@
"Включить"
"Назад"
"Обработка…"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "Доступен спутниковый SOS"
+ "Вы можете отправлять сообщения экстренным службам, даже когда подключение по мобильной сети или Wi-Fi недоступно. Google Сообщения должны быть выбраны в качестве мессенджера по умолчанию."
+ "Спутниковый SOS не поддерживается"
+ "Функция недоступна на этом устройстве."
+ "Спутниковый SOS не настроен"
+ "Проверьте подключение к интернету и повторите попытку."
+ "Спутниковый SOS недоступен"
+ "Функция недоступна в этой стране или регионе."
+ "Спутниковый SOS не настроен"
+ "Чтобы использовать эту функцию, необходимо выбрать Google Сообщения в качестве мессенджера по умолчанию."
+ "Спутниковый SOS недоступен"
+ "Чтобы узнать, можно ли использовать спутниковый SOS в этой стране или регионе, включите настройки геолокации."
+ "Доступен спутниковый обмен сообщениями"
+ "Вы можете обмениваться сообщениями по спутниковой связи, даже когда подключение к мобильной сети или Wi-Fi недоступно. Google Сообщения должны быть выбраны в качестве мессенджера по умолчанию."
+ "Спутниковый обмен сообщениями не поддерживается"
+ "Функция недоступна на этом устройстве."
+ "Спутниковый обмен сообщениями не настроен"
+ "Проверьте подключение к интернету и повторите попытку."
+ "Спутниковый обмен сообщениями недоступен"
+ "Функция недоступна в этой стране или регионе."
+ "Спутниковый обмен сообщениями не настроен"
+ "Чтобы использовать эту функцию, необходимо выбрать Google Сообщения в качестве мессенджера по умолчанию."
+ "Спутниковый обмен сообщениями недоступен"
+ "Чтобы узнать, можно ли обмениваться сообщениями по спутниковой связи в этой стране или регионе, включите настройки геолокации."
"Настройте разблокировку по отпечатку пальца заново"
"Отпечаток \"%s\" больше нельзя распознать."
"Отпечатки \"%1$s\" и \"%2$s\" больше нельзя распознать."
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index db82c6c98fa4f2a4db00c5a976bbe235169d562e..f150cd189f45e1849d68247b8edeac20d1b4fb09 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -612,6 +612,10 @@
"අවට ඇති අල්ට්රා-වයිඩ්බෑන්ඩ් උපාංග අතර සාපේක්ෂ පිහිටීම නිර්ණය කිරීමට යෙදුමට ඉඩ දීම"
"අවට Wi‑Fi උපාංග සමග අන්තර්ක්රියා කරන්න"
"වෙළඳ දැන්වීම් පළ කිරීමට, සම්බන්ධ වීමට සහ අවට ඇති Wi-Fi උපාංගවල සාපේක්ෂ පිහිටීම නිර්ණය කිරීමට යෙදුමට ඉඩ දෙයි"
+
+
+
+
"කැමති NFC ගෙවීම් සේවා තොරතුරු"
"ලියාපදිංචි කළ ආධාර සහ ගමන් මාර්ග ගමනාන්ත වැනි කැමති nfc ගෙවීම් සේවා තොරතුරු ලබා ගැනීමට යෙදුමට ඉඩ දෙයි."
"ආසන්න ක්ෂේත්ර සන්නිවේදනය පාලනය කරන්න"
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index cbabfb6e107634d3f19711f4194cd15d10cb5abe..e17e25f4734dff244ae80e9e4e059d6c3f9bce1d 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -614,6 +614,10 @@
"Povoľte aplikácii určovať relatívnu polohu medzi zariadeniami s ultraširokopásmovým pripojením v okolí"
"interakcia so zariadeniami Wi-Fi v okolí"
"Umožňuje aplikácii oznamovať a rozpoznávať relatívnu polohu zariadení Wi‑Fi v okolí a pripájať sa k nim"
+
+
+
+
"Preferované informácie platenej služby NFC"
"Umožňuje aplikácii získavať preferované informácie platenej služby NFC, napríklad o registrovanej pomoci a trasách k cieľu."
"ovládať technológiu NFC"
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index d7178c802ec6bb8577f6f90833b6863447a0ff73..da9f1c189610eb4318c60be52529a44f133a753a 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -614,6 +614,10 @@
"Aplikaciji dovoli, da določi relativno oddaljenost med napravami UWB v bližini."
"komunikacija z napravami Wi‑Fi v bližini"
"Aplikaciji dovoljuje objavljanje in določanje relativnega položaja naprav Wi‑Fi v bližini ter povezovanje z njimi."
+
+
+
+
"Podatki o prednostni storitvi za plačevanje prek povezave NFC"
"Aplikaciji omogoča pridobivanje podatkov o prednostni storitvi za plačevanje prek povezave NFC, kot so registrirani pripomočki in cilj preusmeritve."
"nadzor nad komunikacijo s tehnologijo bližnjega polja"
@@ -2433,54 +2437,30 @@
"Vklopi"
"Nazaj"
"V teku …"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "SOS prek satelita je zdaj na voljo"
+ "Reševalnim službam lahko pošljete sporočilo, če ni povezave z mobilnim omrežjem ali omrežjem Wi-Fi. Google Sporočila morajo biti privzeta aplikacija za sporočanje."
+ "SOS prek satelita ni podprt"
+ "SOS prek satelita ni podprt v tej napravi"
+ "SOS prek satelita ni nastavljen"
+ "Zagotovite, da imate vzpostavljeno internetno povezavo, in znova poskusite nastaviti"
+ "SOS prek satelita ni na voljo"
+ "SOS prek satelita ni na voljo v tej državi ali regiji"
+ "SOS prek satelita ni nastavljen"
+ "Če želite pošiljati satelitska sporočila, nastavite Google Sporočila kot privzeto aplikacijo za sporočanje"
+ "SOS prek satelita ni na voljo"
+ "Če želite preveriti, ali je SOS prek satelita na voljo v tej državi ali regiji, vklopite nastavitve lokacije"
+ "Satelitska sporočila so na voljo"
+ "Satelitska sporočila lahko pošljete, če ni povezave z mobilnim omrežjem ali omrežjem Wi-Fi. Google Sporočila morajo biti privzeta aplikacija za sporočanje."
+ "Satelitska sporočila niso podprta"
+ "Satelitska sporočila niso podprta v tej napravi"
+ "Satelitska sporočila niso nastavljena"
+ "Zagotovite, da imate vzpostavljeno internetno povezavo, in znova poskusite nastaviti"
+ "Satelitska sporočila niso na voljo"
+ "Satelitska sporočila niso na voljo v tej državi ali regiji"
+ "Satelitska sporočila niso nastavljena"
+ "Če želite pošiljati satelitska sporočila, nastavite Google Sporočila kot privzeto aplikacijo za sporočanje"
+ "Satelitska sporočila niso na voljo"
+ "Če želite preveriti, ali so satelitska sporočila na voljo v tej državi ali regiji, vklopite nastavitve lokacije"
"Vnovična nastavitev odklepanja s prstnim odtisom"
"Odtisa »%s« ni več mogoče prepoznati."
"Odtisov »%1$s« in »%2$s« ni več mogoče prepoznati."
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index 42356bf8cc076661fc6bd004a892a7cd4f71ce13..1b8d0a0095f3c5d8cf8a4a9b737c12878493baaa 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -612,6 +612,10 @@
"Lejo që aplikacioni të përcaktojë pozicionin e përafërt mes pajisjeve në afërsi me brezin ultra të gjerë"
"të ndërveprojë me pajisjet Wi-Fi në afërsi"
"Lejon që aplikacioni të reklamojë, të lidhet dhe të përcaktojë pozicionin përkatës të pajisjeve Wi-Fi në afërsi"
+
+
+
+
"Informacionet për shërbimin e preferuar të pagesës me NFC"
"Lejon aplikacionin të marrë informacione për shërbimin e preferuar të pagesës me NFC si p.sh. ndihmat e regjistruara dhe destinacionin e itinerarit."
"kontrollo \"Komunikimin e fushës në afërsi\" NFC"
@@ -1663,7 +1667,7 @@
"Kufjet"
"USB"
"Sistemi"
- "Audioja e \"bluetooth-it\""
+ "Audioja e Bluetooth-it"
"Ekran wireless"
"Transmeto"
"Lidhu me pajisjen"
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 10fa5f831fb4932584a90d906a2cd11adbf5357b..bdf557173391661ca1bfc3cc57e0eb24d0494489 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -613,6 +613,10 @@
"Дозвољава апликацији да одређује релативну раздаљину између уређаја ултра-широког појаса у близини"
"интеракција са WiFi уређајима у близини"
"Дозвољава апликацији да се оглашава, повезује и утврђује релативну позицију WiFi уређаја у близини"
+
+
+
+
"Информације о жељеној NFC услузи за плаћање"
"Дозвољава апликацији да преузима информације о жељеној NFC услузи за плаћање, попут регистрованих идентификатора апликација и одредишта преусмеравања."
"контрола комуникације у ужем пољу (Near Field Communication)"
@@ -2432,54 +2436,30 @@
"Укључи"
"Назад"
"На чекању..."
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "Хитна помоћ преко сателита је сада доступна"
+ "Можете да шаљете поруке хитним службама ако немате приступ мобилној ни WiFi мрежи. Google Messages мора да буде подразумевана апликација за размену порука."
+ "Хитна помоћ преко сателита није подржана"
+ "Хитна помоћ преко сателита није подржанa на овом уређају"
+ "Хитна помоћ преко сателита није подешена"
+ "Проверите да ли сте повезани на интернет и пробајте поново да подесите"
+ "Хитна помоћ преко сателита није доступна"
+ "Хитна помоћ преко сателита није доступна у овој земљи или региону"
+ "Хитна помоћ преко сателита није подешена"
+ "Да бисте слали поруке преко сателита, подесите Google Messages као подразумевану апликацију за размену порука"
+ "Хитна помоћ преко сателита није доступна"
+ "Да бисте проверили да ли је хитна помоћ преко сателита доступна у овој земљи или региону, укључите подешавања локације"
+ "Размена порука преко сателита је доступна"
+ "Можете да шаљете поруке преко сателита ако немате приступ мобилној ни WiFi мрежи. Google Messages мора да буде подразумевана апликација за размену порука."
+ "Размена порука преко сателита није подржана"
+ "Размена порука преко сателита није подржана на овом уређају"
+ "Размена порука преко сателита није подешена"
+ "Проверите да ли сте повезани на интернет и пробајте поново да подесите"
+ "Размена порука преко сателита није доступна"
+ "Размена порука преко сателита није доступна у овој земљи или региону"
+ "Размена порука преко сателита није подешена"
+ "Да бисте слали поруке преко сателита, подесите Google Messages као подразумевану апликацију за размену порука"
+ "Размена порука преко сателита није доступна"
+ "Да бисте проверили да ли је размена порука преко сателита доступна у овој земљи или региону, укључите подешавања локације"
"Поново подесите откључавање отиском прста"
"%s више не може да се препозна."
"%1$s и %2$s више не могу да се препознају."
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 857b060452ec56bc2bbcc82e6a37f290fce69ec2..8bef5ca8a8429ecd7392d61195a76525ad22d135 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -612,6 +612,10 @@
"Tillåt att appen fastställer den relativa positionen mellan Ultra Wideband-enheter i närheten"
"interagera med wifi-enheter i närheten"
"Tillåter appen att sända ut till, ansluta till och fastställa relativ position för wifi-enheter i närheten"
+
+
+
+
"Information kopplad till standardtjänsten för NFC-betalning"
"Tillåter att appen hämtar information kopplad till standardtjänsten för NFC-betalning, till exempel registrerade hjälpmedel och ruttdestinationer."
"kontrollera närfältskommunikationen"
@@ -2431,54 +2435,30 @@
"Aktivera"
"Tillbaka"
"Väntar …"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "SOS-larm via satellit är nu tillgängligt"
+ "Du kan skicka meddelanden till räddningstjänsten om det inte finns någon mobil- eller wifi-anslutning. Google Messages måste vara din standardapp för meddelanden."
+ "SOS-larm via satellit stöds inte"
+ "SOS-larm via satellit stöds inte på den här enheten"
+ "SOS-larm via satellit har inte konfigurerats"
+ "Kontrollera att enheten är ansluten till internet och försök igen"
+ "SOS-larm via satellit är inte tillgängligt"
+ "SOS-larm via satellit är inte tillgängligt i det här landet eller den här regionen"
+ "SOS-larm via satellit har inte konfigurerats"
+ "Ställ in Google Messages som standardapp för meddelanden om du vill skicka meddelanden via satellit"
+ "SOS-larm via satellit är inte tillgängligt"
+ "Aktivera platsinställningar för att kontrollera om SOS-larm via satellit är tillgängligt i det här landet eller den här regionen"
+ "Satellitmeddelanden är tillgängliga"
+ "Du kan skicka meddelanden via satellit om det inte finns någon mobil- eller wifi-anslutning. Google Messages måste vara din standardapp för meddelanden."
+ "Satellitmeddelanden stöds inte"
+ "Satellitmeddelanden stöds inte på den här enheten"
+ "Satellitmeddelanden har inte ställts in"
+ "Kontrollera att enheten är ansluten till internet och försök igen"
+ "Satellitmeddelanden är inte tillgängliga"
+ "Satellitmeddelanden är inte tillgängliga i det här landet eller den här regionen"
+ "Satellitmeddelanden har inte ställts in"
+ "Ställ in Google Messages som standardapp för meddelanden om du vill skicka meddelanden via satellit"
+ "Satellitmeddelanden är inte tillgängliga"
+ "Aktivera platsinställningar för att kontrollera om satellitmeddelanden är tillgängliga i det här landet eller den här regionen"
"Konfigurera fingeravtryckslås igen"
"Det går inte längre att känna igen %s."
"Det går inte längre att känna igen %1$s och %2$s."
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index d46fa084258bb9cab70854d8c0833f1e74da158a..010415eaf313168891313ed7d27f0edfaf59cba9 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -612,6 +612,10 @@
"Ruhusu programu ibainishe nafasi kati ya vifaa vyenye Bendi Pana Zaidi vilivyo karibu"
"tumia vifaa vya Wi‑Fi vilivyo karibu"
"Huruhusu programu kutangaza, kuunganisha na kubaini mahali palipokadiriwa vilipo vifaa vya Wi-Fi vilivyo karibu"
+
+
+
+
"Maelezo ya Huduma Inayopendelewa ya Malipo ya NFC"
"Huruhusu programu kupata maelezo ya huduma inayopendelewa ya malipo ya nfc kama vile huduma zilizosajiliwa na njia."
"kudhibiti Mawasiliano ya Vifaa Vilivyokaribu (NFC)"
@@ -2405,7 +2409,7 @@
"Muundo wa kibodi umewekwa kuwa %1$s, %2$s, %3$s… Gusa ili ubadilishe."
"Mipangilio ya kibodi halisi imewekwa"
"Gusa ili uangalie kibodi"
- "Faragha"
+ "Sehemu ya Faragha"
"Nakala"
"Kazini"
"Wa 2 wa Kazini"
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index 32fefacb111596ef88340950dfd2eba733a40dca..1915f298261193836a084e0d31780139d3c27dab 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -612,6 +612,10 @@
"அருகிலுள்ள அல்ட்ரா-வைடுபேண்ட் சாதனங்களுக்கிடையிலான தூரத்தைத் தீர்மானிக்க ஆப்ஸை அனுமதிக்கும்"
"அருகிலுள்ள வைஃபை சாதனங்களுடன் தொடர்பு கொள்ளுதல்"
"அருகிலுள்ள வைஃபை சாதனங்களைத் தெரியப்படுத்தவும் இணைக்கவும் இருப்பிடத்தைத் தீர்மானிக்கவும் இது ஆப்ஸை அனுமதிக்கும்"
+
+
+
+
"விருப்பமான NFC பேமெண்ட் சேவை தொடர்பான தகவல்கள்"
"பதிவுசெய்யப்பட்ட கருவிகள், சேருமிடத்திற்கான வழி போன்ற விருப்பமான NFC பேமெண்ட் சேவை தொடர்பான தகவல்களைப் பெற ஆப்ஸை அனுமதிக்கிறது."
"குறுகிய இடைவெளி தகவல்பரிமாற்றத்தைக் கட்டுப்படுத்துதல்"
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index 8500e9dcd0d78fc40eb98cb61922bb0fd139c1e0..6ac81642d41f9916c718605fd968339671f7d927 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -612,6 +612,10 @@
"సమీపంలోని అల్ట్రా-వైడ్బ్యాండ్ పరికరాల మధ్య సాపేక్ష స్థానాన్ని నిర్ణయించడానికి యాప్ను అనుమతించండి"
"సమీపంలోని Wi-Fi పరికరాలతో ఇంటరాక్ట్ చేస్తుంది"
"అడ్వర్టయిజ్, కనెక్ట్ చేయడానికి, సమీపంలోని Wi-Fi పరికరాల సంబంధిత పొజిషన్ను నిర్ణయించడానికి యాప్ను అనుమతిస్తుంది"
+
+
+
+
"ప్రాధాన్యత ఇవ్వబడిన NFC చెల్లింపు సేవల సమాచారం"
"ప్రాధాన్యత ఇవ్వబడిన NFC చెల్లింపు సేవల సమాచారాన్ని, అంటే రిజిస్టర్ చేయబడిన సహాయక సాధనాలు, మార్గం, గమ్యస్థానం వంటి వాటిని పొందేందుకు యాప్ను అనుమతిస్తుంది."
"సమీప క్షేత్ర కమ్యూనికేషన్ను నియంత్రించడం"
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index a1c7b4f59608af04b4698700560474912ab3795c..763eb626619891656720d2c9894062dae60b837f 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -612,6 +612,10 @@
"อนุญาตให้แอประบุตำแหน่งสัมพันธ์ระหว่างอุปกรณ์ที่ใช้แถบความถี่กว้างยิ่งยวดซึ่งอยู่ใกล้เคียง"
"โต้ตอบกับอุปกรณ์ Wi-Fi ที่อยู่ใกล้เคียง"
"อนุญาตให้แอปแสดงข้อมูล เชื่อมต่อ และระบุตำแหน่งซึ่งสัมพันธ์กับอุปกรณ์ Wi-Fi ที่อยู่ใกล้เคียง"
+
+
+
+
"ข้อมูลบริการชำระเงิน NFC ที่ต้องการ"
"อนุญาตให้แอปรับข้อมูลบริการชำระเงิน NFC ที่ต้องการ เช่น รหัสแอป (AID) ที่ลงทะเบียนและปลายทางของเส้นทาง"
"ควบคุม Near Field Communication"
@@ -2431,54 +2435,30 @@
"เปิด"
"ย้อนกลับ"
"รอดำเนินการ..."
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "SOS ดาวเทียมพร้อมใช้งานแล้ว"
+ "คุณส่งข้อความหาบริการช่วยเหลือฉุกเฉินได้ในกรณีที่ไม่มีเครือข่ายมือถือหรือ Wi-Fi โดยที่แอปรับส่งข้อความเริ่มต้นของคุณจะต้องเป็น Google Messages"
+ "ไม่รองรับ SOS ดาวเทียม"
+ "อุปกรณ์นี้ไม่รองรับ SOS ดาวเทียม"
+ "ไม่ได้ตั้งค่า SOS ดาวเทียม"
+ "ตรวจสอบว่าคุณได้เชื่อมต่ออินเทอร์เน็ตแล้ว และลองตั้งค่าอีกครั้ง"
+ "SOS ดาวเทียมไม่พร้อมใช้งาน"
+ "SOS ดาวเทียมไม่พร้อมใช้งานในประเทศหรือภูมิภาคนี้"
+ "ไม่ได้ตั้งค่า SOS ดาวเทียม"
+ "หากต้องการรับส่งข้อความผ่านดาวเทียม ให้ตั้ง Google Messages เป็นแอปรับส่งข้อความเริ่มต้น"
+ "SOS ดาวเทียมไม่พร้อมใช้งาน"
+ "หากต้องการตรวจสอบว่า SOS ดาวเทียมพร้อมให้บริการในประเทศหรือภูมิภาคนี้หรือไม่ ให้เปิดการตั้งค่าตำแหน่ง"
+ "การรับส่งข้อความผ่านดาวเทียมพร้อมใช้งาน"
+ "คุณรับส่งข้อความผ่านดาวเทียมได้ในกรณีที่ไม่มีเครือข่ายมือถือหรือ Wi-Fi โดยที่แอปรับส่งข้อความเริ่มต้นของคุณจะต้องเป็น Google Messages"
+ "ไม่รองรับการรับส่งข้อความผ่านดาวเทียม"
+ "อุปกรณ์นี้ไม่รองรับการรับส่งข้อความผ่านดาวเทียม"
+ "ไม่ได้ตั้งค่าการรับส่งข้อความผ่านดาวเทียม"
+ "ตรวจสอบว่าคุณได้เชื่อมต่ออินเทอร์เน็ตแล้ว และลองตั้งค่าอีกครั้ง"
+ "การรับส่งข้อความผ่านดาวเทียมไม่พร้อมใช้งาน"
+ "การรับส่งข้อความผ่านดาวเทียมไม่พร้อมใช้งานในประเทศหรือภูมิภาคนี้"
+ "ไม่ได้ตั้งค่าการรับส่งข้อความผ่านดาวเทียม"
+ "หากต้องการรับส่งข้อความผ่านดาวเทียม ให้ตั้ง Google Messages เป็นแอปรับส่งข้อความเริ่มต้น"
+ "การรับส่งข้อความผ่านดาวเทียมไม่พร้อมใช้งาน"
+ "หากต้องการตรวจสอบว่าการรับส่งข้อความผ่านดาวเทียมพร้อมให้บริการในประเทศหรือภูมิภาคนี้หรือไม่ ให้เปิดการตั้งค่าตำแหน่ง"
"ตั้งค่าการปลดล็อกด้วยลายนิ้วมืออีกครั้ง"
"ระบบไม่จดจำ %s อีกต่อไป"
"ระบบไม่จดจำ %1$s และ %2$s อีกต่อไป"
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index f15d952db15ae7cbc01d8af97a970adc70401355..b44faae4e84ffac0f964aca6a7cbe5ba76c45ca4 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -612,6 +612,10 @@
"Payagan ang app na tukuyin ang relatibong posisyon sa pagitan ng mga kalapit na Ultra-Wideband device"
"makipag-ugnayan sa mga kalapit na Wi‑Fi device"
"Nagbibigay-daan sa app na i-advertise ang, kumonekta sa, at tukuyin ang nauugnay na posisyon ng mga kalapit na Wi‑Fi device"
+
+
+
+
"Impormasyon sa Gustong NFC na Serbisyo sa Pagbabayad"
"Pinapayagan ang app na makakuha ng impormasyon sa gustong nfc na serbisyo sa pagbabayad tulad ng mga nakarehistrong application ID at destinasyon ng ruta."
"kontrolin ang Near Field Communication"
@@ -2431,54 +2435,30 @@
"I-on"
"Bumalik"
"Nakabinbin..."
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "Available na ang SOS gamit ang Satellite"
+ "Puwede kang magpadala ng mensahe sa mga serbisyong pang-emergency kung walang mobile o Wi-Fi network. Dapat Google Messages ang default mong app sa pagmemensahe."
+ "Hindi sinusuportahan ang SOS gamit ang satellite"
+ "Hindi sinusuportahan ang SOS gamit ang satellite sa device na ito"
+ "Hindi naka-set up ang SOS gamit ang satellite"
+ "Tiyaking nakakonekta ka sa internet at subukang mag-set up ulit"
+ "Hindi available ang SOS gamit ang satellite"
+ "Hindi available ang SOS gamit ang satellite sa bansa o rehiyong ito"
+ "Hindi naka-set up ang SOS gamit ang satellite"
+ "Para magpadala ng mensahe sa pamamagitan ng satellite, itakda ang Google Messages bilang iyong default na app sa pagmemensahe"
+ "Hindi available ang SOS gamit ang satellite"
+ "Para tingnan kung available ang SOS gamit ang satellite sa bansa o rehiyong ito, i-on ang mga setting ng lokasyon"
+ "Available ang satellite messaging"
+ "Puwede kang magpadala ng mensahe sa pamamagitan ng satellite kung walang mobile o Wi-Fi network. Dapat Google Messages ang default mong app sa pagmemensahe."
+ "Hindi sinusuportahan ang satellite messaging"
+ "Hindi sinusuportahan ang satellite messaging sa device na ito"
+ "Hindi naka-set up ang satellite messaging"
+ "Tiyaking nakakonekta ka sa internet at subukang mag-set up ulit"
+ "Hindi available ang satellite messaging"
+ "Hindi available ang satellite messaging sa bansa o rehiyong ito"
+ "Hindi naka-set up ang satellite messaging"
+ "Para magpadala ng mensahe sa pamamagitan ng satellite, itakda ang Google Messages bilang iyong default na app sa pagmemensahe"
+ "Hindi available ang satellite messaging"
+ "Para tingnan kung available ang satellite messaging sa bansa o rehiyong ito, i-on ang mga setting ng lokasyon"
"I-set up ulit ang Pag-unlock Gamit ang Fingerprint"
"Hindi na makilala ang %s."
"Hindi na makilala ang %1$s at %2$s."
@@ -2497,7 +2477,7 @@
"Email"
"SMS"
"Musika"
- "Kalendaryo"
+ "Calendar"
"Calculator"
"Mga Mapa"
"Mga Application"
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 39a005f628f568a6c88b86c6e3f4d62247a46868..e54b8999a1dce06fc1432022d15098c23f4f4955 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -612,6 +612,10 @@
"Uygulamanın, yakındaki Ultra Geniş Bant cihazların birbirine göre konumunu belirlemesine izin verin"
"yakındaki kablosuz cihazlarla etkileşim kur"
"Uygulamanın reklam sunmasına, bağlanmasına ve yakındaki kablosuz cihazların göreli konumunu belirlemesine izin verir"
+
+
+
+
"Tercih Edilen NFC Ödeme Hizmeti Bilgileri"
"Uygulamaya, kayıtlı yardımlar ve rota hedefi gibi tercih edilen NFC ödeme hizmeti bilgilerini alma izni verir."
"Yakın Alan İletişimini denetle"
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 3b9cd192f7a4c16c39a896524fa07ba8b1f97804..344cb28afcb28071cbe13aa80c9bc60418c754af 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -614,6 +614,10 @@
"З цим дозволом додаток може визначати відстань між розташованими поблизу пристроями з надширокосмуговим зв’язком"
"взаємодіяти з пристроями Wi‑Fi поблизу"
"Додаток може виявляти пристрої Wi‑Fi поблизу, підключатися до них і визначати їх відносне розташування"
+
+
+
+
"Використання інформації з платіжного NFC-сервісу"
"Дозволяє додатку отримувати доступ до інформації потрібного платіжного NFC-сервісу (наприклад, пов\'язаних ідентифікаторів чи даних про маршрутизацію трансакцій)."
"контрол. Near Field Communication"
@@ -1575,7 +1579,7 @@
"Видалити елементи"
"Відмінити видалення"
"Наразі нічого не робити"
- "Вибрати обліковий запис"
+ "Вибрати облік. запис"
"Додати обліковий запис"
"Додати облік. запис"
"Збільшити"
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index 679f1026197a94582027f26351fdce7816d5ca72..45e1a2347dbbbefa0afef413dc733f05ab8a9ff0 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -612,6 +612,10 @@
"ایپ کو قریبی الٹرا وائڈ بینڈ آلات کے مابین متعلقہ پوزیشن کا تعین کرنے کی اجازت دیں"
"قریبی Wi-Fi آلات کے ساتھ تعامل کریں"
"ایپ کو اشتہار دینے، منسلک کرنے اور قریبی Wi-Fi آلات کی متعلقہ پوزیشن کا تعین کرنے کی اجازت دیتا ہے"
+
+
+
+
"ترجیح شدہ NFC ادائیگی کی سروس کی معلومات"
"ایپ کو رجسٹرشدہ ایڈز اور روٹ ڈسٹنیشن جیسی ترجیح شدہ nfc ادائیگی سروس کی معلومات حاصل کرنے کی اجازت دیتا ہے۔"
"Near Field کمیونیکیشن کنٹرول کریں"
@@ -2431,54 +2435,30 @@
"آن کریں"
"واپس جائیں"
"زیر التواء..."
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "سیٹلائٹ SOS اب دستیاب ہے"
+ "موبائل یا Wi-Fi نیٹ ورک نہ ہونے پر آپ ایمرجنسی سروسز کو پیغام بھیج سکتے ہیں۔ Google پیغامات آپ کی ڈیفالٹ پیغام رسانی ایپ ہونی چاہیے۔"
+ "سیٹلائٹ SOS تعاون یافتہ نہیں ہے"
+ "سیٹلائٹ SOS اس آلے پر تعاون یافتہ نہیں ہے"
+ "سیٹلائٹ SOS سیٹ اپ نہیں ہے"
+ "یقینی بنائیں کہ آپ انٹرنیٹ سے منسلک ہیں اور دوبارہ سیٹ اپ کرنے کی کوشش کریں"
+ "سیٹلائٹ SOS دستیاب نہیں ہے"
+ "سیٹلائٹ SOS اس ملک یا علاقے میں دستیاب نہیں ہے"
+ "سیٹلائٹ SOS سیٹ اپ نہیں ہے"
+ "سیٹلائٹ کے ذریعے پیغام بھیجنے کے لیے، Google پیغامات کو اپنی ڈیفالٹ پیغام رسانی ایپ کے طور پر سیٹ کریں"
+ "سیٹلائٹ SOS دستیاب نہیں ہے"
+ "یہ چیک کرنے کے لیے کہ آیا اس ملک یا علاقے میں سیٹلائٹ SOS دستیاب ہے، مقام کی ترتیبات کو آن کریں"
+ "سیٹلائٹ پیغام رسانی دستیاب ہے"
+ "موبائل یا Wi-Fi نیٹ ورک نہ ہونے پر آپ سیٹلائٹ کے ذریعے پیغام بھیج سکتے ہیں۔ Google پیغامات آپ کی ڈیفالٹ پیغام رسانی ایپ ہونی چاہیے۔"
+ "سیٹلائٹ پیغام رسانی تعاون یافتہ نہیں ہے"
+ "سیٹلائٹ پیغام رسانی اس آلے پر تعاون یافتہ نہیں ہے"
+ "سیٹلائٹ پیغام رسانی سیٹ اپ نہیں ہے"
+ "یقینی بنائیں کہ آپ انٹرنیٹ سے منسلک ہیں اور دوبارہ سیٹ اپ کرنے کی کوشش کریں"
+ "سیٹلائٹ پیغام رسانی دستیاب نہیں ہے"
+ "سیٹلائٹ پیغام رسانی اس ملک یا علاقے میں دستیاب نہیں ہے"
+ "سیٹلائٹ پیغام رسانی سیٹ اپ نہیں ہے"
+ "سیٹلائٹ کے ذریعے پیغام بھیجنے کے لیے، Google پیغامات کو اپنی ڈیفالٹ پیغام رسانی ایپ کے طور پر سیٹ کریں"
+ "سیٹلائٹ پیغام رسانی دستیاب نہیں ہے"
+ "یہ چیک کرنے کے لیے کہ آیا اس ملک یا علاقے میں سیٹلائٹ پیغام رسانی دستیاب ہے، مقام کی ترتیبات کو آن کریں"
"فنگر پرنٹ اَن لاک کو دوبارہ سیٹ اپ کریں"
"%s مزید پہچانا نہیں جا سکتا۔"
"%1$s اور %2$s کو مزید پہچانا نہیں جا سکتا۔"
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index d7620e1f3afbab05b11f7cda12587e9681a71495..f123bea572b15fa04d08cd0c0e54dba6fb7d3f60 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -612,6 +612,10 @@
"Ilovaga yaqin atrofdagi ultra keng polosali qurilmalarining nisbiy joylashishini aniqlashga ruxsat beradi"
"Yaqin-atrofdagi Wi-Fi qurilmalar bilan ishlash"
"Ilovaga yaqin-atrofdagi Wi-Fi qurilmalarga reklama yuborish, ulanish va ularning taxminiy joylashuvini aniqlash imkonini beradi."
+
+
+
+
"Asosiy NFC toʻlov xizmati haqidagi axborot"
"Bu ilovaga asosiy NFC toʻlov xizmati haqidagi axborotni olish imkonini beradi (masalan, qayd qilingan AID identifikatorlari va marshrutning yakuniy manzili)."
"NFC modulini boshqarish"
@@ -2431,54 +2435,30 @@
"Yoqish"
"Orqaga"
"Kutilmoqda..."
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "Sputnik SOS xizmati mavjud"
+ "Agar mobil yoki Wi-Fi tarmoq boʻlmasa, favqulodda xizmatlarga xabar yuborishingiz mumkin. Google Xabarlar asosiy xabar almashinuv ilovasi boʻlishi zarur."
+ "Sputnik SOS ishlamaydi"
+ "Bu qurilmada sputnik SOS ishlamaydi"
+ "Sputnik SOS sozlanmagan"
+ "Internetga ulanganingizni tekshiring va qayta sozlang"
+ "Sputnik SOS mavjud emas"
+ "Sputnik SOS bu mamlakat yoki hududda mavjud emas"
+ "Sputnik SOS sozlanmagan"
+ "Sunʼiy yoʻldosh orqali xabarlashish uchun Google Xabarlar ilovasini asosiy xabar almashinuv ilovasi sifatida sozlang"
+ "Sputnik SOS mavjud emas"
+ "Bu mamlakat yoki hududda sputnik SOS mavjudligini tekshirish uchun joylashuv sozlamalarini yoqing"
+ "Sunʼiy yoʻldosh orqali xabarlashuv mavjud"
+ "Agar mobil yoki Wi-Fi tarmoq boʻlmasa, sunʼiy yoʻldosh orqali xabar yuborishingiz mumkin. Google Xabarlar asosiy xabar almashinuv ilovasi boʻlishi zarur."
+ "Sunʼiy yoʻldosh orqali xabarlashuv ishlamaydi"
+ "Bu qurilmada sunʼiy yoʻldosh orqali xabarlashuv ishlamaydi"
+ "Sunʼiy yoʻldosh orqali xabarlashuv sozlanmagan"
+ "Internetga ulanganingizni tekshiring va qayta sozlang"
+ "Sunʼiy yoʻldosh orqali xabarlashuv mavjud emas"
+ "Sunʼiy yoʻldosh orqali xabarlashuv ushbu mamlakat yoki hududda ishlamaydi"
+ "Sunʼiy yoʻldosh orqali xabarlashuv sozlanmagan"
+ "Sunʼiy yoʻldosh orqali xabarlashish uchun Google Xabarlar ilovasini asosiy xabar almashinuv ilovasi sifatida sozlang"
+ "Sunʼiy yoʻldosh orqali xabarlashuv mavjud emas"
+ "Bu mamlakat yoki hududda sunʼiy yoʻldosh orqali xabarlashuv mavjudligini tekshirish uchun joylashuv sozlamalarini yoqing"
"Barmoq izi bilan ochish funksiyasini qayta sozlang"
"%s endi tanilmaydi."
"%1$s va %2$s endi tanilmaydi."
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 663078b5caf4bff6bd9678289b6d4834549c7a4a..ef50a9badc4c18db9c56bfda8ef766edb4de0270 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -612,6 +612,10 @@
"Cho phép ứng dụng xác định khoảng cách tương đối giữa các thiết bị ở gần dùng Băng tần siêu rộng"
"tương tác với các thiết bị Wi‑Fi lân cận"
"Cho phép ứng dụng này thông báo, kết nối và xác định vị trí tương đối của các thiết bị Wi‑Fi lân cận"
+
+
+
+
"Thông tin về dịch vụ thanh toán qua công nghệ giao tiếp tầm gần (NFC) được ưu tiên"
"Cho phép ứng dụng nhận thông tin về dịch vụ thanh toán qua công nghệ giao tiếp tầm gần mà bạn ưu tiên, chẳng hạn như các hình thức hỗ trợ đã đăng ký và điểm đến trong hành trình."
"kiểm soát Liên lạc trường gần"
diff --git a/core/res/res/values-watch/themes_device_defaults.xml b/core/res/res/values-watch/themes_device_defaults.xml
index 4d2085bbe0c78ff295e72c5c24bb86c63c1effac..7ac17595a27886a6ef80a846daf87217f8836adc 100644
--- a/core/res/res/values-watch/themes_device_defaults.xml
+++ b/core/res/res/values-watch/themes_device_defaults.xml
@@ -238,16 +238,16 @@ a similar way.
- @color/system_secondary_fixed_dim
- @color/system_on_error_container_dark
- @color/system_on_secondary_fixed
- - @color/system_on_surface_light
+ - @color/system_on_surface_light
- @color/system_tertiary_fixed_dim
- @color/system_on_tertiary_fixed
- @color/system_primary_fixed_dim
- @color/system_secondary_container_dark
- @color/system_error_container_dark
- @color/system_on_primary_fixed
- - @color/system_primary_light
+ - @color/system_primary_light
- @color/system_secondary_fixed
- - @color/system_surface_light
+ - @color/system_surface_light
- @color/system_surface_variant_dark
- @color/system_tertiary_container_dark
- @color/system_tertiary_fixed
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 6007d1e5f9c5e86280824e58a1669ba8268b9169..e2f66fc93c0846aa41118de822b9df6bb4329d10 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -612,6 +612,10 @@
"允许应用确定附近超宽带设备之间的相对位置"
"与附近的 WLAN 设备互动"
"允许该应用向附近的 WLAN 设备进行广播、连接到这些设备以及确定这些设备的相对位置"
+
+
+
+
"首选 NFC 付款服务信息"
"允许应用获取首选 NFC 付款服务信息,例如注册的应用标识符和路线目的地。"
"控制近距离通信"
@@ -2431,54 +2435,30 @@
"开启"
"返回"
"待归档…"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ "现在支持卫星紧急呼救功能"
+ "即使没有移动网络或 WLAN 网络,您仍可以向应急服务发送消息。您必须将 Google 信息设为默认的即时通讯应用。"
+ "不支持卫星紧急呼救功能"
+ "此设备不支持卫星紧急呼救功能"
+ "未设置卫星紧急呼救功能"
+ "请确保您已联网,然后尝试重新设置"
+ "不支持卫星紧急呼救功能"
+ "此国家/地区不支持卫星紧急呼救功能"
+ "未设置卫星紧急呼救功能"
+ "如需通过卫星发送消息,请将 Google 信息设为默认即时通讯应用"
+ "不支持卫星紧急呼救功能"
+ "若要查看此国家/地区是否支持卫星紧急呼救功能,请开启位置信息设置"
+ "支持卫星消息功能"
+ "即使没有移动网络或 WLAN 网络,您仍可以通过卫星发送消息。您必须将 Google 信息设为默认的即时通讯应用。"
+ "不支持卫星消息功能"
+ "此设备不支持卫星消息功能"
+ "未设置卫星消息功能"
+ "请确保您已联网,然后尝试重新设置"
+ "不支持卫星消息功能"
+ "此国家/地区不支持卫星消息功能"
+ "未设置卫星消息功能"
+ "如需通过卫星发送消息,请将 Google 信息设为默认即时通讯应用"
+ "不支持卫星消息功能"
+ "若要查看此国家/地区是否支持卫星消息功能,请开启位置信息设置"
"重新设置指纹解锁功能"
"系统无法再识别%s。"
"系统无法再识别%1$s和%2$s。"
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index fcf50e4beec406b0acf6678b93fd73c96d0f2461..a2d32805df76bbc27bc47d267bcef9268d7f9cbf 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -612,6 +612,10 @@
"允許應用程式判斷附近超寬頻裝置之間的相對位置"
"與附近的 Wi‑Fi 裝置互動"
"允許應用程式向附近的 Wi-Fi 裝置顯示此裝置、連接這些裝置並判斷其相對位置"
+
+
+
+
"由用戶允許授權的 NFC 付款服務資訊"
"允許應用程式取得由用戶允許授權的 NFC 付款服務資訊 (如已註冊的付款輔助功能和最終付款對象)。"
"控制近距離無線通訊"
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index e186e7c908b2036ae381026d2160a726faa80971..d1f8b5a289ed67cce927d3c49747d327cfe92275 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -612,6 +612,10 @@
"允許應用程式判斷附近超寬頻裝置間的相對位置"
"與鄰近的 Wi-Fi 裝置互動"
"允許應用程式顯示鄰近的 Wi-Fi 裝置的資料、與其連線並判斷相對位置"
+
+
+
+
"首選 NFC 付費服務資訊"
"允許應用程式取得首選 NFC 付費服務資訊,例如已註冊的輔助工具和路線目的地。"
"控制近距離無線通訊"
@@ -640,12 +644,12 @@
"允許應用程式修改你的相片收藏。"
"讀取你的媒體收藏的位置資訊"
"允許應用程式讀取你的媒體收藏的位置資訊。"
- "使用生物特徵辨識功能"
- "使用生物特徵辨識或螢幕鎖定功能"
+ "使用生物辨識功能"
+ "使用生物辨識或螢幕鎖定功能"
"驗證你的身分"
- "如要繼續操作,請使用生物特徵辨識功能驗證身分"
- "請使用生物特徵辨識或螢幕鎖定功能驗證身分,才能繼續操作"
- "無法使用生物特徵辨識硬體"
+ "如要繼續操作,請使用生物辨識功能驗證身分"
+ "請使用生物辨識或螢幕鎖定功能驗證身分,才能繼續操作"
+ "無法使用生物辨識硬體"
"已取消驗證"
"無法辨識"
"無法辨識臉孔"
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 69ec5edc9004224019bc2b7d894a7046f838157d..d1b7e510168e3cb57ef7d1960c9984fd1b6736b8 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -612,6 +612,10 @@
"Vumela i-app inqume indawo ehambelanayo phakathi kwamadivayisi e-Ultra-Wideband aseduze"
"xhumana namadivayisi we-Wi‑Fi aseduze"
"Ivumela i-app ikhangise, ixhume, futhi inqume isimo esihambisanayo samadivayisi we-Wi-Fi aseduze"
+
+
+
+
"Ulwazi Lwesevisi Yenkokhelo Ye-NFC Okhethwayo"
"Ivuemela uhlelo lokusebenza ukuthola ulwazi lesevisi yenkokhelo ye-nfc njengezinsiza zokubhalisa nezindawo zomzila."
"lawula Uxhumano Lwenkambu Eseduze"
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index e6dedce8feaf4836588e7cf55d7609414a8475d6..f6590b1360f8d98fd1e8bb1a5fe4fc66256023ae 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -1218,155 +1218,132 @@
it prevent any 'false' in any of its children. -->
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1376,23 +1353,41 @@
-
+
-
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -7753,14 +7748,14 @@
-
-
-
+
+
+
+
+
+
+
-
-
-
-
@@ -7771,7 +7766,7 @@
-
+
@@ -10284,23 +10279,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
@@ -10309,6 +10307,11 @@
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index f5bb554b0b32ce5c99aacc9c4990aa4885affc2b..13dd4a35564c29bd7aeb5fe6a331c38bec31f2fb 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -238,393 +238,319 @@
#F9AB00
-
+
#FFFFFF
-
+
#FEFBFF
-
+
#EEF0FF
-
+
#D9E2FF
-
+
#B0C6FF
-
+
#94AAE4
-
+
#7A90C8
-
+
#6076AC
-
+
#475D92
-
+
#2F4578
-
+
#152E60
-
+
#001945
-
+
#000000
-
-
+
#FFFFFF
-
+
#FEFBFF
-
+
#EEF0FF
-
+
#DCE2F9
-
+
#C0C6DC
-
+
#A4ABC1
-
+
#8A90A5
-
+
#70778B
-
+
#575E71
-
+
#404659
-
+
#2A3042
-
+
#151B2C
-
+
#000000
-
-
+
#FFFFFF
-
+
#FFFBFF
-
+
#FFEBFA
-
+
#FDD7FA
-
+
#E0BBDD
-
+
#C3A0C1
-
+
#A886A6
-
+
#8C6D8C
-
+
#725572
-
+
#593D59
-
+
#412742
-
+
#2A122C
-
+
#000000
-
-
+
#FFFFFF
-
+
#FEFBFF
-
+
#F1F0F7
-
+
#E2E2E9
-
+
#C6C6CD
-
+
#ABABB1
-
+
#909097
-
+
#76777D
-
+
#5D5E64
-
+
#45464C
-
+
#2F3036
-
+
#1A1B20
-
+
#000000
-
-
+
#FFFFFF
-
+
#FEFBFF
-
+
#F0F0FA
-
+
#E1E2EC
-
+
#C5C6D0
-
+
#A9ABB4
-
+
#8F9099
-
+
#757780
-
+
#5C5E67
-
+
#44464F
-
+
#2E3038
-
+
#191B23
-
+
#000000
-
-
- #ffffff
-
- #FFFBF9
-
- #FCEEEE
-
- #F9DEDC
-
- #F2B8B5
-
- #EC928E
-
- #E46962
-
- #DC362E
-
- #B3261E
-
- #8C1D18
-
- #601410
-
- #410E0B
-
+
+ #FFFFFF
+
+ #FFFBFF
+
+ #FFEDEA
+
+ #FFDAD6
+
+ #FFB4AB
+
+ #FF897D
+
+ #FF5449
+
+ #DE3730
+
+ #BA1A1A
+
+ #93000A
+
+ #690005
+
+ #410002
+
#000000
-
- #D9E2FF
- #001945
- #475D92
+ #FAF8FF
+ #D9E2FF
+ #000000
+ #44464F
+ #BA1A1A
+ #FFDAD6
+ #F1F0F7
+ #B0C6FF
+ #2F3036
+ #1A1B20
+ #FFFFFF
+ #93000A
#FFFFFF
- #DCE2F9
- #151B2C
- #575E71
+ #2F4578
#FFFFFF
- #FDD7FA
- #2A122C
- #725572
+ #404659
+ #1A1B20
+ #44464F
#FFFFFF
- #FAF8FF
- #1A1B20
+ #593D59
+ #757780
+ #C5C6D0
+ #76777D
+ #757780
+ #6076AC
+ #70778B
+ #8C6D8C
+ #475D92
+ #D9E2FF
+ #000000
+ #575E71
+ #DCE2F9
+ #000000
#FAF8FF
- #1A1B20
- #F4F3FA
- #FFFFFF
+ #FAF8FF
#EEEDF4
#E8E7EF
#E2E2E9
- #FAF8FF
+ #F4F3FA
+ #FFFFFF
#DAD9E0
+ #475D92
#E1E2EC
- #44464F
- #757780
- #C5C6D0
- #BA1A1A
- #FFFFFF
- #FFDAD6
- #410002
- #D9E2FF
- #44464F
- #000000
-#E2E2E9
- #C5C6D0
+ #725572
+ #FDD7FA
+ #E2E2E9
+ #E2E2E9
#E2E2E9
+ #C5C6D0
#E2E2E9
- #E2E2E9
- #6076AC
- #70778B
- #8C6D8C
- #76777D
- #757780
- #2F4578
- #D9E2FF
- #B0C6FF
+ #121318
+ #2F4578
+ #FFFFFF
+ #C5C6D0
+ #FFB4AB
+ #93000A
+ #2F3036
+ #475D92
+ #E2E2E9
+ #E2E2E9
+ #690005
+ #FFDAD6
#152E60
- #404659
- #DCE2F9
- #C0C6DC
+ #D9E2FF
#2A3042
- #593D59
- #FDD7FA
- #E0BBDD
+ #DCE2F9
+ #E2E2E9
+ #C5C6D0
#412742
- #121318
- #E2E2E9
+ #FDD7FA
+ #8F9099
+ #44464F
+ #76777D
+ #757780
+ #6076AC
+ #70778B
+ #8C6D8C
+ #B0C6FF
+ #2F4578
+ #000000
+ #C0C6DC
+ #404659
+ #000000
#121318
- #E2E2E9
- #1A1B20
- #0C0E13
+ #38393F
#1E1F25
#282A2F
#33343A
- #38393F
+ #1A1B20
+ #0C0E13
#121318
+ #B0C6FF
#44464F
- #C5C6D0
- #8F9099
- #44464F
- #FFB4AB
- #690005
- #93000A
- #FFDAD6
- #2F4578
- #C5C6D0
- #FFFFFF
+ #E0BBDD
+ #593D59
+ #1A1B20
#1A1B20
- #44464F
#1A1B20
+ #44464F
#1A1B20
- #1A1B20
- #6076AC
- #70778B
- #8C6D8C
- #76777D
- #757780
- #D9E2FF
- #B0C6FF
#001945
#2F4578
- #DCE2F9
- #C0C6DC
#151B2C
#404659
- #FDD7FA
- #E0BBDD
#2A122C
#593D59
-
-
- #EEF0FF
- #373D50
- #3D5487
- #4F659A
- #D9E2FF
- #475D92
- #94AAE4
- #E0BBDD
+ #D9E2FF
+ #B0C6FF
+ #DCE2F9
+ #C0C6DC
+ #FDD7FA
+ #E0BBDD
#475D92
#6E7488
#5E73A9
#8A6A89
- #000000
-#D9E2FF
+ #373D50
+ #3D5487
+ #725572
#152E60
#2F4578
- #2F3036
#E1E2EC
#C5C6D0
- #0C0E13
+ #475D92
#C5C6D0
- #152E60
- #8A90A5
- #D9E2FF
- #B0C6FF
- #2F4578
- #B0C6FF
- #94AAE4
- #FDD7FA
+ #D9E2FF
+ #0C0E13
+ #2F3036
+ #D9E2FF
+ #94AAE4
+ #E0BBDD
+ #000000
+ #4F659A
+ #EEF0FF
#B0C6FF
#DCE2F9
#7A90C8
#FDD7FA
- #000000
-#D9E2FF
+ #8A90A5
+ #D9E2FF
+ #FDD7FA
#001945
#2F4578
- #2F3036
#E1E2EC
#C5C6D0
- #0C0E13
+ #B0C6FF
#50525A
+ #D9E2FF
+ #0C0E13
+ #2F3036
+ #2F4578
+ #94AAE4
+ #FDD7FA
+ #000000
+ #B0C6FF
+ #152E60
#5F6368
diff --git a/core/res/res/values/colors_dynamic.xml b/core/res/res/values/colors_dynamic.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ab283eb3c6c845945b2500644eb862269ea26c62
--- /dev/null
+++ b/core/res/res/values/colors_dynamic.xml
@@ -0,0 +1,103 @@
+
+
+
+
+
+ @color/system_background_light
+ @color/system_control_activated_light
+ @color/system_control_highlight_light
+ @color/system_control_normal_light
+ @color/system_error_light
+ @color/system_error_container_light
+ @color/system_inverse_on_surface_light
+ @color/system_inverse_primary_light
+ @color/system_inverse_surface_light
+ @color/system_on_background_light
+ @color/system_on_error_light
+ @color/system_on_error_container_light
+ @color/system_on_primary_light
+ @color/system_on_primary_container_light
+ @color/system_on_secondary_light
+ @color/system_on_secondary_container_light
+ @color/system_on_surface_light
+ @color/system_on_surface_variant_light
+ @color/system_on_tertiary_light
+ @color/system_on_tertiary_container_light
+ @color/system_outline_light
+ @color/system_outline_variant_light
+ @color/system_palette_key_color_neutral_light
+ @color/system_palette_key_color_neutral_variant_light
+ @color/system_palette_key_color_primary_light
+ @color/system_palette_key_color_secondary_light
+ @color/system_palette_key_color_tertiary_light
+ @color/system_primary_light
+ @color/system_primary_container_light
+ @color/system_scrim_light
+ @color/system_secondary_light
+ @color/system_secondary_container_light
+ @color/system_shadow_light
+ @color/system_surface_light
+ @color/system_surface_bright_light
+ @color/system_surface_container_light
+ @color/system_surface_container_high_light
+ @color/system_surface_container_highest_light
+ @color/system_surface_container_low_light
+ @color/system_surface_container_lowest_light
+ @color/system_surface_dim_light
+ @color/system_surface_tint_light
+ @color/system_surface_variant_light
+ @color/system_tertiary_light
+ @color/system_tertiary_container_light
+ @color/system_text_hint_inverse_light
+ @color/system_text_primary_inverse_light
+ @color/system_text_primary_inverse_disable_only_light
+ @color/system_text_secondary_and_tertiary_inverse_light
+ @color/system_text_secondary_and_tertiary_inverse_disabled_light
+ @color/system_on_primary_fixed
+ @color/system_on_primary_fixed_variant
+ @color/system_on_secondary_fixed
+ @color/system_on_secondary_fixed_variant
+ @color/system_on_tertiary_fixed
+ @color/system_on_tertiary_fixed_variant
+ @color/system_primary_fixed
+ @color/system_primary_fixed_dim
+ @color/system_secondary_fixed
+ @color/system_secondary_fixed_dim
+ @color/system_tertiary_fixed
+ @color/system_tertiary_fixed_dim
+ @color/system_brand_a_light
+ @color/system_brand_b_light
+ @color/system_brand_c_light
+ @color/system_brand_d_light
+ @color/system_clock_hour_light
+ @color/system_clock_minute_light
+ @color/system_clock_second_light
+ @color/system_on_shade_active_light
+ @color/system_on_shade_active_variant_light
+ @color/system_on_shade_inactive_light
+ @color/system_on_shade_inactive_variant_light
+ @color/system_on_theme_app_light
+ @color/system_overview_background_light
+ @color/system_shade_active_light
+ @color/system_shade_disabled_light
+ @color/system_shade_inactive_light
+ @color/system_theme_app_light
+ @color/system_theme_app_ring_light
+ @color/system_theme_notif_light
+ @color/system_under_surface_light
+ @color/system_weather_temp_light
+ @color/system_widget_background_light
+
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 219cefd273ac05ffad115b9d4fd4ea9618030849..3f4ea2df9266f6411cc50388676302295d881cf3 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1849,6 +1849,10 @@
- -1
+
+ 30000
+
+ true
true
+
+ true
+
+ 0
@@ -5894,6 +5906,11 @@
+
+
+
com.android.server.location.ComprehensiveCountryDetector
@@ -6563,7 +6580,7 @@
- 32
+ 1024
false
@@ -7005,6 +7022,15 @@
+
+
+
+
+
@@ -7199,9 +7225,12 @@
com\u002eandroid\u002esettings
-
-
+
+
false
+
+
+
diff --git a/core/res/res/values/config_telephony.xml b/core/res/res/values/config_telephony.xml
index 31e9913dd98861134b7c9f3b2469be33b91582d0..4ec27a31df8c917d65476c6b7fb0d491a67f4655 100644
--- a/core/res/res/values/config_telephony.xml
+++ b/core/res/res/values/config_telephony.xml
@@ -318,6 +318,12 @@
true
+
+ true
+
+
16dp
-
+
52dp
+
+ 72dp
+
16dp
@@ -310,6 +315,9 @@
56dp
+
+ 72dp
+
49.5dp
@@ -331,9 +339,17 @@
24dp
+
+ 40dp
+
4dp
+
+ 8dp
+
16dp
@@ -803,6 +819,8 @@
16dp
@dimen/notification_icon_circle_size
+
+ @dimen/notification_2025_icon_circle_size
@dimen/notification_icon_circle_start
@@ -820,13 +838,13 @@
2dp
- 8dp
-
- 8dp
-
- 3dp
+ 4dp
6dp
+
+ 2dp
+
+ 16dp
6dp
diff --git a/core/res/res/values/public-staging.xml b/core/res/res/values/public-staging.xml
index b6436d0b30a5dd6f3e0a4997a96852dae63b48f7..b0b87d1dead68d32eda938830aee3ed69aef4ddd 100644
--- a/core/res/res/values/public-staging.xml
+++ b/core/res/res/values/public-staging.xml
@@ -131,6 +131,8 @@
+
+
@@ -140,12 +142,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/core/res/res/values/stoppable_fgs_system_apps.xml b/core/res/res/values/stoppable_fgs_system_apps.xml
index 165ff61c7b3e46da58bce01720c06d253892a2af..06843f4b4f76113e455639b80f79e0bf7f0ebc96 100644
--- a/core/res/res/values/stoppable_fgs_system_apps.xml
+++ b/core/res/res/values/stoppable_fgs_system_apps.xml
@@ -19,6 +19,7 @@
+ - com.android.virtualization.terminal
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index badb98686fb232cc96e5ee032babe305c4c33d2e..a2a19a23d43193c5bc384115efafdc136ae5f6d6 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2098,6 +2098,7 @@
+
@@ -2388,6 +2389,8 @@
+
+
@@ -3139,9 +3142,12 @@
-
+
+
+
+
@@ -3875,9 +3881,9 @@
-
-
+
+
@@ -5310,73 +5316,91 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -5678,8 +5702,8 @@
-
-
+
+
diff --git a/core/res/res/values/themes_device_defaults.xml b/core/res/res/values/themes_device_defaults.xml
index 352c3904406ca77445bcb2cfea92d02b0fe3d96f..d8346d87f62405a763763f76d1a0beca970b0089 100644
--- a/core/res/res/values/themes_device_defaults.xml
+++ b/core/res/res/values/themes_device_defaults.xml
@@ -239,73 +239,90 @@ easier.
- @color/foreground_device_default_dark
- @color/foreground_device_default_light
- - @color/system_on_secondary_fixed_variant
- - @color/system_on_tertiary_fixed_variant
- - @color/system_surface_container_lowest_dark
- - @color/system_on_primary_fixed_variant
- - @color/system_on_secondary_container_dark
- - @color/system_on_tertiary_container_dark
- - @color/system_surface_container_low_dark
- - @color/system_on_primary_container_dark
- - @color/system_secondary_fixed_dim
- - @color/system_on_error_container_dark
- - @color/system_on_secondary_fixed
- - @color/system_on_surface_light
- - @color/system_tertiary_fixed_dim
- - @color/system_on_tertiary_fixed
- - @color/system_primary_fixed_dim
- - @color/system_secondary_container_dark
+ - @color/system_background_dark
+ - @color/system_control_activated_dark
+ - @color/system_control_highlight_dark
+ - @color/system_control_normal_dark
+ - @color/system_error_dark
- @color/system_error_container_dark
- - @color/system_on_primary_fixed
- - @color/system_primary_light
- - @color/system_secondary_fixed
- - @color/system_surface_light
- - @color/system_surface_variant_dark
- - @color/system_tertiary_container_dark
- - @color/system_tertiary_fixed
- - @color/system_primary_container_dark
+ - @color/system_inverse_on_surface_dark
+ - @color/system_inverse_primary_dark
+ - @color/system_inverse_surface_dark
- @color/system_on_background_dark
- - @color/system_primary_fixed
- - @color/system_on_secondary_dark
- - @color/system_on_tertiary_dark
- - @color/system_surface_dim_dark
- - @color/system_surface_bright_dark
- @color/system_on_error_dark
- - @color/system_surface_dark
- - @color/system_surface_container_high_dark
- - @color/system_surface_container_highest_dark
+ - @color/system_on_error_container_dark
+ - @color/system_on_primary_dark
+ - @color/system_on_primary_container_dark
+ - @color/system_on_secondary_dark
+ - @color/system_on_secondary_container_dark
+ - @color/system_on_surface_dark
- @color/system_on_surface_variant_dark
+ - @color/system_on_tertiary_dark
+ - @color/system_on_tertiary_container_dark
- @color/system_outline_dark
- @color/system_outline_variant_dark
- - @color/system_on_primary_dark
- - @color/system_on_surface_dark
- - @color/system_surface_container_dark
+ - @color/system_palette_key_color_neutral_dark
+ - @color/system_palette_key_color_neutral_variant_dark
+ - @color/system_palette_key_color_primary_dark
+ - @color/system_palette_key_color_secondary_dark
+ - @color/system_palette_key_color_tertiary_dark
- @color/system_primary_dark
+ - @color/system_primary_container_dark
+ - @color/system_scrim_dark
- @color/system_secondary_dark
+ - @color/system_secondary_container_dark
+ - @color/system_shadow_dark
+ - @color/system_surface_dark
+ - @color/system_surface_bright_dark
+ - @color/system_surface_container_dark
+ - @color/system_surface_container_high_dark
+ - @color/system_surface_container_highest_dark
+ - @color/system_surface_container_low_dark
+ - @color/system_surface_container_lowest_dark
+ - @color/system_surface_dim_dark
+ - @color/system_surface_tint_dark
+ - @color/system_surface_variant_dark
- @color/system_tertiary_dark
- - @color/system_error_dark
-
- - @color/system_widget_background_dark
- - @color/system_clock_hour_dark
- - @color/system_clock_minute_dark
- - @color/system_clock_second_dark
- - @color/system_theme_app_dark
- - @color/system_on_theme_app_dark
- - @color/system_theme_app_ring_dark
- - @color/system_theme_notif_dark
+ - @color/system_tertiary_container_dark
+ - @color/system_text_hint_inverse_dark
+ - @color/system_text_primary_inverse_dark
+ - @color/system_text_primary_inverse_disable_only_dark
+ - @color/system_text_secondary_and_tertiary_inverse_dark
+ - @color/system_text_secondary_and_tertiary_inverse_disabled_dark
+ - @color/system_on_primary_fixed
+ - @color/system_on_primary_fixed_variant
+ - @color/system_on_secondary_fixed
+ - @color/system_on_secondary_fixed_variant
+ - @color/system_on_tertiary_fixed
+ - @color/system_on_tertiary_fixed_variant
+ - @color/system_primary_fixed
+ - @color/system_primary_fixed_dim
+ - @color/system_secondary_fixed
+ - @color/system_secondary_fixed_dim
+ - @color/system_tertiary_fixed
+ - @color/system_tertiary_fixed_dim
- @color/system_brand_a_dark
- @color/system_brand_b_dark
- @color/system_brand_c_dark
- @color/system_brand_d_dark
- - @color/system_under_surface_dark
- - @color/system_shade_active_dark
+ - @color/system_clock_hour_dark
+ - @color/system_clock_minute_dark
+ - @color/system_clock_second_dark
- @color/system_on_shade_active_dark
- @color/system_on_shade_active_variant_dark
- - @color/system_shade_inactive_dark
- @color/system_on_shade_inactive_dark
- @color/system_on_shade_inactive_variant_dark
- - @color/system_shade_disabled_dark
+ - @color/system_on_theme_app_dark
- @color/system_overview_background_dark
+ - @color/system_shade_active_dark
+ - @color/system_shade_disabled_dark
+ - @color/system_shade_inactive_dark
+ - @color/system_theme_app_dark
+ - @color/system_theme_app_ring_dark
+ - @color/system_theme_notif_dark
+ - @color/system_under_surface_dark
+ - @color/system_weather_temp_dark
+ - @color/system_widget_background_dark
@@ -357,73 +374,90 @@ easier.
- @style/Widget.DeviceDefault.Toolbar
- - @color/system_on_secondary_fixed_variant
- - @color/system_on_tertiary_fixed_variant
- - @color/system_surface_container_lowest_dark
- - @color/system_on_primary_fixed_variant
- - @color/system_on_secondary_container_dark
- - @color/system_on_tertiary_container_dark
- - @color/system_surface_container_low_dark
- - @color/system_on_primary_container_dark
- - @color/system_secondary_fixed_dim
- - @color/system_on_error_container_dark
- - @color/system_on_secondary_fixed
- - @color/system_on_surface_light
- - @color/system_tertiary_fixed_dim
- - @color/system_on_tertiary_fixed
- - @color/system_primary_fixed_dim
- - @color/system_secondary_container_dark
+ - @color/system_background_dark
+ - @color/system_control_activated_dark
+ - @color/system_control_highlight_dark
+ - @color/system_control_normal_dark
+ - @color/system_error_dark
- @color/system_error_container_dark
- - @color/system_on_primary_fixed
- - @color/system_primary_light
- - @color/system_secondary_fixed
- - @color/system_surface_light
- - @color/system_surface_variant_dark
- - @color/system_tertiary_container_dark
- - @color/system_tertiary_fixed
- - @color/system_primary_container_dark
+ - @color/system_inverse_on_surface_dark
+ - @color/system_inverse_primary_dark
+ - @color/system_inverse_surface_dark
- @color/system_on_background_dark
- - @color/system_primary_fixed
- - @color/system_on_secondary_dark
- - @color/system_on_tertiary_dark
- - @color/system_surface_dim_dark
- - @color/system_surface_bright_dark
- @color/system_on_error_dark
- - @color/system_surface_dark
- - @color/system_surface_container_high_dark
- - @color/system_surface_container_highest_dark
+ - @color/system_on_error_container_dark
+ - @color/system_on_primary_dark
+ - @color/system_on_primary_container_dark
+ - @color/system_on_secondary_dark
+ - @color/system_on_secondary_container_dark
+ - @color/system_on_surface_dark
- @color/system_on_surface_variant_dark
+ - @color/system_on_tertiary_dark
+ - @color/system_on_tertiary_container_dark
- @color/system_outline_dark
- @color/system_outline_variant_dark
- - @color/system_on_primary_dark
- - @color/system_on_surface_dark
- - @color/system_surface_container_dark
+ - @color/system_palette_key_color_neutral_dark
+ - @color/system_palette_key_color_neutral_variant_dark
+ - @color/system_palette_key_color_primary_dark
+ - @color/system_palette_key_color_secondary_dark
+ - @color/system_palette_key_color_tertiary_dark
- @color/system_primary_dark
+ - @color/system_primary_container_dark
+ - @color/system_scrim_dark
- @color/system_secondary_dark
+ - @color/system_secondary_container_dark
+ - @color/system_shadow_dark
+ - @color/system_surface_dark
+ - @color/system_surface_bright_dark
+ - @color/system_surface_container_dark
+ - @color/system_surface_container_high_dark
+ - @color/system_surface_container_highest_dark
+ - @color/system_surface_container_low_dark
+ - @color/system_surface_container_lowest_dark
+ - @color/system_surface_dim_dark
+ - @color/system_surface_tint_dark
+ - @color/system_surface_variant_dark
- @color/system_tertiary_dark
- - @color/system_error_dark
-
- - @color/system_widget_background_dark
- - @color/system_clock_hour_dark
- - @color/system_clock_minute_dark
- - @color/system_clock_second_dark
- - @color/system_theme_app_dark
- - @color/system_on_theme_app_dark
- - @color/system_theme_app_ring_dark
- - @color/system_theme_notif_dark
+ - @color/system_tertiary_container_dark
+ - @color/system_text_hint_inverse_dark
+ - @color/system_text_primary_inverse_dark
+ - @color/system_text_primary_inverse_disable_only_dark
+ - @color/system_text_secondary_and_tertiary_inverse_dark
+ - @color/system_text_secondary_and_tertiary_inverse_disabled_dark
+ - @color/system_on_primary_fixed
+ - @color/system_on_primary_fixed_variant
+ - @color/system_on_secondary_fixed
+ - @color/system_on_secondary_fixed_variant
+ - @color/system_on_tertiary_fixed
+ - @color/system_on_tertiary_fixed_variant
+ - @color/system_primary_fixed
+ - @color/system_primary_fixed_dim
+ - @color/system_secondary_fixed
+ - @color/system_secondary_fixed_dim
+ - @color/system_tertiary_fixed
+ - @color/system_tertiary_fixed_dim
- @color/system_brand_a_dark
- @color/system_brand_b_dark
- @color/system_brand_c_dark
- @color/system_brand_d_dark
- - @color/system_under_surface_dark
- - @color/system_shade_active_dark
+ - @color/system_clock_hour_dark
+ - @color/system_clock_minute_dark
+ - @color/system_clock_second_dark
- @color/system_on_shade_active_dark
- @color/system_on_shade_active_variant_dark
- - @color/system_shade_inactive_dark
- @color/system_on_shade_inactive_dark
- @color/system_on_shade_inactive_variant_dark
- - @color/system_shade_disabled_dark
+ - @color/system_on_theme_app_dark
- @color/system_overview_background_dark
+ - @color/system_shade_active_dark
+ - @color/system_shade_disabled_dark
+ - @color/system_shade_inactive_dark
+ - @color/system_theme_app_dark
+ - @color/system_theme_app_ring_dark
+ - @color/system_theme_notif_dark
+ - @color/system_under_surface_dark
+ - @color/system_weather_temp_dark
+ - @color/system_widget_background_dark
- @style/Widget.DeviceDefault.Toolbar
- - @color/system_on_secondary_fixed_variant
- - @color/system_on_tertiary_fixed_variant
- - @color/system_surface_container_lowest_dark
- - @color/system_on_primary_fixed_variant
- - @color/system_on_secondary_container_dark
- - @color/system_on_tertiary_container_dark
- - @color/system_surface_container_low_dark
- - @color/system_on_primary_container_dark
- - @color/system_secondary_fixed_dim
- - @color/system_on_error_container_dark
- - @color/system_on_secondary_fixed
- - @color/system_on_surface_light
- - @color/system_tertiary_fixed_dim
- - @color/system_on_tertiary_fixed
- - @color/system_primary_fixed_dim
- - @color/system_secondary_container_dark
+ - @color/system_background_dark
+ - @color/system_control_activated_dark
+ - @color/system_control_highlight_dark
+ - @color/system_control_normal_dark
+ - @color/system_error_dark
- @color/system_error_container_dark
- - @color/system_on_primary_fixed
- - @color/system_primary_light
- - @color/system_secondary_fixed
- - @color/system_surface_light
- - @color/system_surface_variant_dark
- - @color/system_tertiary_container_dark
- - @color/system_tertiary_fixed
- - @color/system_primary_container_dark
+ - @color/system_inverse_on_surface_dark
+ - @color/system_inverse_primary_dark
+ - @color/system_inverse_surface_dark
- @color/system_on_background_dark
- - @color/system_primary_fixed
- - @color/system_on_secondary_dark
- - @color/system_on_tertiary_dark
- - @color/system_surface_dim_dark
- - @color/system_surface_bright_dark
- @color/system_on_error_dark
- - @color/system_surface_dark
- - @color/system_surface_container_high_dark
- - @color/system_surface_container_highest_dark
+ - @color/system_on_error_container_dark
+ - @color/system_on_primary_dark
+ - @color/system_on_primary_container_dark
+ - @color/system_on_secondary_dark
+ - @color/system_on_secondary_container_dark
+ - @color/system_on_surface_dark
- @color/system_on_surface_variant_dark
+ - @color/system_on_tertiary_dark
+ - @color/system_on_tertiary_container_dark
- @color/system_outline_dark
- @color/system_outline_variant_dark
- - @color/system_on_primary_dark
- - @color/system_on_surface_dark
- - @color/system_surface_container_dark
+ - @color/system_palette_key_color_neutral_dark
+ - @color/system_palette_key_color_neutral_variant_dark
+ - @color/system_palette_key_color_primary_dark
+ - @color/system_palette_key_color_secondary_dark
+ - @color/system_palette_key_color_tertiary_dark
- @color/system_primary_dark
+ - @color/system_primary_container_dark
+ - @color/system_scrim_dark
- @color/system_secondary_dark
+ - @color/system_secondary_container_dark
+ - @color/system_shadow_dark
+ - @color/system_surface_dark
+ - @color/system_surface_bright_dark
+ - @color/system_surface_container_dark
+ - @color/system_surface_container_high_dark
+ - @color/system_surface_container_highest_dark
+ - @color/system_surface_container_low_dark
+ - @color/system_surface_container_lowest_dark
+ - @color/system_surface_dim_dark
+ - @color/system_surface_tint_dark
+ - @color/system_surface_variant_dark
- @color/system_tertiary_dark
- - @color/system_error_dark
-
- - @color/system_widget_background_dark
+ - @color/system_tertiary_container_dark
+ - @color/system_text_hint_inverse_dark
+ - @color/system_text_primary_inverse_dark
+ - @color/system_text_primary_inverse_disable_only_dark
+ - @color/system_text_secondary_and_tertiary_inverse_dark
+ - @color/system_text_secondary_and_tertiary_inverse_disabled_dark
+ - @color/system_on_primary_fixed
+ - @color/system_on_primary_fixed_variant
+ - @color/system_on_secondary_fixed
+ - @color/system_on_secondary_fixed_variant
+ - @color/system_on_tertiary_fixed
+ - @color/system_on_tertiary_fixed_variant
+ - @color/system_primary_fixed
+ - @color/system_primary_fixed_dim
+ - @color/system_secondary_fixed
+ - @color/system_secondary_fixed_dim
+ - @color/system_tertiary_fixed
+ - @color/system_tertiary_fixed_dim
+ - @color/system_brand_a_dark
+ - @color/system_brand_b_dark
+ - @color/system_brand_c_dark
+ - @color/system_brand_d_dark
- @color/system_clock_hour_dark
- @color/system_clock_minute_dark
- @color/system_clock_second_dark
- - @color/system_theme_app_dark
- - @color/system_on_theme_app_dark
- - @color/system_theme_app_ring_dark
- - @color/system_theme_notif_dark
- - @color/system_brand_a_dark
- - @color/system_brand_b_dark
- - @color/system_brand_c_dark
- - @color/system_brand_d_dark
- - @color/system_under_surface_dark
- - @color/system_shade_active_dark
- @color/system_on_shade_active_dark
- @color/system_on_shade_active_variant_dark
- - @color/system_shade_inactive_dark
- @color/system_on_shade_inactive_dark
- @color/system_on_shade_inactive_variant_dark
- - @color/system_shade_disabled_dark
+ - @color/system_on_theme_app_dark
- @color/system_overview_background_dark
+ - @color/system_shade_active_dark
+ - @color/system_shade_disabled_dark
+ - @color/system_shade_inactive_dark
+ - @color/system_theme_app_dark
+ - @color/system_theme_app_ring_dark
+ - @color/system_theme_notif_dark
+ - @color/system_under_surface_dark
+ - @color/system_weather_temp_dark
+ - @color/system_widget_background_dark
- @style/Widget.DeviceDefault.Toolbar
- - @color/system_on_secondary_fixed_variant
- - @color/system_on_tertiary_fixed_variant
- - @color/system_surface_container_lowest_dark
- - @color/system_on_primary_fixed_variant
- - @color/system_on_secondary_container_dark
- - @color/system_on_tertiary_container_dark
- - @color/system_surface_container_low_dark
- - @color/system_on_primary_container_dark
- - @color/system_secondary_fixed_dim
- - @color/system_on_error_container_dark
- - @color/system_on_secondary_fixed
- - @color/system_on_surface_light
- - @color/system_tertiary_fixed_dim
- - @color/system_on_tertiary_fixed
- - @color/system_primary_fixed_dim
- - @color/system_secondary_container_dark
+ - @color/system_background_dark
+ - @color/system_control_activated_dark
+ - @color/system_control_highlight_dark
+ - @color/system_control_normal_dark
+ - @color/system_error_dark
- @color/system_error_container_dark
- - @color/system_on_primary_fixed
- - @color/system_primary_light
- - @color/system_secondary_fixed
- - @color/system_surface_light
- - @color/system_surface_variant_dark
- - @color/system_tertiary_container_dark
- - @color/system_tertiary_fixed
- - @color/system_primary_container_dark
+ - @color/system_inverse_on_surface_dark
+ - @color/system_inverse_primary_dark
+ - @color/system_inverse_surface_dark
- @color/system_on_background_dark
- - @color/system_primary_fixed
- - @color/system_on_secondary_dark
- - @color/system_on_tertiary_dark
- - @color/system_surface_dim_dark
- - @color/system_surface_bright_dark
- @color/system_on_error_dark
- - @color/system_surface_dark
- - @color/system_surface_container_high_dark
- - @color/system_surface_container_highest_dark
+ - @color/system_on_error_container_dark
+ - @color/system_on_primary_dark
+ - @color/system_on_primary_container_dark
+ - @color/system_on_secondary_dark
+ - @color/system_on_secondary_container_dark
+ - @color/system_on_surface_dark
- @color/system_on_surface_variant_dark
+ - @color/system_on_tertiary_dark
+ - @color/system_on_tertiary_container_dark
- @color/system_outline_dark
- @color/system_outline_variant_dark
- - @color/system_on_primary_dark
- - @color/system_on_surface_dark
- - @color/system_surface_container_dark
+ - @color/system_palette_key_color_neutral_dark
+ - @color/system_palette_key_color_neutral_variant_dark
+ - @color/system_palette_key_color_primary_dark
+ - @color/system_palette_key_color_secondary_dark
+ - @color/system_palette_key_color_tertiary_dark
- @color/system_primary_dark
+ - @color/system_primary_container_dark
+ - @color/system_scrim_dark
- @color/system_secondary_dark
+ - @color/system_secondary_container_dark
+ - @color/system_shadow_dark
+ - @color/system_surface_dark
+ - @color/system_surface_bright_dark
+ - @color/system_surface_container_dark
+ - @color/system_surface_container_high_dark
+ - @color/system_surface_container_highest_dark
+ - @color/system_surface_container_low_dark
+ - @color/system_surface_container_lowest_dark
+ - @color/system_surface_dim_dark
+ - @color/system_surface_tint_dark
+ - @color/system_surface_variant_dark
- @color/system_tertiary_dark
- - @color/system_error_dark
-
- - @color/system_widget_background_dark
- - @color/system_clock_hour_dark
- - @color/system_clock_minute_dark
- - @color/system_clock_second_dark
- - @color/system_theme_app_dark
- - @color/system_on_theme_app_dark
- - @color/system_theme_app_ring_dark
- - @color/system_theme_notif_dark
+ - @color/system_tertiary_container_dark
+ - @color/system_text_hint_inverse_dark
+ - @color/system_text_primary_inverse_dark
+ - @color/system_text_primary_inverse_disable_only_dark
+ - @color/system_text_secondary_and_tertiary_inverse_dark
+ - @color/system_text_secondary_and_tertiary_inverse_disabled_dark
+ - @color/system_on_primary_fixed
+ - @color/system_on_primary_fixed_variant
+ - @color/system_on_secondary_fixed
+ - @color/system_on_secondary_fixed_variant
+ - @color/system_on_tertiary_fixed
+ - @color/system_on_tertiary_fixed_variant
+ - @color/system_primary_fixed
+ - @color/system_primary_fixed_dim
+ - @color/system_secondary_fixed
+ - @color/system_secondary_fixed_dim
+ - @color/system_tertiary_fixed
+ - @color/system_tertiary_fixed_dim
- @color/system_brand_a_dark
- @color/system_brand_b_dark
- @color/system_brand_c_dark
- @color/system_brand_d_dark
- - @color/system_under_surface_dark
- - @color/system_shade_active_dark
+ - @color/system_clock_hour_dark
+ - @color/system_clock_minute_dark
+ - @color/system_clock_second_dark
- @color/system_on_shade_active_dark
- @color/system_on_shade_active_variant_dark
- - @color/system_shade_inactive_dark
- @color/system_on_shade_inactive_dark
- @color/system_on_shade_inactive_variant_dark
- - @color/system_shade_disabled_dark
+ - @color/system_on_theme_app_dark
- @color/system_overview_background_dark
+ - @color/system_shade_active_dark
+ - @color/system_shade_disabled_dark
+ - @color/system_shade_inactive_dark
+ - @color/system_theme_app_dark
+ - @color/system_theme_app_ring_dark
+ - @color/system_theme_notif_dark
+ - @color/system_under_surface_dark
+ - @color/system_weather_temp_dark
+ - @color/system_widget_background_dark
- @style/Widget.DeviceDefault.Toolbar
- - @color/system_on_secondary_fixed_variant
- - @color/system_on_tertiary_fixed_variant
- - @color/system_surface_container_lowest_dark
- - @color/system_on_primary_fixed_variant
- - @color/system_on_secondary_container_dark
- - @color/system_on_tertiary_container_dark
- - @color/system_surface_container_low_dark
- - @color/system_on_primary_container_dark
- - @color/system_secondary_fixed_dim
- - @color/system_on_error_container_dark
- - @color/system_on_secondary_fixed
- - @color/system_on_surface_light
- - @color/system_tertiary_fixed_dim
- - @color/system_on_tertiary_fixed
- - @color/system_primary_fixed_dim
- - @color/system_secondary_container_dark
+ - @color/system_background_dark
+ - @color/system_control_activated_dark
+ - @color/system_control_highlight_dark
+ - @color/system_control_normal_dark
+ - @color/system_error_dark
- @color/system_error_container_dark
- - @color/system_on_primary_fixed
- - @color/system_primary_light
- - @color/system_secondary_fixed
- - @color/system_surface_light
- - @color/system_surface_variant_dark
- - @color/system_tertiary_container_dark
- - @color/system_tertiary_fixed
- - @color/system_primary_container_dark
+ - @color/system_inverse_on_surface_dark
+ - @color/system_inverse_primary_dark
+ - @color/system_inverse_surface_dark
- @color/system_on_background_dark
- - @color/system_primary_fixed
- - @color/system_on_secondary_dark
- - @color/system_on_tertiary_dark
- - @color/system_surface_dim_dark
- - @color/system_surface_bright_dark
- @color/system_on_error_dark
- - @color/system_surface_dark
- - @color/system_surface_container_high_dark
- - @color/system_surface_container_highest_dark
+ - @color/system_on_error_container_dark
+ - @color/system_on_primary_dark
+ - @color/system_on_primary_container_dark
+ - @color/system_on_secondary_dark
+ - @color/system_on_secondary_container_dark
+ - @color/system_on_surface_dark
- @color/system_on_surface_variant_dark
+ - @color/system_on_tertiary_dark
+ - @color/system_on_tertiary_container_dark
- @color/system_outline_dark
- @color/system_outline_variant_dark
- - @color/system_on_primary_dark
- - @color/system_on_surface_dark
- - @color/system_surface_container_dark
+ - @color/system_palette_key_color_neutral_dark
+ - @color/system_palette_key_color_neutral_variant_dark
+ - @color/system_palette_key_color_primary_dark
+ - @color/system_palette_key_color_secondary_dark
+ - @color/system_palette_key_color_tertiary_dark
- @color/system_primary_dark
+ - @color/system_primary_container_dark
+ - @color/system_scrim_dark
- @color/system_secondary_dark
+ - @color/system_secondary_container_dark
+ - @color/system_shadow_dark
+ - @color/system_surface_dark
+ - @color/system_surface_bright_dark
+ - @color/system_surface_container_dark
+ - @color/system_surface_container_high_dark
+ - @color/system_surface_container_highest_dark
+ - @color/system_surface_container_low_dark
+ - @color/system_surface_container_lowest_dark
+ - @color/system_surface_dim_dark
+ - @color/system_surface_tint_dark
+ - @color/system_surface_variant_dark
- @color/system_tertiary_dark
- - @color/system_error_dark
-
- - @color/system_widget_background_dark
- - @color/system_clock_hour_dark
- - @color/system_clock_minute_dark
- - @color/system_clock_second_dark
- - @color/system_theme_app_dark
- - @color/system_on_theme_app_dark
- - @color/system_theme_app_ring_dark
- - @color/system_theme_notif_dark
+ - @color/system_tertiary_container_dark
+ - @color/system_text_hint_inverse_dark
+ - @color/system_text_primary_inverse_dark
+ - @color/system_text_primary_inverse_disable_only_dark
+ - @color/system_text_secondary_and_tertiary_inverse_dark
+ - @color/system_text_secondary_and_tertiary_inverse_disabled_dark
+ - @color/system_on_primary_fixed
+ - @color/system_on_primary_fixed_variant
+ - @color/system_on_secondary_fixed
+ - @color/system_on_secondary_fixed_variant
+ - @color/system_on_tertiary_fixed
+ - @color/system_on_tertiary_fixed_variant
+ - @color/system_primary_fixed
+ - @color/system_primary_fixed_dim
+ - @color/system_secondary_fixed
+ - @color/system_secondary_fixed_dim
+ - @color/system_tertiary_fixed
+ - @color/system_tertiary_fixed_dim
- @color/system_brand_a_dark
- @color/system_brand_b_dark
- @color/system_brand_c_dark
- @color/system_brand_d_dark
- - @color/system_under_surface_dark
- - @color/system_shade_active_dark
+ - @color/system_clock_hour_dark
+ - @color/system_clock_minute_dark
+ - @color/system_clock_second_dark
- @color/system_on_shade_active_dark
- @color/system_on_shade_active_variant_dark
- - @color/system_shade_inactive_dark
- @color/system_on_shade_inactive_dark
- @color/system_on_shade_inactive_variant_dark
- - @color/system_shade_disabled_dark
+ - @color/system_on_theme_app_dark
- @color/system_overview_background_dark
+ - @color/system_shade_active_dark
+ - @color/system_shade_disabled_dark
+ - @color/system_shade_inactive_dark
+ - @color/system_theme_app_dark
+ - @color/system_theme_app_ring_dark
+ - @color/system_theme_notif_dark
+ - @color/system_under_surface_dark
+ - @color/system_weather_temp_dark
+ - @color/system_widget_background_dark
- @style/Widget.DeviceDefault.Toolbar
- - @color/system_on_secondary_fixed_variant
- - @color/system_on_tertiary_fixed_variant
- - @color/system_surface_container_lowest_dark
- - @color/system_on_primary_fixed_variant
- - @color/system_on_secondary_container_dark
- - @color/system_on_tertiary_container_dark
- - @color/system_surface_container_low_dark
- - @color/system_on_primary_container_dark
- - @color/system_secondary_fixed_dim
- - @color/system_on_error_container_dark
- - @color/system_on_secondary_fixed
- - @color/system_on_surface_light
- - @color/system_tertiary_fixed_dim
- - @color/system_on_tertiary_fixed
- - @color/system_primary_fixed_dim
- - @color/system_secondary_container_dark
+ - @color/system_background_dark
+ - @color/system_control_activated_dark
+ - @color/system_control_highlight_dark
+ - @color/system_control_normal_dark
+ - @color/system_error_dark
- @color/system_error_container_dark
- - @color/system_on_primary_fixed
- - @color/system_primary_light
- - @color/system_secondary_fixed
- - @color/system_surface_light
- - @color/system_surface_variant_dark
- - @color/system_tertiary_container_dark
- - @color/system_tertiary_fixed
- - @color/system_primary_container_dark
+ - @color/system_inverse_on_surface_dark
+ - @color/system_inverse_primary_dark
+ - @color/system_inverse_surface_dark
- @color/system_on_background_dark
- - @color/system_primary_fixed
- - @color/system_on_secondary_dark
- - @color/system_on_tertiary_dark
- - @color/system_surface_dim_dark
- - @color/system_surface_bright_dark
- @color/system_on_error_dark
- - @color/system_surface_dark
- - @color/system_surface_container_high_dark
- - @color/system_surface_container_highest_dark
+ - @color/system_on_error_container_dark
+ - @color/system_on_primary_dark
+ - @color/system_on_primary_container_dark
+ - @color/system_on_secondary_dark
+ - @color/system_on_secondary_container_dark
+ - @color/system_on_surface_dark
- @color/system_on_surface_variant_dark
+ - @color/system_on_tertiary_dark
+ - @color/system_on_tertiary_container_dark
- @color/system_outline_dark
- @color/system_outline_variant_dark
- - @color/system_on_primary_dark
- - @color/system_on_surface_dark
- - @color/system_surface_container_dark
+ - @color/system_palette_key_color_neutral_dark
+ - @color/system_palette_key_color_neutral_variant_dark
+ - @color/system_palette_key_color_primary_dark
+ - @color/system_palette_key_color_secondary_dark
+ - @color/system_palette_key_color_tertiary_dark
- @color/system_primary_dark
+ - @color/system_primary_container_dark
+ - @color/system_scrim_dark
- @color/system_secondary_dark
+ - @color/system_secondary_container_dark
+ - @color/system_shadow_dark
+ - @color/system_surface_dark
+ - @color/system_surface_bright_dark
+ - @color/system_surface_container_dark
+ - @color/system_surface_container_high_dark
+ - @color/system_surface_container_highest_dark
+ - @color/system_surface_container_low_dark
+ - @color/system_surface_container_lowest_dark
+ - @color/system_surface_dim_dark
+ - @color/system_surface_tint_dark
+ - @color/system_surface_variant_dark
- @color/system_tertiary_dark
- - @color/system_error_dark
-
- - @color/system_widget_background_dark
- - @color/system_clock_hour_dark
- - @color/system_clock_minute_dark
- - @color/system_clock_second_dark
- - @color/system_theme_app_dark
- - @color/system_on_theme_app_dark
- - @color/system_theme_app_ring_dark
- - @color/system_theme_notif_dark
+ - @color/system_tertiary_container_dark
+ - @color/system_text_hint_inverse_dark
+ - @color/system_text_primary_inverse_dark
+ - @color/system_text_primary_inverse_disable_only_dark
+ - @color/system_text_secondary_and_tertiary_inverse_dark
+ - @color/system_text_secondary_and_tertiary_inverse_disabled_dark
+ - @color/system_on_primary_fixed
+ - @color/system_on_primary_fixed_variant
+ - @color/system_on_secondary_fixed
+ - @color/system_on_secondary_fixed_variant
+ - @color/system_on_tertiary_fixed
+ - @color/system_on_tertiary_fixed_variant
+ - @color/system_primary_fixed
+ - @color/system_primary_fixed_dim
+ - @color/system_secondary_fixed
+ - @color/system_secondary_fixed_dim
+ - @color/system_tertiary_fixed
+ - @color/system_tertiary_fixed_dim
- @color/system_brand_a_dark
- @color/system_brand_b_dark
- @color/system_brand_c_dark
- @color/system_brand_d_dark
- - @color/system_under_surface_dark
- - @color/system_shade_active_dark
+ - @color/system_clock_hour_dark
+ - @color/system_clock_minute_dark
+ - @color/system_clock_second_dark
- @color/system_on_shade_active_dark
- @color/system_on_shade_active_variant_dark
- - @color/system_shade_inactive_dark
- @color/system_on_shade_inactive_dark
- @color/system_on_shade_inactive_variant_dark
- - @color/system_shade_disabled_dark
+ - @color/system_on_theme_app_dark
- @color/system_overview_background_dark
+ - @color/system_shade_active_dark
+ - @color/system_shade_disabled_dark
+ - @color/system_shade_inactive_dark
+ - @color/system_theme_app_dark
+ - @color/system_theme_app_ring_dark
+ - @color/system_theme_notif_dark
+ - @color/system_under_surface_dark
+ - @color/system_weather_temp_dark
+ - @color/system_widget_background_dark
- @style/Widget.DeviceDefault.Toolbar
- - @color/system_on_secondary_fixed_variant
- - @color/system_on_tertiary_fixed_variant
- - @color/system_surface_container_lowest_dark
- - @color/system_on_primary_fixed_variant
- - @color/system_on_secondary_container_dark
- - @color/system_on_tertiary_container_dark
- - @color/system_surface_container_low_dark
- - @color/system_on_primary_container_dark
- - @color/system_secondary_fixed_dim
- - @color/system_on_error_container_dark
- - @color/system_on_secondary_fixed
- - @color/system_on_surface_light
- - @color/system_tertiary_fixed_dim
- - @color/system_on_tertiary_fixed
- - @color/system_primary_fixed_dim
- - @color/system_secondary_container_dark
+ - @color/system_background_dark
+ - @color/system_control_activated_dark
+ - @color/system_control_highlight_dark
+ - @color/system_control_normal_dark
+ - @color/system_error_dark
- @color/system_error_container_dark
- - @color/system_on_primary_fixed
- - @color/system_primary_light
- - @color/system_secondary_fixed
- - @color/system_surface_light
- - @color/system_surface_variant_dark
- - @color/system_tertiary_container_dark
- - @color/system_tertiary_fixed
- - @color/system_primary_container_dark
+ - @color/system_inverse_on_surface_dark
+ - @color/system_inverse_primary_dark
+ - @color/system_inverse_surface_dark
- @color/system_on_background_dark
- - @color/system_primary_fixed
- - @color/system_on_secondary_dark
- - @color/system_on_tertiary_dark
- - @color/system_surface_dim_dark
- - @color/system_surface_bright_dark
- @color/system_on_error_dark
- - @color/system_surface_dark
- - @color/system_surface_container_high_dark
- - @color/system_surface_container_highest_dark
+ - @color/system_on_error_container_dark
+ - @color/system_on_primary_dark
+ - @color/system_on_primary_container_dark
+ - @color/system_on_secondary_dark
+ - @color/system_on_secondary_container_dark
+ - @color/system_on_surface_dark
- @color/system_on_surface_variant_dark
+ - @color/system_on_tertiary_dark
+ - @color/system_on_tertiary_container_dark
- @color/system_outline_dark
- @color/system_outline_variant_dark
- - @color/system_on_primary_dark
- - @color/system_on_surface_dark
- - @color/system_surface_container_dark
+ - @color/system_palette_key_color_neutral_dark
+ - @color/system_palette_key_color_neutral_variant_dark
+ - @color/system_palette_key_color_primary_dark
+ - @color/system_palette_key_color_secondary_dark
+ - @color/system_palette_key_color_tertiary_dark
- @color/system_primary_dark
+ - @color/system_primary_container_dark
+ - @color/system_scrim_dark
- @color/system_secondary_dark
+ - @color/system_secondary_container_dark
+ - @color/system_shadow_dark
+ - @color/system_surface_dark
+ - @color/system_surface_bright_dark
+ - @color/system_surface_container_dark
+ - @color/system_surface_container_high_dark
+ - @color/system_surface_container_highest_dark
+ - @color/system_surface_container_low_dark
+ - @color/system_surface_container_lowest_dark
+ - @color/system_surface_dim_dark
+ - @color/system_surface_tint_dark
+ - @color/system_surface_variant_dark
- @color/system_tertiary_dark
- - @color/system_error_dark
-
- - @color/system_widget_background_dark
- - @color/system_clock_hour_dark
- - @color/system_clock_minute_dark
- - @color/system_clock_second_dark
- - @color/system_theme_app_dark
- - @color/system_on_theme_app_dark
- - @color/system_theme_app_ring_dark
- - @color/system_theme_notif_dark
+ - @color/system_tertiary_container_dark
+ - @color/system_text_hint_inverse_dark
+ - @color/system_text_primary_inverse_dark
+ - @color/system_text_primary_inverse_disable_only_dark
+ - @color/system_text_secondary_and_tertiary_inverse_dark
+ - @color/system_text_secondary_and_tertiary_inverse_disabled_dark
+ - @color/system_on_primary_fixed
+ - @color/system_on_primary_fixed_variant
+ - @color/system_on_secondary_fixed
+ - @color/system_on_secondary_fixed_variant
+ - @color/system_on_tertiary_fixed
+ - @color/system_on_tertiary_fixed_variant
+ - @color/system_primary_fixed
+ - @color/system_primary_fixed_dim
+ - @color/system_secondary_fixed
+ - @color/system_secondary_fixed_dim
+ - @color/system_tertiary_fixed
+ - @color/system_tertiary_fixed_dim
- @color/system_brand_a_dark
- @color/system_brand_b_dark
- @color/system_brand_c_dark
- @color/system_brand_d_dark
- - @color/system_under_surface_dark
- - @color/system_shade_active_dark
+ - @color/system_clock_hour_dark
+ - @color/system_clock_minute_dark
+ - @color/system_clock_second_dark
- @color/system_on_shade_active_dark
- @color/system_on_shade_active_variant_dark
- - @color/system_shade_inactive_dark
- @color/system_on_shade_inactive_dark
- @color/system_on_shade_inactive_variant_dark
- - @color/system_shade_disabled_dark
+ - @color/system_on_theme_app_dark
- @color/system_overview_background_dark
+ - @color/system_shade_active_dark
+ - @color/system_shade_disabled_dark
+ - @color/system_shade_inactive_dark
+ - @color/system_theme_app_dark
+ - @color/system_theme_app_ring_dark
+ - @color/system_theme_notif_dark
+ - @color/system_under_surface_dark
+ - @color/system_weather_temp_dark
+ - @color/system_widget_background_dark
@@ -1070,73 +1189,90 @@ easier.
- @style/Widget.DeviceDefault.Toolbar
- - @color/system_on_secondary_fixed_variant
- - @color/system_on_tertiary_fixed_variant
- - @color/system_surface_container_lowest_dark
- - @color/system_on_primary_fixed_variant
- - @color/system_on_secondary_container_dark
- - @color/system_on_tertiary_container_dark
- - @color/system_surface_container_low_dark
- - @color/system_on_primary_container_dark
- - @color/system_secondary_fixed_dim
- - @color/system_on_error_container_dark
- - @color/system_on_secondary_fixed
- - @color/system_on_surface_light
- - @color/system_tertiary_fixed_dim
- - @color/system_on_tertiary_fixed
- - @color/system_primary_fixed_dim
- - @color/system_secondary_container_dark
+ - @color/system_background_dark
+ - @color/system_control_activated_dark
+ - @color/system_control_highlight_dark
+ - @color/system_control_normal_dark
+ - @color/system_error_dark
- @color/system_error_container_dark
- - @color/system_on_primary_fixed
- - @color/system_primary_light
- - @color/system_secondary_fixed
- - @color/system_surface_light
- - @color/system_surface_variant_dark
- - @color/system_tertiary_container_dark
- - @color/system_tertiary_fixed
- - @color/system_primary_container_dark
+ - @color/system_inverse_on_surface_dark
+ - @color/system_inverse_primary_dark
+ - @color/system_inverse_surface_dark
- @color/system_on_background_dark
- - @color/system_primary_fixed
- - @color/system_on_secondary_dark
- - @color/system_on_tertiary_dark
- - @color/system_surface_dim_dark
- - @color/system_surface_bright_dark
- @color/system_on_error_dark
- - @color/system_surface_dark
- - @color/system_surface_container_high_dark
- - @color/system_surface_container_highest_dark
+ - @color/system_on_error_container_dark
+ - @color/system_on_primary_dark
+ - @color/system_on_primary_container_dark
+ - @color/system_on_secondary_dark
+ - @color/system_on_secondary_container_dark
+ - @color/system_on_surface_dark
- @color/system_on_surface_variant_dark
+ - @color/system_on_tertiary_dark
+ - @color/system_on_tertiary_container_dark
- @color/system_outline_dark
- @color/system_outline_variant_dark
- - @color/system_on_primary_dark
- - @color/system_on_surface_dark
- - @color/system_surface_container_dark
+ - @color/system_palette_key_color_neutral_dark
+ - @color/system_palette_key_color_neutral_variant_dark
+ - @color/system_palette_key_color_primary_dark
+ - @color/system_palette_key_color_secondary_dark
+ - @color/system_palette_key_color_tertiary_dark
- @color/system_primary_dark
+ - @color/system_primary_container_dark
+ - @color/system_scrim_dark
- @color/system_secondary_dark
+ - @color/system_secondary_container_dark
+ - @color/system_shadow_dark
+ - @color/system_surface_dark
+ - @color/system_surface_bright_dark
+ - @color/system_surface_container_dark
+ - @color/system_surface_container_high_dark
+ - @color/system_surface_container_highest_dark
+ - @color/system_surface_container_low_dark
+ - @color/system_surface_container_lowest_dark
+ - @color/system_surface_dim_dark
+ - @color/system_surface_tint_dark
+ - @color/system_surface_variant_dark
- @color/system_tertiary_dark
- - @color/system_error_dark
-
- - @color/system_widget_background_dark
- - @color/system_clock_hour_dark
- - @color/system_clock_minute_dark
- - @color/system_clock_second_dark
- - @color/system_theme_app_dark
- - @color/system_on_theme_app_dark
- - @color/system_theme_app_ring_dark
- - @color/system_theme_notif_dark
+ - @color/system_tertiary_container_dark
+ - @color/system_text_hint_inverse_dark
+ - @color/system_text_primary_inverse_dark
+ - @color/system_text_primary_inverse_disable_only_dark
+ - @color/system_text_secondary_and_tertiary_inverse_dark
+ - @color/system_text_secondary_and_tertiary_inverse_disabled_dark
+ - @color/system_on_primary_fixed
+ - @color/system_on_primary_fixed_variant
+ - @color/system_on_secondary_fixed
+ - @color/system_on_secondary_fixed_variant
+ - @color/system_on_tertiary_fixed
+ - @color/system_on_tertiary_fixed_variant
+ - @color/system_primary_fixed
+ - @color/system_primary_fixed_dim
+ - @color/system_secondary_fixed
+ - @color/system_secondary_fixed_dim
+ - @color/system_tertiary_fixed
+ - @color/system_tertiary_fixed_dim
- @color/system_brand_a_dark
- @color/system_brand_b_dark
- @color/system_brand_c_dark
- @color/system_brand_d_dark
- - @color/system_under_surface_dark
- - @color/system_shade_active_dark
+ - @color/system_clock_hour_dark
+ - @color/system_clock_minute_dark
+ - @color/system_clock_second_dark
- @color/system_on_shade_active_dark
- @color/system_on_shade_active_variant_dark
- - @color/system_shade_inactive_dark
- @color/system_on_shade_inactive_dark
- @color/system_on_shade_inactive_variant_dark
- - @color/system_shade_disabled_dark
+ - @color/system_on_theme_app_dark
- @color/system_overview_background_dark
+ - @color/system_shade_active_dark
+ - @color/system_shade_disabled_dark
+ - @color/system_shade_inactive_dark
+ - @color/system_theme_app_dark
+ - @color/system_theme_app_ring_dark
+ - @color/system_theme_notif_dark
+ - @color/system_under_surface_dark
+ - @color/system_weather_temp_dark
+ - @color/system_widget_background_dark
- @style/Widget.DeviceDefault.Toolbar
- - @color/system_on_secondary_fixed_variant
- - @color/system_on_tertiary_fixed_variant
- - @color/system_surface_container_lowest_dark
- - @color/system_on_primary_fixed_variant
- - @color/system_on_secondary_container_dark
- - @color/system_on_tertiary_container_dark
- - @color/system_surface_container_low_dark
- - @color/system_on_primary_container_dark
- - @color/system_secondary_fixed_dim
- - @color/system_on_error_container_dark
- - @color/system_on_secondary_fixed
- - @color/system_on_surface_light
- - @color/system_tertiary_fixed_dim
- - @color/system_on_tertiary_fixed
- - @color/system_primary_fixed_dim
- - @color/system_secondary_container_dark
+ - @color/system_background_dark
+ - @color/system_control_activated_dark
+ - @color/system_control_highlight_dark
+ - @color/system_control_normal_dark
+ - @color/system_error_dark
- @color/system_error_container_dark
- - @color/system_on_primary_fixed
- - @color/system_primary_light
- - @color/system_secondary_fixed
- - @color/system_surface_light
- - @color/system_surface_variant_dark
- - @color/system_tertiary_container_dark
- - @color/system_tertiary_fixed
- - @color/system_primary_container_dark
+ - @color/system_inverse_on_surface_dark
+ - @color/system_inverse_primary_dark
+ - @color/system_inverse_surface_dark
- @color/system_on_background_dark
- - @color/system_primary_fixed
- - @color/system_on_secondary_dark
- - @color/system_on_tertiary_dark
- - @color/system_surface_dim_dark
- - @color/system_surface_bright_dark
- @color/system_on_error_dark
- - @color/system_surface_dark
- - @color/system_surface_container_high_dark
- - @color/system_surface_container_highest_dark
+ - @color/system_on_error_container_dark
+ - @color/system_on_primary_dark
+ - @color/system_on_primary_container_dark
+ - @color/system_on_secondary_dark
+ - @color/system_on_secondary_container_dark
+ - @color/system_on_surface_dark
- @color/system_on_surface_variant_dark
+ - @color/system_on_tertiary_dark
+ - @color/system_on_tertiary_container_dark
- @color/system_outline_dark
- @color/system_outline_variant_dark
- - @color/system_on_primary_dark
- - @color/system_on_surface_dark
- - @color/system_surface_container_dark
+ - @color/system_palette_key_color_neutral_dark
+ - @color/system_palette_key_color_neutral_variant_dark
+ - @color/system_palette_key_color_primary_dark
+ - @color/system_palette_key_color_secondary_dark
+ - @color/system_palette_key_color_tertiary_dark
- @color/system_primary_dark
+ - @color/system_primary_container_dark
+ - @color/system_scrim_dark
- @color/system_secondary_dark
+ - @color/system_secondary_container_dark
+ - @color/system_shadow_dark
+ - @color/system_surface_dark
+ - @color/system_surface_bright_dark
+ - @color/system_surface_container_dark
+ - @color/system_surface_container_high_dark
+ - @color/system_surface_container_highest_dark
+ - @color/system_surface_container_low_dark
+ - @color/system_surface_container_lowest_dark
+ - @color/system_surface_dim_dark
+ - @color/system_surface_tint_dark
+ - @color/system_surface_variant_dark
- @color/system_tertiary_dark
- - @color/system_error_dark
-
- - @color/system_widget_background_dark
- - @color/system_clock_hour_dark
- - @color/system_clock_minute_dark
- - @color/system_clock_second_dark
- - @color/system_theme_app_dark
- - @color/system_on_theme_app_dark
- - @color/system_theme_app_ring_dark
- - @color/system_theme_notif_dark
+ - @color/system_tertiary_container_dark
+ - @color/system_text_hint_inverse_dark
+ - @color/system_text_primary_inverse_dark
+ - @color/system_text_primary_inverse_disable_only_dark
+ - @color/system_text_secondary_and_tertiary_inverse_dark
+ - @color/system_text_secondary_and_tertiary_inverse_disabled_dark
+ - @color/system_on_primary_fixed
+ - @color/system_on_primary_fixed_variant
+ - @color/system_on_secondary_fixed
+ - @color/system_on_secondary_fixed_variant
+ - @color/system_on_tertiary_fixed
+ - @color/system_on_tertiary_fixed_variant
+ - @color/system_primary_fixed
+ - @color/system_primary_fixed_dim
+ - @color/system_secondary_fixed
+ - @color/system_secondary_fixed_dim
+ - @color/system_tertiary_fixed
+ - @color/system_tertiary_fixed_dim
- @color/system_brand_a_dark
- @color/system_brand_b_dark
- @color/system_brand_c_dark
- @color/system_brand_d_dark
- - @color/system_under_surface_dark
- - @color/system_shade_active_dark
+ - @color/system_clock_hour_dark
+ - @color/system_clock_minute_dark
+ - @color/system_clock_second_dark
- @color/system_on_shade_active_dark
- @color/system_on_shade_active_variant_dark
- - @color/system_shade_inactive_dark
- @color/system_on_shade_inactive_dark
- @color/system_on_shade_inactive_variant_dark
- - @color/system_shade_disabled_dark
+ - @color/system_on_theme_app_dark
- @color/system_overview_background_dark
+ - @color/system_shade_active_dark
+ - @color/system_shade_disabled_dark
+ - @color/system_shade_inactive_dark
+ - @color/system_theme_app_dark
+ - @color/system_theme_app_ring_dark
+ - @color/system_theme_notif_dark
+ - @color/system_under_surface_dark
+ - @color/system_weather_temp_dark
+ - @color/system_widget_background_dark
@@ -1320,73 +1473,90 @@ easier.
- @style/Widget.DeviceDefault.Toolbar
- - @color/system_on_secondary_fixed_variant
- - @color/system_on_tertiary_fixed_variant
- - @color/system_surface_container_lowest_dark
- - @color/system_on_primary_fixed_variant
- - @color/system_on_secondary_container_dark
- - @color/system_on_tertiary_container_dark
- - @color/system_surface_container_low_dark
- - @color/system_on_primary_container_dark
- - @color/system_secondary_fixed_dim
- - @color/system_on_error_container_dark
- - @color/system_on_secondary_fixed
- - @color/system_on_surface_light
- - @color/system_tertiary_fixed_dim
- - @color/system_on_tertiary_fixed
- - @color/system_primary_fixed_dim
- - @color/system_secondary_container_dark
+ - @color/system_background_dark
+ - @color/system_control_activated_dark
+ - @color/system_control_highlight_dark
+ - @color/system_control_normal_dark
+ - @color/system_error_dark
- @color/system_error_container_dark
- - @color/system_on_primary_fixed
- - @color/system_primary_light
- - @color/system_secondary_fixed
- - @color/system_surface_light
- - @color/system_surface_variant_dark
- - @color/system_tertiary_container_dark
- - @color/system_tertiary_fixed
- - @color/system_primary_container_dark
+ - @color/system_inverse_on_surface_dark
+ - @color/system_inverse_primary_dark
+ - @color/system_inverse_surface_dark
- @color/system_on_background_dark
- - @color/system_primary_fixed
- - @color/system_on_secondary_dark
- - @color/system_on_tertiary_dark
- - @color/system_surface_dim_dark
- - @color/system_surface_bright_dark
- @color/system_on_error_dark
- - @color/system_surface_dark
- - @color/system_surface_container_high_dark
- - @color/system_surface_container_highest_dark
+ - @color/system_on_error_container_dark
+ - @color/system_on_primary_dark
+ - @color/system_on_primary_container_dark
+ - @color/system_on_secondary_dark
+ - @color/system_on_secondary_container_dark
+ - @color/system_on_surface_dark
- @color/system_on_surface_variant_dark
+ - @color/system_on_tertiary_dark
+ - @color/system_on_tertiary_container_dark
- @color/system_outline_dark
- @color/system_outline_variant_dark
- - @color/system_on_primary_dark
- - @color/system_on_surface_dark
- - @color/system_surface_container_dark
+ - @color/system_palette_key_color_neutral_dark
+ - @color/system_palette_key_color_neutral_variant_dark
+ - @color/system_palette_key_color_primary_dark
+ - @color/system_palette_key_color_secondary_dark
+ - @color/system_palette_key_color_tertiary_dark
- @color/system_primary_dark
+ - @color/system_primary_container_dark
+ - @color/system_scrim_dark
- @color/system_secondary_dark
+ - @color/system_secondary_container_dark
+ - @color/system_shadow_dark
+ - @color/system_surface_dark
+ - @color/system_surface_bright_dark
+ - @color/system_surface_container_dark
+ - @color/system_surface_container_high_dark
+ - @color/system_surface_container_highest_dark
+ - @color/system_surface_container_low_dark
+ - @color/system_surface_container_lowest_dark
+ - @color/system_surface_dim_dark
+ - @color/system_surface_tint_dark
+ - @color/system_surface_variant_dark
- @color/system_tertiary_dark
- - @color/system_error_dark
-
- - @color/system_widget_background_dark
- - @color/system_clock_hour_dark
- - @color/system_clock_minute_dark
- - @color/system_clock_second_dark
- - @color/system_theme_app_dark
- - @color/system_on_theme_app_dark
- - @color/system_theme_app_ring_dark
- - @color/system_theme_notif_dark
+ - @color/system_tertiary_container_dark
+ - @color/system_text_hint_inverse_dark
+ - @color/system_text_primary_inverse_dark
+ - @color/system_text_primary_inverse_disable_only_dark
+ - @color/system_text_secondary_and_tertiary_inverse_dark
+ - @color/system_text_secondary_and_tertiary_inverse_disabled_dark
+ - @color/system_on_primary_fixed
+ - @color/system_on_primary_fixed_variant
+ - @color/system_on_secondary_fixed
+ - @color/system_on_secondary_fixed_variant
+ - @color/system_on_tertiary_fixed
+ - @color/system_on_tertiary_fixed_variant
+ - @color/system_primary_fixed
+ - @color/system_primary_fixed_dim
+ - @color/system_secondary_fixed
+ - @color/system_secondary_fixed_dim
+ - @color/system_tertiary_fixed
+ - @color/system_tertiary_fixed_dim
- @color/system_brand_a_dark
- @color/system_brand_b_dark
- @color/system_brand_c_dark
- @color/system_brand_d_dark
- - @color/system_under_surface_dark
- - @color/system_shade_active_dark
+ - @color/system_clock_hour_dark
+ - @color/system_clock_minute_dark
+ - @color/system_clock_second_dark
- @color/system_on_shade_active_dark
- @color/system_on_shade_active_variant_dark
- - @color/system_shade_inactive_dark
- @color/system_on_shade_inactive_dark
- @color/system_on_shade_inactive_variant_dark
- - @color/system_shade_disabled_dark
+ - @color/system_on_theme_app_dark
- @color/system_overview_background_dark
+ - @color/system_shade_active_dark
+ - @color/system_shade_disabled_dark
+ - @color/system_shade_inactive_dark
+ - @color/system_theme_app_dark
+ - @color/system_theme_app_ring_dark
+ - @color/system_theme_notif_dark
+ - @color/system_under_surface_dark
+ - @color/system_weather_temp_dark
+ - @color/system_widget_background_dark
- @style/Widget.DeviceDefault.Toolbar
- - @color/system_on_secondary_fixed_variant
- - @color/system_on_tertiary_fixed_variant
- - @color/system_surface_container_lowest_dark
- - @color/system_on_primary_fixed_variant
- - @color/system_on_secondary_container_dark
- - @color/system_on_tertiary_container_dark
- - @color/system_surface_container_low_dark
- - @color/system_on_primary_container_dark
- - @color/system_secondary_fixed_dim
- - @color/system_on_error_container_dark
- - @color/system_on_secondary_fixed
- - @color/system_on_surface_light
- - @color/system_tertiary_fixed_dim
- - @color/system_on_tertiary_fixed
- - @color/system_primary_fixed_dim
- - @color/system_secondary_container_dark
+ - @color/system_background_dark
+ - @color/system_control_activated_dark
+ - @color/system_control_highlight_dark
+ - @color/system_control_normal_dark
+ - @color/system_error_dark
- @color/system_error_container_dark
- - @color/system_on_primary_fixed
- - @color/system_primary_light
- - @color/system_secondary_fixed
- - @color/system_surface_light
- - @color/system_surface_variant_dark
- - @color/system_tertiary_container_dark
- - @color/system_tertiary_fixed
- - @color/system_primary_container_dark
+ - @color/system_inverse_on_surface_dark
+ - @color/system_inverse_primary_dark
+ - @color/system_inverse_surface_dark
- @color/system_on_background_dark
- - @color/system_primary_fixed
- - @color/system_on_secondary_dark
- - @color/system_on_tertiary_dark
- - @color/system_surface_dim_dark
- - @color/system_surface_bright_dark
- @color/system_on_error_dark
- - @color/system_surface_dark
- - @color/system_surface_container_high_dark
- - @color/system_surface_container_highest_dark
+ - @color/system_on_error_container_dark
+ - @color/system_on_primary_dark
+ - @color/system_on_primary_container_dark
+ - @color/system_on_secondary_dark
+ - @color/system_on_secondary_container_dark
+ - @color/system_on_surface_dark
- @color/system_on_surface_variant_dark
+ - @color/system_on_tertiary_dark
+ - @color/system_on_tertiary_container_dark
- @color/system_outline_dark
- @color/system_outline_variant_dark
- - @color/system_on_primary_dark
- - @color/system_on_surface_dark
- - @color/system_surface_container_dark
+ - @color/system_palette_key_color_neutral_dark
+ - @color/system_palette_key_color_neutral_variant_dark
+ - @color/system_palette_key_color_primary_dark
+ - @color/system_palette_key_color_secondary_dark
+ - @color/system_palette_key_color_tertiary_dark
- @color/system_primary_dark
+ - @color/system_primary_container_dark
+ - @color/system_scrim_dark
- @color/system_secondary_dark
+ - @color/system_secondary_container_dark
+ - @color/system_shadow_dark
+ - @color/system_surface_dark
+ - @color/system_surface_bright_dark
+ - @color/system_surface_container_dark
+ - @color/system_surface_container_high_dark
+ - @color/system_surface_container_highest_dark
+ - @color/system_surface_container_low_dark
+ - @color/system_surface_container_lowest_dark
+ - @color/system_surface_dim_dark
+ - @color/system_surface_tint_dark
+ - @color/system_surface_variant_dark
- @color/system_tertiary_dark
- - @color/system_error_dark
-
- - @color/system_widget_background_dark
- - @color/system_clock_hour_dark
- - @color/system_clock_minute_dark
- - @color/system_clock_second_dark
- - @color/system_theme_app_dark
- - @color/system_on_theme_app_dark
- - @color/system_theme_app_ring_dark
- - @color/system_theme_notif_dark
+ - @color/system_tertiary_container_dark
+ - @color/system_text_hint_inverse_dark
+ - @color/system_text_primary_inverse_dark
+ - @color/system_text_primary_inverse_disable_only_dark
+ - @color/system_text_secondary_and_tertiary_inverse_dark
+ - @color/system_text_secondary_and_tertiary_inverse_disabled_dark
+ - @color/system_on_primary_fixed
+ - @color/system_on_primary_fixed_variant
+ - @color/system_on_secondary_fixed
+ - @color/system_on_secondary_fixed_variant
+ - @color/system_on_tertiary_fixed
+ - @color/system_on_tertiary_fixed_variant
+ - @color/system_primary_fixed
+ - @color/system_primary_fixed_dim
+ - @color/system_secondary_fixed
+ - @color/system_secondary_fixed_dim
+ - @color/system_tertiary_fixed
+ - @color/system_tertiary_fixed_dim
- @color/system_brand_a_dark
- @color/system_brand_b_dark
- @color/system_brand_c_dark
- @color/system_brand_d_dark
- - @color/system_under_surface_dark
- - @color/system_shade_active_dark
+ - @color/system_clock_hour_dark
+ - @color/system_clock_minute_dark
+ - @color/system_clock_second_dark
- @color/system_on_shade_active_dark
- @color/system_on_shade_active_variant_dark
- - @color/system_shade_inactive_dark
- @color/system_on_shade_inactive_dark
- @color/system_on_shade_inactive_variant_dark
- - @color/system_shade_disabled_dark
+ - @color/system_on_theme_app_dark
- @color/system_overview_background_dark
+ - @color/system_shade_active_dark
+ - @color/system_shade_disabled_dark
+ - @color/system_shade_inactive_dark
+ - @color/system_theme_app_dark
+ - @color/system_theme_app_ring_dark
+ - @color/system_theme_notif_dark
+ - @color/system_under_surface_dark
+ - @color/system_weather_temp_dark
+ - @color/system_widget_background_dark
@@ -1554,73 +1741,90 @@ easier.
- @style/Widget.DeviceDefault.Toolbar
- - @color/system_on_secondary_fixed_variant
- - @color/system_on_tertiary_fixed_variant
- - @color/system_surface_container_lowest_dark
- - @color/system_on_primary_fixed_variant
+ - @color/system_background_dark
+ - @color/system_control_activated_dark
+ - @color/system_control_highlight_dark
+ - @color/system_control_normal_dark
+ - @color/system_error_dark
+ - @color/system_error_container_dark
+ - @color/system_inverse_on_surface_dark
+ - @color/system_inverse_primary_dark
+ - @color/system_inverse_surface_dark
+ - @color/system_on_background_dark
+ - @color/system_on_error_dark
+ - @color/system_on_error_container_dark
+ - @color/system_on_primary_dark
+ - @color/system_on_primary_container_dark
+ - @color/system_on_secondary_dark
- @color/system_on_secondary_container_dark
+ - @color/system_on_surface_dark
+ - @color/system_on_surface_variant_dark
+ - @color/system_on_tertiary_dark
- @color/system_on_tertiary_container_dark
- - @color/system_surface_container_low_dark
- - @color/system_on_primary_container_dark
- - @color/system_secondary_fixed_dim
- - @color/system_on_error_container_dark
- - @color/system_on_secondary_fixed
- - @color/system_on_surface_light
- - @color/system_tertiary_fixed_dim
- - @color/system_on_tertiary_fixed
- - @color/system_primary_fixed_dim
- - @color/system_secondary_container_dark
- - @color/system_error_container_dark
- - @color/system_on_primary_fixed
- - @color/system_primary_light
- - @color/system_secondary_fixed
- - @color/system_surface_light
- - @color/system_surface_variant_dark
- - @color/system_tertiary_container_dark
- - @color/system_tertiary_fixed
- - @color/system_primary_container_dark
- - @color/system_on_background_dark
- - @color/system_primary_fixed
- - @color/system_on_secondary_dark
- - @color/system_on_tertiary_dark
- - @color/system_surface_dim_dark
- - @color/system_surface_bright_dark
- - @color/system_on_error_dark
- - @color/system_surface_dark
- - @color/system_surface_container_high_dark
- - @color/system_surface_container_highest_dark
- - @color/system_on_surface_variant_dark
- @color/system_outline_dark
- @color/system_outline_variant_dark
- - @color/system_on_primary_dark
- - @color/system_on_surface_dark
- - @color/system_surface_container_dark
+ - @color/system_palette_key_color_neutral_dark
+ - @color/system_palette_key_color_neutral_variant_dark
+ - @color/system_palette_key_color_primary_dark
+ - @color/system_palette_key_color_secondary_dark
+ - @color/system_palette_key_color_tertiary_dark
- @color/system_primary_dark
+ - @color/system_primary_container_dark
+ - @color/system_scrim_dark
- @color/system_secondary_dark
+ - @color/system_secondary_container_dark
+ - @color/system_shadow_dark
+ - @color/system_surface_dark
+ - @color/system_surface_bright_dark
+ - @color/system_surface_container_dark
+ - @color/system_surface_container_high_dark
+ - @color/system_surface_container_highest_dark
+ - @color/system_surface_container_low_dark
+ - @color/system_surface_container_lowest_dark
+ - @color/system_surface_dim_dark
+ - @color/system_surface_tint_dark
+ - @color/system_surface_variant_dark
- @color/system_tertiary_dark
- - @color/system_error_dark
-
- - @color/system_widget_background_dark
- - @color/system_clock_hour_dark
- - @color/system_clock_minute_dark
- - @color/system_clock_second_dark
- - @color/system_theme_app_dark
- - @color/system_on_theme_app_dark
- - @color/system_theme_app_ring_dark
- - @color/system_theme_notif_dark
+ - @color/system_tertiary_container_dark
+ - @color/system_text_hint_inverse_dark
+ - @color/system_text_primary_inverse_dark
+ - @color/system_text_primary_inverse_disable_only_dark
+ - @color/system_text_secondary_and_tertiary_inverse_dark
+ - @color/system_text_secondary_and_tertiary_inverse_disabled_dark
+ - @color/system_on_primary_fixed
+ - @color/system_on_primary_fixed_variant
+ - @color/system_on_secondary_fixed
+ - @color/system_on_secondary_fixed_variant
+ - @color/system_on_tertiary_fixed
+ - @color/system_on_tertiary_fixed_variant
+ - @color/system_primary_fixed
+ - @color/system_primary_fixed_dim
+ - @color/system_secondary_fixed
+ - @color/system_secondary_fixed_dim
+ - @color/system_tertiary_fixed
+ - @color/system_tertiary_fixed_dim
- @color/system_brand_a_dark
- @color/system_brand_b_dark
- @color/system_brand_c_dark
- @color/system_brand_d_dark
- - @color/system_under_surface_dark
- - @color/system_shade_active_dark
+ - @color/system_clock_hour_dark
+ - @color/system_clock_minute_dark
+ - @color/system_clock_second_dark
- @color/system_on_shade_active_dark
- @color/system_on_shade_active_variant_dark
- - @color/system_shade_inactive_dark
- @color/system_on_shade_inactive_dark
- @color/system_on_shade_inactive_variant_dark
- - @color/system_shade_disabled_dark
+ - @color/system_on_theme_app_dark
- @color/system_overview_background_dark
+ - @color/system_shade_active_dark
+ - @color/system_shade_disabled_dark
+ - @color/system_shade_inactive_dark
+ - @color/system_theme_app_dark
+ - @color/system_theme_app_ring_dark
+ - @color/system_theme_notif_dark
+ - @color/system_under_surface_dark
+ - @color/system_weather_temp_dark
+ - @color/system_widget_background_dark
- @style/Widget.DeviceDefault.Toolbar
- - @color/system_on_secondary_fixed_variant
- - @color/system_on_tertiary_fixed_variant
- - @color/system_surface_container_lowest_dark
- - @color/system_on_primary_fixed_variant
- - @color/system_on_secondary_container_dark
- - @color/system_on_tertiary_container_dark
- - @color/system_surface_container_low_dark
- - @color/system_on_primary_container_dark
- - @color/system_secondary_fixed_dim
- - @color/system_on_error_container_dark
- - @color/system_on_secondary_fixed
- - @color/system_on_surface_light
- - @color/system_tertiary_fixed_dim
- - @color/system_on_tertiary_fixed
- - @color/system_primary_fixed_dim
- - @color/system_secondary_container_dark
+ - @color/system_background_dark
+ - @color/system_control_activated_dark
+ - @color/system_control_highlight_dark
+ - @color/system_control_normal_dark
+ - @color/system_error_dark
- @color/system_error_container_dark
- - @color/system_on_primary_fixed
- - @color/system_primary_light
- - @color/system_secondary_fixed
- - @color/system_surface_light
- - @color/system_surface_variant_dark
- - @color/system_tertiary_container_dark
- - @color/system_tertiary_fixed
- - @color/system_primary_container_dark
+ - @color/system_inverse_on_surface_dark
+ - @color/system_inverse_primary_dark
+ - @color/system_inverse_surface_dark
- @color/system_on_background_dark
- - @color/system_primary_fixed
- - @color/system_on_secondary_dark
- - @color/system_on_tertiary_dark
- - @color/system_surface_dim_dark
- - @color/system_surface_bright_dark
- @color/system_on_error_dark
- - @color/system_surface_dark
- - @color/system_surface_container_high_dark
- - @color/system_surface_container_highest_dark
+ - @color/system_on_error_container_dark
+ - @color/system_on_primary_dark
+ - @color/system_on_primary_container_dark
+ - @color/system_on_secondary_dark
+ - @color/system_on_secondary_container_dark
+ - @color/system_on_surface_dark
- @color/system_on_surface_variant_dark
+ - @color/system_on_tertiary_dark
+ - @color/system_on_tertiary_container_dark
- @color/system_outline_dark
- @color/system_outline_variant_dark
- - @color/system_on_primary_dark
- - @color/system_on_surface_dark
- - @color/system_surface_container_dark
+ - @color/system_palette_key_color_neutral_dark
+ - @color/system_palette_key_color_neutral_variant_dark
+ - @color/system_palette_key_color_primary_dark
+ - @color/system_palette_key_color_secondary_dark
+ - @color/system_palette_key_color_tertiary_dark
- @color/system_primary_dark
+ - @color/system_primary_container_dark
+ - @color/system_scrim_dark
- @color/system_secondary_dark
+ - @color/system_secondary_container_dark
+ - @color/system_shadow_dark
+ - @color/system_surface_dark
+ - @color/system_surface_bright_dark
+ - @color/system_surface_container_dark
+ - @color/system_surface_container_high_dark
+ - @color/system_surface_container_highest_dark
+ - @color/system_surface_container_low_dark
+ - @color/system_surface_container_lowest_dark
+ - @color/system_surface_dim_dark
+ - @color/system_surface_tint_dark
+ - @color/system_surface_variant_dark
- @color/system_tertiary_dark
- - @color/system_error_dark
-
- - @color/system_widget_background_dark
- - @color/system_clock_hour_dark
- - @color/system_clock_minute_dark
- - @color/system_clock_second_dark
- - @color/system_theme_app_dark
- - @color/system_on_theme_app_dark
- - @color/system_theme_app_ring_dark
- - @color/system_theme_notif_dark
+ - @color/system_tertiary_container_dark
+ - @color/system_text_hint_inverse_dark
+ - @color/system_text_primary_inverse_dark
+ - @color/system_text_primary_inverse_disable_only_dark
+ - @color/system_text_secondary_and_tertiary_inverse_dark
+ - @color/system_text_secondary_and_tertiary_inverse_disabled_dark
+ - @color/system_on_primary_fixed
+ - @color/system_on_primary_fixed_variant
+ - @color/system_on_secondary_fixed
+ - @color/system_on_secondary_fixed_variant
+ - @color/system_on_tertiary_fixed
+ - @color/system_on_tertiary_fixed_variant
+ - @color/system_primary_fixed
+ - @color/system_primary_fixed_dim
+ - @color/system_secondary_fixed
+ - @color/system_secondary_fixed_dim
+ - @color/system_tertiary_fixed
+ - @color/system_tertiary_fixed_dim
- @color/system_brand_a_dark
- @color/system_brand_b_dark
- @color/system_brand_c_dark
- @color/system_brand_d_dark
- - @color/system_under_surface_dark
- - @color/system_shade_active_dark
+ - @color/system_clock_hour_dark
+ - @color/system_clock_minute_dark
+ - @color/system_clock_second_dark
- @color/system_on_shade_active_dark
- @color/system_on_shade_active_variant_dark
- - @color/system_shade_inactive_dark
- @color/system_on_shade_inactive_dark
- @color/system_on_shade_inactive_variant_dark
- - @color/system_shade_disabled_dark
+ - @color/system_on_theme_app_dark
- @color/system_overview_background_dark
+ - @color/system_shade_active_dark
+ - @color/system_shade_disabled_dark
+ - @color/system_shade_inactive_dark
+ - @color/system_theme_app_dark
+ - @color/system_theme_app_ring_dark
+ - @color/system_theme_notif_dark
+ - @color/system_under_surface_dark
+ - @color/system_weather_temp_dark
+ - @color/system_widget_background_dark
- @style/Widget.DeviceDefault.Toolbar
- - @color/system_on_secondary_fixed_variant
- - @color/system_on_tertiary_fixed_variant
- - @color/system_surface_container_lowest_dark
- - @color/system_on_primary_fixed_variant
- - @color/system_on_secondary_container_dark
- - @color/system_on_tertiary_container_dark
- - @color/system_surface_container_low_dark
- - @color/system_on_primary_container_dark
- - @color/system_secondary_fixed_dim
- - @color/system_on_error_container_dark
- - @color/system_on_secondary_fixed
- - @color/system_on_surface_light
- - @color/system_tertiary_fixed_dim
- - @color/system_on_tertiary_fixed
- - @color/system_primary_fixed_dim
- - @color/system_secondary_container_dark
+ - @color/system_background_dark
+ - @color/system_control_activated_dark
+ - @color/system_control_highlight_dark
+ - @color/system_control_normal_dark
+ - @color/system_error_dark
- @color/system_error_container_dark
- - @color/system_on_primary_fixed
- - @color/system_primary_light
- - @color/system_secondary_fixed
- - @color/system_surface_light
- - @color/system_surface_variant_dark
- - @color/system_tertiary_container_dark
- - @color/system_tertiary_fixed
- - @color/system_primary_container_dark
+ - @color/system_inverse_on_surface_dark
+ - @color/system_inverse_primary_dark
+ - @color/system_inverse_surface_dark
- @color/system_on_background_dark
- - @color/system_primary_fixed
- - @color/system_on_secondary_dark
- - @color/system_on_tertiary_dark
- - @color/system_surface_dim_dark
- - @color/system_surface_bright_dark
- @color/system_on_error_dark
- - @color/system_surface_dark
- - @color/system_surface_container_high_dark
- - @color/system_surface_container_highest_dark
+ - @color/system_on_error_container_dark
+ - @color/system_on_primary_dark
+ - @color/system_on_primary_container_dark
+ - @color/system_on_secondary_dark
+ - @color/system_on_secondary_container_dark
+ - @color/system_on_surface_dark
- @color/system_on_surface_variant_dark
+ - @color/system_on_tertiary_dark
+ - @color/system_on_tertiary_container_dark
- @color/system_outline_dark
- @color/system_outline_variant_dark
- - @color/system_on_primary_dark
- - @color/system_on_surface_dark
- - @color/system_surface_container_dark
+ - @color/system_palette_key_color_neutral_dark
+ - @color/system_palette_key_color_neutral_variant_dark
+ - @color/system_palette_key_color_primary_dark
+ - @color/system_palette_key_color_secondary_dark
+ - @color/system_palette_key_color_tertiary_dark
- @color/system_primary_dark
+ - @color/system_primary_container_dark
+ - @color/system_scrim_dark
- @color/system_secondary_dark
+ - @color/system_secondary_container_dark
+ - @color/system_shadow_dark
+ - @color/system_surface_dark
+ - @color/system_surface_bright_dark
+ - @color/system_surface_container_dark
+ - @color/system_surface_container_high_dark
+ - @color/system_surface_container_highest_dark
+ - @color/system_surface_container_low_dark
+ - @color/system_surface_container_lowest_dark
+ - @color/system_surface_dim_dark
+ - @color/system_surface_tint_dark
+ - @color/system_surface_variant_dark
- @color/system_tertiary_dark
- - @color/system_error_dark
-
- - @color/system_widget_background_dark
- - @color/system_clock_hour_dark
- - @color/system_clock_minute_dark
- - @color/system_clock_second_dark
- - @color/system_theme_app_dark
- - @color/system_on_theme_app_dark
- - @color/system_theme_app_ring_dark
- - @color/system_theme_notif_dark
+ - @color/system_tertiary_container_dark
+ - @color/system_text_hint_inverse_dark
+ - @color/system_text_primary_inverse_dark
+ - @color/system_text_primary_inverse_disable_only_dark
+ - @color/system_text_secondary_and_tertiary_inverse_dark
+ - @color/system_text_secondary_and_tertiary_inverse_disabled_dark
+ - @color/system_on_primary_fixed
+ - @color/system_on_primary_fixed_variant
+ - @color/system_on_secondary_fixed
+ - @color/system_on_secondary_fixed_variant
+ - @color/system_on_tertiary_fixed
+ - @color/system_on_tertiary_fixed_variant
+ - @color/system_primary_fixed
+ - @color/system_primary_fixed_dim
+ - @color/system_secondary_fixed
+ - @color/system_secondary_fixed_dim
+ - @color/system_tertiary_fixed
+ - @color/system_tertiary_fixed_dim
- @color/system_brand_a_dark
- @color/system_brand_b_dark
- @color/system_brand_c_dark
- @color/system_brand_d_dark
- - @color/system_under_surface_dark
- - @color/system_shade_active_dark
+ - @color/system_clock_hour_dark
+ - @color/system_clock_minute_dark
+ - @color/system_clock_second_dark
- @color/system_on_shade_active_dark
- @color/system_on_shade_active_variant_dark
- - @color/system_shade_inactive_dark
- @color/system_on_shade_inactive_dark
- @color/system_on_shade_inactive_variant_dark
- - @color/system_shade_disabled_dark
+ - @color/system_on_theme_app_dark
- @color/system_overview_background_dark
+ - @color/system_shade_active_dark
+ - @color/system_shade_disabled_dark
+ - @color/system_shade_inactive_dark
+ - @color/system_theme_app_dark
+ - @color/system_theme_app_ring_dark
+ - @color/system_theme_notif_dark
+ - @color/system_under_surface_dark
+ - @color/system_weather_temp_dark
+ - @color/system_widget_background_dark
- @style/Widget.DeviceDefault.Toolbar
- - @color/system_on_secondary_fixed_variant
- - @color/system_on_tertiary_fixed_variant
- - @color/system_surface_container_lowest_dark
- - @color/system_on_primary_fixed_variant
- - @color/system_on_secondary_container_dark
- - @color/system_on_tertiary_container_dark
- - @color/system_surface_container_low_dark
- - @color/system_on_primary_container_dark
- - @color/system_secondary_fixed_dim
- - @color/system_on_error_container_dark
- - @color/system_on_secondary_fixed
- - @color/system_on_surface_light
- - @color/system_tertiary_fixed_dim
- - @color/system_on_tertiary_fixed
- - @color/system_primary_fixed_dim
- - @color/system_secondary_container_dark
+ - @color/system_background_dark
+ - @color/system_control_activated_dark
+ - @color/system_control_highlight_dark
+ - @color/system_control_normal_dark
+ - @color/system_error_dark
- @color/system_error_container_dark
- - @color/system_on_primary_fixed
- - @color/system_primary_light
- - @color/system_secondary_fixed
- - @color/system_surface_light
- - @color/system_surface_variant_dark
- - @color/system_tertiary_container_dark
- - @color/system_tertiary_fixed
- - @color/system_primary_container_dark
+ - @color/system_inverse_on_surface_dark
+ - @color/system_inverse_primary_dark
+ - @color/system_inverse_surface_dark
- @color/system_on_background_dark
- - @color/system_primary_fixed
- - @color/system_on_secondary_dark
- - @color/system_on_tertiary_dark
- - @color/system_surface_dim_dark
- - @color/system_surface_bright_dark
- @color/system_on_error_dark
- - @color/system_surface_dark
- - @color/system_surface_container_high_dark
- - @color/system_surface_container_highest_dark
+ - @color/system_on_error_container_dark
+ - @color/system_on_primary_dark
+ - @color/system_on_primary_container_dark
+ - @color/system_on_secondary_dark
+ - @color/system_on_secondary_container_dark
+ - @color/system_on_surface_dark
- @color/system_on_surface_variant_dark
+ - @color/system_on_tertiary_dark
+ - @color/system_on_tertiary_container_dark
- @color/system_outline_dark
- @color/system_outline_variant_dark
- - @color/system_on_primary_dark
- - @color/system_on_surface_dark
- - @color/system_surface_container_dark
+ - @color/system_palette_key_color_neutral_dark
+ - @color/system_palette_key_color_neutral_variant_dark
+ - @color/system_palette_key_color_primary_dark
+ - @color/system_palette_key_color_secondary_dark
+ - @color/system_palette_key_color_tertiary_dark
- @color/system_primary_dark
+ - @color/system_primary_container_dark
+ - @color/system_scrim_dark
- @color/system_secondary_dark
+ - @color/system_secondary_container_dark
+ - @color/system_shadow_dark
+ - @color/system_surface_dark
+ - @color/system_surface_bright_dark
+ - @color/system_surface_container_dark
+ - @color/system_surface_container_high_dark
+ - @color/system_surface_container_highest_dark
+ - @color/system_surface_container_low_dark
+ - @color/system_surface_container_lowest_dark
+ - @color/system_surface_dim_dark
+ - @color/system_surface_tint_dark
+ - @color/system_surface_variant_dark
- @color/system_tertiary_dark
- - @color/system_error_dark
-
- - @color/system_widget_background_dark
- - @color/system_clock_hour_dark
- - @color/system_clock_minute_dark
- - @color/system_clock_second_dark
- - @color/system_theme_app_dark
- - @color/system_on_theme_app_dark
- - @color/system_theme_app_ring_dark
- - @color/system_theme_notif_dark
+ - @color/system_tertiary_container_dark
+ - @color/system_text_hint_inverse_dark
+ - @color/system_text_primary_inverse_dark
+ - @color/system_text_primary_inverse_disable_only_dark
+ - @color/system_text_secondary_and_tertiary_inverse_dark
+ - @color/system_text_secondary_and_tertiary_inverse_disabled_dark
+ - @color/system_on_primary_fixed
+ - @color/system_on_primary_fixed_variant
+ - @color/system_on_secondary_fixed
+ - @color/system_on_secondary_fixed_variant
+ - @color/system_on_tertiary_fixed
+ - @color/system_on_tertiary_fixed_variant
+ - @color/system_primary_fixed
+ - @color/system_primary_fixed_dim
+ - @color/system_secondary_fixed
+ - @color/system_secondary_fixed_dim
+ - @color/system_tertiary_fixed
+ - @color/system_tertiary_fixed_dim
- @color/system_brand_a_dark
- @color/system_brand_b_dark
- @color/system_brand_c_dark
- @color/system_brand_d_dark
- - @color/system_under_surface_dark
- - @color/system_shade_active_dark
+ - @color/system_clock_hour_dark
+ - @color/system_clock_minute_dark
+ - @color/system_clock_second_dark
- @color/system_on_shade_active_dark
- @color/system_on_shade_active_variant_dark
- - @color/system_shade_inactive_dark
- @color/system_on_shade_inactive_dark
- @color/system_on_shade_inactive_variant_dark
- - @color/system_shade_disabled_dark
+ - @color/system_on_theme_app_dark
- @color/system_overview_background_dark
+ - @color/system_shade_active_dark
+ - @color/system_shade_disabled_dark
+ - @color/system_shade_inactive_dark
+ - @color/system_theme_app_dark
+ - @color/system_theme_app_ring_dark
+ - @color/system_theme_notif_dark
+ - @color/system_under_surface_dark
+ - @color/system_weather_temp_dark
+ - @color/system_widget_background_dark
- @style/Widget.DeviceDefault.Toolbar
- - @color/system_on_secondary_fixed_variant
- - @color/system_on_tertiary_fixed_variant
- - @color/system_surface_container_lowest_light
- - @color/system_on_primary_fixed_variant
- - @color/system_on_secondary_container_light
- - @color/system_on_tertiary_container_light
- - @color/system_surface_container_low_light
- - @color/system_on_primary_container_light
- - @color/system_secondary_fixed_dim
- - @color/system_on_error_container_light
- - @color/system_on_secondary_fixed
- - @color/system_on_surface_dark
- - @color/system_tertiary_fixed_dim
- - @color/system_on_tertiary_fixed
- - @color/system_primary_fixed_dim
- - @color/system_secondary_container_light
+ - @color/system_background_light
+ - @color/system_control_activated_light
+ - @color/system_control_highlight_light
+ - @color/system_control_normal_light
+ - @color/system_error_light
- @color/system_error_container_light
- - @color/system_on_primary_fixed
- - @color/system_primary_dark
- - @color/system_secondary_fixed
- - @color/system_surface_dark
- - @color/system_surface_variant_light
- - @color/system_tertiary_container_light
- - @color/system_tertiary_fixed
- - @color/system_primary_container_light
+ - @color/system_inverse_on_surface_light
+ - @color/system_inverse_primary_light
+ - @color/system_inverse_surface_light
- @color/system_on_background_light
- - @color/system_primary_fixed
- - @color/system_on_secondary_light
- - @color/system_on_tertiary_light
- - @color/system_surface_dim_light
- - @color/system_surface_bright_light
- @color/system_on_error_light
- - @color/system_surface_light
- - @color/system_surface_container_high_light
- - @color/system_surface_container_highest_light
+ - @color/system_on_error_container_light
+ - @color/system_on_primary_light
+ - @color/system_on_primary_container_light
+ - @color/system_on_secondary_light
+ - @color/system_on_secondary_container_light
+ - @color/system_on_surface_light
- @color/system_on_surface_variant_light
+ - @color/system_on_tertiary_light
+ - @color/system_on_tertiary_container_light
- @color/system_outline_light
- @color/system_outline_variant_light
- - @color/system_on_primary_light
- - @color/system_on_surface_light
- - @color/system_surface_container_light
+ - @color/system_palette_key_color_neutral_light
+ - @color/system_palette_key_color_neutral_variant_light
+ - @color/system_palette_key_color_primary_light
+ - @color/system_palette_key_color_secondary_light
+ - @color/system_palette_key_color_tertiary_light
- @color/system_primary_light
+ - @color/system_primary_container_light
+ - @color/system_scrim_light
- @color/system_secondary_light
+ - @color/system_secondary_container_light
+ - @color/system_shadow_light
+ - @color/system_surface_light
+ - @color/system_surface_bright_light
+ - @color/system_surface_container_light
+ - @color/system_surface_container_high_light
+ - @color/system_surface_container_highest_light
+ - @color/system_surface_container_low_light
+ - @color/system_surface_container_lowest_light
+ - @color/system_surface_dim_light
+ - @color/system_surface_tint_light
+ - @color/system_surface_variant_light
- @color/system_tertiary_light
- - @color/system_error_light
-
- - @color/system_widget_background_light
- - @color/system_clock_hour_light
- - @color/system_clock_minute_light
- - @color/system_clock_second_light
- - @color/system_theme_app_light
- - @color/system_on_theme_app_light
- - @color/system_theme_app_ring_light
- - @color/system_theme_notif_light
+ - @color/system_tertiary_container_light
+ - @color/system_text_hint_inverse_light
+ - @color/system_text_primary_inverse_light
+ - @color/system_text_primary_inverse_disable_only_light
+ - @color/system_text_secondary_and_tertiary_inverse_light
+ - @color/system_text_secondary_and_tertiary_inverse_disabled_light
+ - @color/system_on_primary_fixed
+ - @color/system_on_primary_fixed_variant
+ - @color/system_on_secondary_fixed
+ - @color/system_on_secondary_fixed_variant
+ - @color/system_on_tertiary_fixed
+ - @color/system_on_tertiary_fixed_variant
+ - @color/system_primary_fixed
+ - @color/system_primary_fixed_dim
+ - @color/system_secondary_fixed
+ - @color/system_secondary_fixed_dim
+ - @color/system_tertiary_fixed
+ - @color/system_tertiary_fixed_dim
- @color/system_brand_a_light
- @color/system_brand_b_light
- @color/system_brand_c_light
- @color/system_brand_d_light
- - @color/system_under_surface_light
- - @color/system_shade_active_light
+ - @color/system_clock_hour_light
+ - @color/system_clock_minute_light
+ - @color/system_clock_second_light
- @color/system_on_shade_active_light
- @color/system_on_shade_active_variant_light
- - @color/system_shade_inactive_light
- @color/system_on_shade_inactive_light
- @color/system_on_shade_inactive_variant_light
- - @color/system_shade_disabled_light
+ - @color/system_on_theme_app_light
- @color/system_overview_background_light
+ - @color/system_shade_active_light
+ - @color/system_shade_disabled_light
+ - @color/system_shade_inactive_light
+ - @color/system_theme_app_light
+ - @color/system_theme_app_ring_light
+ - @color/system_theme_notif_light
+ - @color/system_under_surface_light
+ - @color/system_weather_temp_light
+ - @color/system_widget_background_light
- @style/Widget.DeviceDefault.Toolbar
- - @color/system_on_secondary_fixed_variant
- - @color/system_on_tertiary_fixed_variant
- - @color/system_surface_container_lowest_light
- - @color/system_on_primary_fixed_variant
- - @color/system_on_secondary_container_light
- - @color/system_on_tertiary_container_light
- - @color/system_surface_container_low_light
- - @color/system_on_primary_container_light
- - @color/system_secondary_fixed_dim
- - @color/system_on_error_container_light
- - @color/system_on_secondary_fixed
- - @color/system_on_surface_dark
- - @color/system_tertiary_fixed_dim
- - @color/system_on_tertiary_fixed
- - @color/system_primary_fixed_dim
- - @color/system_secondary_container_light
+ - @color/system_background_light
+ - @color/system_control_activated_light
+ - @color/system_control_highlight_light
+ - @color/system_control_normal_light
+ - @color/system_error_light
- @color/system_error_container_light
- - @color/system_on_primary_fixed
- - @color/system_primary_dark
- - @color/system_secondary_fixed
- - @color/system_surface_dark
- - @color/system_surface_variant_light
- - @color/system_tertiary_container_light
- - @color/system_tertiary_fixed
- - @color/system_primary_container_light
+ - @color/system_inverse_on_surface_light
+ - @color/system_inverse_primary_light
+ - @color/system_inverse_surface_light
- @color/system_on_background_light
- - @color/system_primary_fixed
- - @color/system_on_secondary_light
- - @color/system_on_tertiary_light
- - @color/system_surface_dim_light
- - @color/system_surface_bright_light
- @color/system_on_error_light
- - @color/system_surface_light
- - @color/system_surface_container_high_light
- - @color/system_surface_container_highest_light
+ - @color/system_on_error_container_light
+ - @color/system_on_primary_light
+ - @color/system_on_primary_container_light
+ - @color/system_on_secondary_light
+ - @color/system_on_secondary_container_light
+ - @color/system_on_surface_light
- @color/system_on_surface_variant_light
+ - @color/system_on_tertiary_light
+ - @color/system_on_tertiary_container_light
- @color/system_outline_light
- @color/system_outline_variant_light
- - @color/system_on_primary_light
- - @color/system_on_surface_light
- - @color/system_surface_container_light
+ - @color/system_palette_key_color_neutral_light
+ - @color/system_palette_key_color_neutral_variant_light
+ - @color/system_palette_key_color_primary_light
+ - @color/system_palette_key_color_secondary_light
+ - @color/system_palette_key_color_tertiary_light
- @color/system_primary_light
+ - @color/system_primary_container_light
+ - @color/system_scrim_light
- @color/system_secondary_light
+ - @color/system_secondary_container_light
+ - @color/system_shadow_light
+ - @color/system_surface_light
+ - @color/system_surface_bright_light
+ - @color/system_surface_container_light
+ - @color/system_surface_container_high_light
+ - @color/system_surface_container_highest_light
+ - @color/system_surface_container_low_light
+ - @color/system_surface_container_lowest_light
+ - @color/system_surface_dim_light
+ - @color/system_surface_tint_light
+ - @color/system_surface_variant_light
- @color/system_tertiary_light
- - @color/system_error_light
-
- - @color/system_widget_background_light
+ - @color/system_tertiary_container_light
+ - @color/system_text_hint_inverse_light
+ - @color/system_text_primary_inverse_light
+ - @color/system_text_primary_inverse_disable_only_light
+ - @color/system_text_secondary_and_tertiary_inverse_light
+ - @color/system_text_secondary_and_tertiary_inverse_disabled_light
+ - @color/system_on_primary_fixed
+ - @color/system_on_primary_fixed_variant
+ - @color/system_on_secondary_fixed
+ - @color/system_on_secondary_fixed_variant
+ - @color/system_on_tertiary_fixed
+ - @color/system_on_tertiary_fixed_variant
+ - @color/system_primary_fixed
+ - @color/system_primary_fixed_dim
+ - @color/system_secondary_fixed
+ - @color/system_secondary_fixed_dim
+ - @color/system_tertiary_fixed
+ - @color/system_tertiary_fixed_dim
+ - @color/system_brand_a_light
+ - @color/system_brand_b_light
+ - @color/system_brand_c_light
+ - @color/system_brand_d_light
- @color/system_clock_hour_light
- @color/system_clock_minute_light
- @color/system_clock_second_light
- - @color/system_theme_app_light
- - @color/system_on_theme_app_light
- - @color/system_theme_app_ring_light
- - @color/system_theme_notif_light
- - @color/system_brand_a_light
- - @color/system_brand_b_light
- - @color/system_brand_c_light
- - @color/system_brand_d_light
- - @color/system_under_surface_light
- - @color/system_shade_active_light
- @color/system_on_shade_active_light
- @color/system_on_shade_active_variant_light
- - @color/system_shade_inactive_light
- @color/system_on_shade_inactive_light
- @color/system_on_shade_inactive_variant_light
- - @color/system_shade_disabled_light
+ - @color/system_on_theme_app_light
- @color/system_overview_background_light
+ - @color/system_shade_active_light
+ - @color/system_shade_disabled_light
+ - @color/system_shade_inactive_light
+ - @color/system_theme_app_light
+ - @color/system_theme_app_ring_light
+ - @color/system_theme_notif_light
+ - @color/system_under_surface_light
+ - @color/system_weather_temp_light
+ - @color/system_widget_background_light
@@ -2379,73 +2685,90 @@ easier.
- @style/Widget.DeviceDefault.Toolbar
- - @color/system_on_secondary_fixed_variant
- - @color/system_on_tertiary_fixed_variant
- - @color/system_surface_container_lowest_dark
- - @color/system_on_primary_fixed_variant
- - @color/system_on_secondary_container_dark
- - @color/system_on_tertiary_container_dark
- - @color/system_surface_container_low_dark
- - @color/system_on_primary_container_dark
- - @color/system_secondary_fixed_dim
- - @color/system_on_error_container_dark
- - @color/system_on_secondary_fixed
- - @color/system_on_surface_light
- - @color/system_tertiary_fixed_dim
- - @color/system_on_tertiary_fixed
- - @color/system_primary_fixed_dim
- - @color/system_secondary_container_dark
+ - @color/system_background_dark
+ - @color/system_control_activated_dark
+ - @color/system_control_highlight_dark
+ - @color/system_control_normal_dark
+ - @color/system_error_dark
- @color/system_error_container_dark
- - @color/system_on_primary_fixed
- - @color/system_primary_light
- - @color/system_secondary_fixed
- - @color/system_surface_light
- - @color/system_surface_variant_dark
- - @color/system_tertiary_container_dark
- - @color/system_tertiary_fixed
- - @color/system_primary_container_dark
+ - @color/system_inverse_on_surface_dark
+ - @color/system_inverse_primary_dark
+ - @color/system_inverse_surface_dark
- @color/system_on_background_dark
- - @color/system_primary_fixed
- - @color/system_on_secondary_dark
- - @color/system_on_tertiary_dark
- - @color/system_surface_dim_dark
- - @color/system_surface_bright_dark
- @color/system_on_error_dark
- - @color/system_surface_dark
- - @color/system_surface_container_high_dark
- - @color/system_surface_container_highest_dark
+ - @color/system_on_error_container_dark
+ - @color/system_on_primary_dark
+ - @color/system_on_primary_container_dark
+ - @color/system_on_secondary_dark
+ - @color/system_on_secondary_container_dark
+ - @color/system_on_surface_dark
- @color/system_on_surface_variant_dark
+ - @color/system_on_tertiary_dark
+ - @color/system_on_tertiary_container_dark
- @color/system_outline_dark
- @color/system_outline_variant_dark
- - @color/system_on_primary_dark
- - @color/system_on_surface_dark
- - @color/system_surface_container_dark
+ - @color/system_palette_key_color_neutral_dark
+ - @color/system_palette_key_color_neutral_variant_dark
+ - @color/system_palette_key_color_primary_dark
+ - @color/system_palette_key_color_secondary_dark
+ - @color/system_palette_key_color_tertiary_dark
- @color/system_primary_dark
+ - @color/system_primary_container_dark
+ - @color/system_scrim_dark
- @color/system_secondary_dark
+ - @color/system_secondary_container_dark
+ - @color/system_shadow_dark
+ - @color/system_surface_dark
+ - @color/system_surface_bright_dark
+ - @color/system_surface_container_dark
+ - @color/system_surface_container_high_dark
+ - @color/system_surface_container_highest_dark
+ - @color/system_surface_container_low_dark
+ - @color/system_surface_container_lowest_dark
+ - @color/system_surface_dim_dark
+ - @color/system_surface_tint_dark
+ - @color/system_surface_variant_dark
- @color/system_tertiary_dark
- - @color/system_error_dark
-
- - @color/system_widget_background_dark
- - @color/system_clock_hour_dark
- - @color/system_clock_minute_dark
- - @color/system_clock_second_dark
- - @color/system_theme_app_dark
- - @color/system_on_theme_app_dark
- - @color/system_theme_app_ring_dark
- - @color/system_theme_notif_dark
+ - @color/system_tertiary_container_dark
+ - @color/system_text_hint_inverse_dark
+ - @color/system_text_primary_inverse_dark
+ - @color/system_text_primary_inverse_disable_only_dark
+ - @color/system_text_secondary_and_tertiary_inverse_dark
+ - @color/system_text_secondary_and_tertiary_inverse_disabled_dark
+ - @color/system_on_primary_fixed
+ - @color/system_on_primary_fixed_variant
+ - @color/system_on_secondary_fixed
+ - @color/system_on_secondary_fixed_variant
+ - @color/system_on_tertiary_fixed
+ - @color/system_on_tertiary_fixed_variant
+ - @color/system_primary_fixed
+ - @color/system_primary_fixed_dim
+ - @color/system_secondary_fixed
+ - @color/system_secondary_fixed_dim
+ - @color/system_tertiary_fixed
+ - @color/system_tertiary_fixed_dim
- @color/system_brand_a_dark
- @color/system_brand_b_dark
- @color/system_brand_c_dark
- @color/system_brand_d_dark
- - @color/system_under_surface_dark
- - @color/system_shade_active_dark
+ - @color/system_clock_hour_dark
+ - @color/system_clock_minute_dark
+ - @color/system_clock_second_dark
- @color/system_on_shade_active_dark
- @color/system_on_shade_active_variant_dark
- - @color/system_shade_inactive_dark
- @color/system_on_shade_inactive_dark
- @color/system_on_shade_inactive_variant_dark
- - @color/system_shade_disabled_dark
+ - @color/system_on_theme_app_dark
- @color/system_overview_background_dark
+ - @color/system_shade_active_dark
+ - @color/system_shade_disabled_dark
+ - @color/system_shade_inactive_dark
+ - @color/system_theme_app_dark
+ - @color/system_theme_app_ring_dark
+ - @color/system_theme_notif_dark
+ - @color/system_under_surface_dark
+ - @color/system_weather_temp_dark
+ - @color/system_widget_background_dark
@@ -2747,73 +3087,90 @@ easier.
- ?attr/colorBackgroundFloating
- ?attr/colorBackgroundFloating
- - @color/system_on_secondary_fixed_variant
- - @color/system_on_tertiary_fixed_variant
- - @color/system_surface_container_lowest_light
- - @color/system_on_primary_fixed_variant
- - @color/system_on_secondary_container_light
- - @color/system_on_tertiary_container_light
- - @color/system_surface_container_low_light
- - @color/system_on_primary_container_light
- - @color/system_secondary_fixed_dim
- - @color/system_on_error_container_light
- - @color/system_on_secondary_fixed
- - @color/system_on_surface_dark
- - @color/system_tertiary_fixed_dim
- - @color/system_on_tertiary_fixed
- - @color/system_primary_fixed_dim
- - @color/system_secondary_container_light
+ - @color/system_background_light
+ - @color/system_control_activated_light
+ - @color/system_control_highlight_light
+ - @color/system_control_normal_light
+ - @color/system_error_light
- @color/system_error_container_light
- - @color/system_on_primary_fixed
- - @color/system_primary_dark
- - @color/system_secondary_fixed
- - @color/system_surface_dark
- - @color/system_surface_variant_light
- - @color/system_tertiary_container_light
- - @color/system_tertiary_fixed
- - @color/system_primary_container_light
+ - @color/system_inverse_on_surface_light
+ - @color/system_inverse_primary_light
+ - @color/system_inverse_surface_light
- @color/system_on_background_light
- - @color/system_primary_fixed
- - @color/system_on_secondary_light
- - @color/system_on_tertiary_light
- - @color/system_surface_dim_light
- - @color/system_surface_bright_light
- @color/system_on_error_light
- - @color/system_surface_light
- - @color/system_surface_container_high_light
- - @color/system_surface_container_highest_light
+ - @color/system_on_error_container_light
+ - @color/system_on_primary_light
+ - @color/system_on_primary_container_light
+ - @color/system_on_secondary_light
+ - @color/system_on_secondary_container_light
+ - @color/system_on_surface_light
- @color/system_on_surface_variant_light
+ - @color/system_on_tertiary_light
+ - @color/system_on_tertiary_container_light
- @color/system_outline_light
- @color/system_outline_variant_light
- - @color/system_on_primary_light
- - @color/system_on_surface_light
- - @color/system_surface_container_light
+ - @color/system_palette_key_color_neutral_light
+ - @color/system_palette_key_color_neutral_variant_light
+ - @color/system_palette_key_color_primary_light
+ - @color/system_palette_key_color_secondary_light
+ - @color/system_palette_key_color_tertiary_light
- @color/system_primary_light
+ - @color/system_primary_container_light
+ - @color/system_scrim_light
- @color/system_secondary_light
+ - @color/system_secondary_container_light
+ - @color/system_shadow_light
+ - @color/system_surface_light
+ - @color/system_surface_bright_light
+ - @color/system_surface_container_light
+ - @color/system_surface_container_high_light
+ - @color/system_surface_container_highest_light
+ - @color/system_surface_container_low_light
+ - @color/system_surface_container_lowest_light
+ - @color/system_surface_dim_light
+ - @color/system_surface_tint_light
+ - @color/system_surface_variant_light
- @color/system_tertiary_light
- - @color/system_error_light
-
- - @color/system_widget_background_light
- - @color/system_clock_hour_light
- - @color/system_clock_minute_light
- - @color/system_clock_second_light
- - @color/system_theme_app_light
- - @color/system_on_theme_app_light
- - @color/system_theme_app_ring_light
- - @color/system_theme_notif_light
+ - @color/system_tertiary_container_light
+ - @color/system_text_hint_inverse_light
+ - @color/system_text_primary_inverse_light
+ - @color/system_text_primary_inverse_disable_only_light
+ - @color/system_text_secondary_and_tertiary_inverse_light
+ - @color/system_text_secondary_and_tertiary_inverse_disabled_light
+ - @color/system_on_primary_fixed
+ - @color/system_on_primary_fixed_variant
+ - @color/system_on_secondary_fixed
+ - @color/system_on_secondary_fixed_variant
+ - @color/system_on_tertiary_fixed
+ - @color/system_on_tertiary_fixed_variant
+ - @color/system_primary_fixed
+ - @color/system_primary_fixed_dim
+ - @color/system_secondary_fixed
+ - @color/system_secondary_fixed_dim
+ - @color/system_tertiary_fixed
+ - @color/system_tertiary_fixed_dim
- @color/system_brand_a_light
- @color/system_brand_b_light
- @color/system_brand_c_light
- @color/system_brand_d_light
- - @color/system_under_surface_light
- - @color/system_shade_active_light
+ - @color/system_clock_hour_light
+ - @color/system_clock_minute_light
+ - @color/system_clock_second_light
- @color/system_on_shade_active_light
- @color/system_on_shade_active_variant_light
- - @color/system_shade_inactive_light
- @color/system_on_shade_inactive_light
- @color/system_on_shade_inactive_variant_light
- - @color/system_shade_disabled_light
+ - @color/system_on_theme_app_light
- @color/system_overview_background_light
+ - @color/system_shade_active_light
+ - @color/system_shade_disabled_light
+ - @color/system_shade_inactive_light
+ - @color/system_theme_app_light
+ - @color/system_theme_app_ring_light
+ - @color/system_theme_notif_light
+ - @color/system_under_surface_light
+ - @color/system_weather_temp_light
+ - @color/system_widget_background_light
- @style/Widget.DeviceDefault.Toolbar
- - @color/system_on_secondary_fixed_variant
- - @color/system_on_tertiary_fixed_variant
- - @color/system_surface_container_lowest_light
- - @color/system_on_primary_fixed_variant
- - @color/system_on_secondary_container_light
- - @color/system_on_tertiary_container_light
- - @color/system_surface_container_low_light
- - @color/system_on_primary_container_light
- - @color/system_secondary_fixed_dim
- - @color/system_on_error_container_light
- - @color/system_on_secondary_fixed
- - @color/system_on_surface_dark
- - @color/system_tertiary_fixed_dim
- - @color/system_on_tertiary_fixed
- - @color/system_primary_fixed_dim
- - @color/system_secondary_container_light
+ - @color/system_background_light
+ - @color/system_control_activated_light
+ - @color/system_control_highlight_light
+ - @color/system_control_normal_light
+ - @color/system_error_light
- @color/system_error_container_light
- - @color/system_on_primary_fixed
- - @color/system_primary_dark
- - @color/system_secondary_fixed
- - @color/system_surface_dark
- - @color/system_surface_variant_light
- - @color/system_tertiary_container_light
- - @color/system_tertiary_fixed
- - @color/system_primary_container_light
+ - @color/system_inverse_on_surface_light
+ - @color/system_inverse_primary_light
+ - @color/system_inverse_surface_light
- @color/system_on_background_light
- - @color/system_primary_fixed
- - @color/system_on_secondary_light
- - @color/system_on_tertiary_light
- - @color/system_surface_dim_light
- - @color/system_surface_bright_light
- @color/system_on_error_light
- - @color/system_surface_light
- - @color/system_surface_container_high_light
- - @color/system_surface_container_highest_light
+ - @color/system_on_error_container_light
+ - @color/system_on_primary_light
+ - @color/system_on_primary_container_light
+ - @color/system_on_secondary_light
+ - @color/system_on_secondary_container_light
+ - @color/system_on_surface_light
- @color/system_on_surface_variant_light
+ - @color/system_on_tertiary_light
+ - @color/system_on_tertiary_container_light
- @color/system_outline_light
- @color/system_outline_variant_light
- - @color/system_on_primary_light
- - @color/system_on_surface_light
- - @color/system_surface_container_light
+ - @color/system_palette_key_color_neutral_light
+ - @color/system_palette_key_color_neutral_variant_light
+ - @color/system_palette_key_color_primary_light
+ - @color/system_palette_key_color_secondary_light
+ - @color/system_palette_key_color_tertiary_light
- @color/system_primary_light
+ - @color/system_primary_container_light
+ - @color/system_scrim_light
- @color/system_secondary_light
+ - @color/system_secondary_container_light
+ - @color/system_shadow_light
+ - @color/system_surface_light
+ - @color/system_surface_bright_light
+ - @color/system_surface_container_light
+ - @color/system_surface_container_high_light
+ - @color/system_surface_container_highest_light
+ - @color/system_surface_container_low_light
+ - @color/system_surface_container_lowest_light
+ - @color/system_surface_dim_light
+ - @color/system_surface_tint_light
+ - @color/system_surface_variant_light
- @color/system_tertiary_light
- - @color/system_error_light
-
- - @color/system_widget_background_light
- - @color/system_clock_hour_light
- - @color/system_clock_minute_light
- - @color/system_clock_second_light
- - @color/system_theme_app_light
- - @color/system_on_theme_app_light
- - @color/system_theme_app_ring_light
- - @color/system_theme_notif_light
+ - @color/system_tertiary_container_light
+ - @color/system_text_hint_inverse_light
+ - @color/system_text_primary_inverse_light
+ - @color/system_text_primary_inverse_disable_only_light
+ - @color/system_text_secondary_and_tertiary_inverse_light
+ - @color/system_text_secondary_and_tertiary_inverse_disabled_light
+ - @color/system_on_primary_fixed
+ - @color/system_on_primary_fixed_variant
+ - @color/system_on_secondary_fixed
+ - @color/system_on_secondary_fixed_variant
+ - @color/system_on_tertiary_fixed
+ - @color/system_on_tertiary_fixed_variant
+ - @color/system_primary_fixed
+ - @color/system_primary_fixed_dim
+ - @color/system_secondary_fixed
+ - @color/system_secondary_fixed_dim
+ - @color/system_tertiary_fixed
+ - @color/system_tertiary_fixed_dim
- @color/system_brand_a_light
- @color/system_brand_b_light
- @color/system_brand_c_light
- @color/system_brand_d_light
- - @color/system_under_surface_light
- - @color/system_shade_active_light
+ - @color/system_clock_hour_light
+ - @color/system_clock_minute_light
+ - @color/system_clock_second_light
- @color/system_on_shade_active_light
- @color/system_on_shade_active_variant_light
- - @color/system_shade_inactive_light
- @color/system_on_shade_inactive_light
- @color/system_on_shade_inactive_variant_light
- - @color/system_shade_disabled_light
+ - @color/system_on_theme_app_light
- @color/system_overview_background_light
+ - @color/system_shade_active_light
+ - @color/system_shade_disabled_light
+ - @color/system_shade_inactive_light
+ - @color/system_theme_app_light
+ - @color/system_theme_app_ring_light
+ - @color/system_theme_notif_light
+ - @color/system_under_surface_light
+ - @color/system_weather_temp_light
+ - @color/system_widget_background_light
@@ -2980,73 +3354,90 @@ easier.
- @style/Widget.DeviceDefault.Toolbar
- - @color/system_on_secondary_fixed_variant
- - @color/system_on_tertiary_fixed_variant
- - @color/system_surface_container_lowest_light
- - @color/system_on_primary_fixed_variant
- - @color/system_on_secondary_container_light
- - @color/system_on_tertiary_container_light
- - @color/system_surface_container_low_light
- - @color/system_on_primary_container_light
- - @color/system_secondary_fixed_dim
- - @color/system_on_error_container_light
- - @color/system_on_secondary_fixed
- - @color/system_on_surface_dark
- - @color/system_tertiary_fixed_dim
- - @color/system_on_tertiary_fixed
- - @color/system_primary_fixed_dim
- - @color/system_secondary_container_light
+ - @color/system_background_light
+ - @color/system_control_activated_light
+ - @color/system_control_highlight_light
+ - @color/system_control_normal_light
+ - @color/system_error_light
- @color/system_error_container_light
- - @color/system_on_primary_fixed
- - @color/system_primary_dark
- - @color/system_secondary_fixed
- - @color/system_surface_dark
- - @color/system_surface_variant_light
- - @color/system_tertiary_container_light
- - @color/system_tertiary_fixed
- - @color/system_primary_container_light
+ - @color/system_inverse_on_surface_light
+ - @color/system_inverse_primary_light
+ - @color/system_inverse_surface_light
- @color/system_on_background_light
- - @color/system_primary_fixed
- - @color/system_on_secondary_light
- - @color/system_on_tertiary_light
- - @color/system_surface_dim_light
- - @color/system_surface_bright_light
- @color/system_on_error_light
- - @color/system_surface_light
- - @color/system_surface_container_high_light
- - @color/system_surface_container_highest_light
+ - @color/system_on_error_container_light
+ - @color/system_on_primary_light
+ - @color/system_on_primary_container_light
+ - @color/system_on_secondary_light
+ - @color/system_on_secondary_container_light
+ - @color/system_on_surface_light
- @color/system_on_surface_variant_light
+ - @color/system_on_tertiary_light
+ - @color/system_on_tertiary_container_light
- @color/system_outline_light
- @color/system_outline_variant_light
- - @color/system_on_primary_light
- - @color/system_on_surface_light
- - @color/system_surface_container_light
+ - @color/system_palette_key_color_neutral_light
+ - @color/system_palette_key_color_neutral_variant_light
+ - @color/system_palette_key_color_primary_light
+ - @color/system_palette_key_color_secondary_light
+ - @color/system_palette_key_color_tertiary_light
- @color/system_primary_light
+ - @color/system_primary_container_light
+ - @color/system_scrim_light
- @color/system_secondary_light
+ - @color/system_secondary_container_light
+ - @color/system_shadow_light
+ - @color/system_surface_light
+ - @color/system_surface_bright_light
+ - @color/system_surface_container_light
+ - @color/system_surface_container_high_light
+ - @color/system_surface_container_highest_light
+ - @color/system_surface_container_low_light
+ - @color/system_surface_container_lowest_light
+ - @color/system_surface_dim_light
+ - @color/system_surface_tint_light
+ - @color/system_surface_variant_light
- @color/system_tertiary_light
- - @color/system_error_light
-
- - @color/system_widget_background_light
- - @color/system_clock_hour_light
- - @color/system_clock_minute_light
- - @color/system_clock_second_light
- - @color/system_theme_app_light
- - @color/system_on_theme_app_light
- - @color/system_theme_app_ring_light
- - @color/system_theme_notif_light
+ - @color/system_tertiary_container_light
+ - @color/system_text_hint_inverse_light
+ - @color/system_text_primary_inverse_light
+ - @color/system_text_primary_inverse_disable_only_light
+ - @color/system_text_secondary_and_tertiary_inverse_light
+ - @color/system_text_secondary_and_tertiary_inverse_disabled_light
+ - @color/system_on_primary_fixed
+ - @color/system_on_primary_fixed_variant
+ - @color/system_on_secondary_fixed
+ - @color/system_on_secondary_fixed_variant
+ - @color/system_on_tertiary_fixed
+ - @color/system_on_tertiary_fixed_variant
+ - @color/system_primary_fixed
+ - @color/system_primary_fixed_dim
+ - @color/system_secondary_fixed
+ - @color/system_secondary_fixed_dim
+ - @color/system_tertiary_fixed
+ - @color/system_tertiary_fixed_dim
- @color/system_brand_a_light
- @color/system_brand_b_light
- @color/system_brand_c_light
- @color/system_brand_d_light
- - @color/system_under_surface_light
- - @color/system_shade_active_light
+ - @color/system_clock_hour_light
+ - @color/system_clock_minute_light
+ - @color/system_clock_second_light
- @color/system_on_shade_active_light
- @color/system_on_shade_active_variant_light
- - @color/system_shade_inactive_light
- @color/system_on_shade_inactive_light
- @color/system_on_shade_inactive_variant_light
- - @color/system_shade_disabled_light
+ - @color/system_on_theme_app_light
- @color/system_overview_background_light
+ - @color/system_shade_active_light
+ - @color/system_shade_disabled_light
+ - @color/system_shade_inactive_light
+ - @color/system_theme_app_light
+ - @color/system_theme_app_ring_light
+ - @color/system_theme_notif_light
+ - @color/system_under_surface_light
+ - @color/system_weather_temp_light
+ - @color/system_widget_background_light
- @style/Widget.DeviceDefault.Toolbar
- - @color/system_on_secondary_fixed_variant
- - @color/system_on_tertiary_fixed_variant
- - @color/system_surface_container_lowest_light
- - @color/system_on_primary_fixed_variant
- - @color/system_on_secondary_container_light
- - @color/system_on_tertiary_container_light
- - @color/system_surface_container_low_light
- - @color/system_on_primary_container_light
- - @color/system_secondary_fixed_dim
- - @color/system_on_error_container_light
- - @color/system_on_secondary_fixed
- - @color/system_on_surface_dark
- - @color/system_tertiary_fixed_dim
- - @color/system_on_tertiary_fixed
- - @color/system_primary_fixed_dim
- - @color/system_secondary_container_light
+ - @color/system_background_light
+ - @color/system_control_activated_light
+ - @color/system_control_highlight_light
+ - @color/system_control_normal_light
+ - @color/system_error_light
- @color/system_error_container_light
- - @color/system_on_primary_fixed
- - @color/system_primary_dark
- - @color/system_secondary_fixed
- - @color/system_surface_dark
- - @color/system_surface_variant_light
- - @color/system_tertiary_container_light
- - @color/system_tertiary_fixed
- - @color/system_primary_container_light
+ - @color/system_inverse_on_surface_light
+ - @color/system_inverse_primary_light
+ - @color/system_inverse_surface_light
- @color/system_on_background_light
- - @color/system_primary_fixed
- - @color/system_on_secondary_light
- - @color/system_on_tertiary_light
- - @color/system_surface_dim_light
- - @color/system_surface_bright_light
- @color/system_on_error_light
- - @color/system_surface_light
- - @color/system_surface_container_high_light
- - @color/system_surface_container_highest_light
+ - @color/system_on_error_container_light
+ - @color/system_on_primary_light
+ - @color/system_on_primary_container_light
+ - @color/system_on_secondary_light
+ - @color/system_on_secondary_container_light
+ - @color/system_on_surface_light
- @color/system_on_surface_variant_light
+ - @color/system_on_tertiary_light
+ - @color/system_on_tertiary_container_light
- @color/system_outline_light
- @color/system_outline_variant_light
- - @color/system_on_primary_light
- - @color/system_on_surface_light
- - @color/system_surface_container_light
+ - @color/system_palette_key_color_neutral_light
+ - @color/system_palette_key_color_neutral_variant_light
+ - @color/system_palette_key_color_primary_light
+ - @color/system_palette_key_color_secondary_light
+ - @color/system_palette_key_color_tertiary_light
- @color/system_primary_light
+ - @color/system_primary_container_light
+ - @color/system_scrim_light
- @color/system_secondary_light
+ - @color/system_secondary_container_light
+ - @color/system_shadow_light
+ - @color/system_surface_light
+ - @color/system_surface_bright_light
+ - @color/system_surface_container_light
+ - @color/system_surface_container_high_light
+ - @color/system_surface_container_highest_light
+ - @color/system_surface_container_low_light
+ - @color/system_surface_container_lowest_light
+ - @color/system_surface_dim_light
+ - @color/system_surface_tint_light
+ - @color/system_surface_variant_light
- @color/system_tertiary_light
- - @color/system_error_light
-
- - @color/system_widget_background_light
- - @color/system_clock_hour_light
- - @color/system_clock_minute_light
- - @color/system_clock_second_light
- - @color/system_theme_app_light
- - @color/system_on_theme_app_light
- - @color/system_theme_app_ring_light
- - @color/system_theme_notif_light
+ - @color/system_tertiary_container_light
+ - @color/system_text_hint_inverse_light
+ - @color/system_text_primary_inverse_light
+ - @color/system_text_primary_inverse_disable_only_light
+ - @color/system_text_secondary_and_tertiary_inverse_light
+ - @color/system_text_secondary_and_tertiary_inverse_disabled_light
+ - @color/system_on_primary_fixed
+ - @color/system_on_primary_fixed_variant
+ - @color/system_on_secondary_fixed
+ - @color/system_on_secondary_fixed_variant
+ - @color/system_on_tertiary_fixed
+ - @color/system_on_tertiary_fixed_variant
+ - @color/system_primary_fixed
+ - @color/system_primary_fixed_dim
+ - @color/system_secondary_fixed
+ - @color/system_secondary_fixed_dim
+ - @color/system_tertiary_fixed
+ - @color/system_tertiary_fixed_dim
- @color/system_brand_a_light
- @color/system_brand_b_light
- @color/system_brand_c_light
- @color/system_brand_d_light
- - @color/system_under_surface_light
- - @color/system_shade_active_light
+ - @color/system_clock_hour_light
+ - @color/system_clock_minute_light
+ - @color/system_clock_second_light
- @color/system_on_shade_active_light
- @color/system_on_shade_active_variant_light
- - @color/system_shade_inactive_light
- @color/system_on_shade_inactive_light
- @color/system_on_shade_inactive_variant_light
- - @color/system_shade_disabled_light
+ - @color/system_on_theme_app_light
- @color/system_overview_background_light
+ - @color/system_shade_active_light
+ - @color/system_shade_disabled_light
+ - @color/system_shade_inactive_light
+ - @color/system_theme_app_light
+ - @color/system_theme_app_ring_light
+ - @color/system_theme_notif_light
+ - @color/system_under_surface_light
+ - @color/system_weather_temp_light
+ - @color/system_widget_background_light
- @style/Widget.DeviceDefault.Toolbar
- - @color/system_on_secondary_fixed_variant
- - @color/system_on_tertiary_fixed_variant
- - @color/system_surface_container_lowest_light
- - @color/system_on_primary_fixed_variant
- - @color/system_on_secondary_container_light
- - @color/system_on_tertiary_container_light
- - @color/system_surface_container_low_light
- - @color/system_on_primary_container_light
- - @color/system_secondary_fixed_dim
- - @color/system_on_error_container_light
- - @color/system_on_secondary_fixed
- - @color/system_on_surface_dark
- - @color/system_tertiary_fixed_dim
- - @color/system_on_tertiary_fixed
- - @color/system_primary_fixed_dim
- - @color/system_secondary_container_light
+ - @color/system_background_light
+ - @color/system_control_activated_light
+ - @color/system_control_highlight_light
+ - @color/system_control_normal_light
+ - @color/system_error_light
- @color/system_error_container_light
- - @color/system_on_primary_fixed
- - @color/system_primary_dark
- - @color/system_secondary_fixed
- - @color/system_surface_dark
- - @color/system_surface_variant_light
- - @color/system_tertiary_container_light
- - @color/system_tertiary_fixed
- - @color/system_primary_container_light
+ - @color/system_inverse_on_surface_light
+ - @color/system_inverse_primary_light
+ - @color/system_inverse_surface_light
- @color/system_on_background_light
- - @color/system_primary_fixed
- - @color/system_on_secondary_light
- - @color/system_on_tertiary_light
- - @color/system_surface_dim_light
- - @color/system_surface_bright_light
- @color/system_on_error_light
- - @color/system_surface_light
- - @color/system_surface_container_high_light
- - @color/system_surface_container_highest_light
+ - @color/system_on_error_container_light
+ - @color/system_on_primary_light
+ - @color/system_on_primary_container_light
+ - @color/system_on_secondary_light
+ - @color/system_on_secondary_container_light
+ - @color/system_on_surface_light
- @color/system_on_surface_variant_light
+ - @color/system_on_tertiary_light
+ - @color/system_on_tertiary_container_light
- @color/system_outline_light
- @color/system_outline_variant_light
- - @color/system_on_primary_light
- - @color/system_on_surface_light
- - @color/system_surface_container_light
+ - @color/system_palette_key_color_neutral_light
+ - @color/system_palette_key_color_neutral_variant_light
+ - @color/system_palette_key_color_primary_light
+ - @color/system_palette_key_color_secondary_light
+ - @color/system_palette_key_color_tertiary_light
- @color/system_primary_light
+ - @color/system_primary_container_light
+ - @color/system_scrim_light
- @color/system_secondary_light
+ - @color/system_secondary_container_light
+ - @color/system_shadow_light
+ - @color/system_surface_light
+ - @color/system_surface_bright_light
+ - @color/system_surface_container_light
+ - @color/system_surface_container_high_light
+ - @color/system_surface_container_highest_light
+ - @color/system_surface_container_low_light
+ - @color/system_surface_container_lowest_light
+ - @color/system_surface_dim_light
+ - @color/system_surface_tint_light
+ - @color/system_surface_variant_light
- @color/system_tertiary_light
- - @color/system_error_light
-
- - @color/system_widget_background_light
- - @color/system_clock_hour_light
- - @color/system_clock_minute_light
- - @color/system_clock_second_light
- - @color/system_theme_app_light
- - @color/system_on_theme_app_light
- - @color/system_theme_app_ring_light
- - @color/system_theme_notif_light
+ - @color/system_tertiary_container_light
+ - @color/system_text_hint_inverse_light
+ - @color/system_text_primary_inverse_light
+ - @color/system_text_primary_inverse_disable_only_light
+ - @color/system_text_secondary_and_tertiary_inverse_light
+ - @color/system_text_secondary_and_tertiary_inverse_disabled_light
+ - @color/system_on_primary_fixed
+ - @color/system_on_primary_fixed_variant
+ - @color/system_on_secondary_fixed
+ - @color/system_on_secondary_fixed_variant
+ - @color/system_on_tertiary_fixed
+ - @color/system_on_tertiary_fixed_variant
+ - @color/system_primary_fixed
+ - @color/system_primary_fixed_dim
+ - @color/system_secondary_fixed
+ - @color/system_secondary_fixed_dim
+ - @color/system_tertiary_fixed
+ - @color/system_tertiary_fixed_dim
- @color/system_brand_a_light
- @color/system_brand_b_light
- @color/system_brand_c_light
- @color/system_brand_d_light
- - @color/system_under_surface_light
- - @color/system_shade_active_light
+ - @color/system_clock_hour_light
+ - @color/system_clock_minute_light
+ - @color/system_clock_second_light
- @color/system_on_shade_active_light
- @color/system_on_shade_active_variant_light
- - @color/system_shade_inactive_light
- @color/system_on_shade_inactive_light
- @color/system_on_shade_inactive_variant_light
- - @color/system_shade_disabled_light
+ - @color/system_on_theme_app_light
- @color/system_overview_background_light
+ - @color/system_shade_active_light
+ - @color/system_shade_disabled_light
+ - @color/system_shade_inactive_light
+ - @color/system_theme_app_light
+ - @color/system_theme_app_ring_light
+ - @color/system_theme_notif_light
+ - @color/system_under_surface_light
+ - @color/system_weather_temp_light
+ - @color/system_widget_background_light
- @style/Widget.DeviceDefault.Toolbar
- - @color/system_on_secondary_fixed_variant
- - @color/system_on_tertiary_fixed_variant
- - @color/system_surface_container_lowest_light
- - @color/system_on_primary_fixed_variant
+ - @color/system_background_light
+ - @color/system_control_activated_light
+ - @color/system_control_highlight_light
+ - @color/system_control_normal_light
+ - @color/system_error_light
+ - @color/system_error_container_light
+ - @color/system_inverse_on_surface_light
+ - @color/system_inverse_primary_light
+ - @color/system_inverse_surface_light
+ - @color/system_on_background_light
+ - @color/system_on_error_light
+ - @color/system_on_error_container_light
+ - @color/system_on_primary_light
+ - @color/system_on_primary_container_light
+ - @color/system_on_secondary_light
- @color/system_on_secondary_container_light
+ - @color/system_on_surface_light
+ - @color/system_on_surface_variant_light
+ - @color/system_on_tertiary_light
- @color/system_on_tertiary_container_light
- - @color/system_surface_container_low_light
- - @color/system_on_primary_container_light
- - @color/system_secondary_fixed_dim
- - @color/system_on_error_container_light
- - @color/system_on_secondary_fixed
- - @color/system_on_surface_dark
- - @color/system_tertiary_fixed_dim
- - @color/system_on_tertiary_fixed
- - @color/system_primary_fixed_dim
- - @color/system_secondary_container_light
- - @color/system_error_container_light
- - @color/system_on_primary_fixed
- - @color/system_primary_dark
- - @color/system_secondary_fixed
- - @color/system_surface_dark
- - @color/system_surface_variant_light
- - @color/system_tertiary_container_light
- - @color/system_tertiary_fixed
- - @color/system_primary_container_light
- - @color/system_on_background_light
- - @color/system_primary_fixed
- - @color/system_on_secondary_light
- - @color/system_on_tertiary_light
- - @color/system_surface_dim_light
- - @color/system_surface_bright_light
- - @color/system_on_error_light
- - @color/system_surface_light
- - @color/system_surface_container_high_light
- - @color/system_surface_container_highest_light
- - @color/system_on_surface_variant_light
- @color/system_outline_light
- @color/system_outline_variant_light
- - @color/system_on_primary_light
- - @color/system_on_surface_light
- - @color/system_surface_container_light
+ - @color/system_palette_key_color_neutral_light
+ - @color/system_palette_key_color_neutral_variant_light
+ - @color/system_palette_key_color_primary_light
+ - @color/system_palette_key_color_secondary_light
+ - @color/system_palette_key_color_tertiary_light
- @color/system_primary_light
+ - @color/system_primary_container_light
+ - @color/system_scrim_light
- @color/system_secondary_light
+ - @color/system_secondary_container_light
+ - @color/system_shadow_light
+ - @color/system_surface_light
+ - @color/system_surface_bright_light
+ - @color/system_surface_container_light
+ - @color/system_surface_container_high_light
+ - @color/system_surface_container_highest_light
+ - @color/system_surface_container_low_light
+ - @color/system_surface_container_lowest_light
+ - @color/system_surface_dim_light
+ - @color/system_surface_tint_light
+ - @color/system_surface_variant_light
- @color/system_tertiary_light
- - @color/system_error_light
-
- - @color/system_widget_background_light
- - @color/system_clock_hour_light
- - @color/system_clock_minute_light
- - @color/system_clock_second_light
- - @color/system_theme_app_light
- - @color/system_on_theme_app_light
- - @color/system_theme_app_ring_light
- - @color/system_theme_notif_light
+ - @color/system_tertiary_container_light
+ - @color/system_text_hint_inverse_light
+ - @color/system_text_primary_inverse_light
+ - @color/system_text_primary_inverse_disable_only_light
+ - @color/system_text_secondary_and_tertiary_inverse_light
+ - @color/system_text_secondary_and_tertiary_inverse_disabled_light
+ - @color/system_on_primary_fixed
+ - @color/system_on_primary_fixed_variant
+ - @color/system_on_secondary_fixed
+ - @color/system_on_secondary_fixed_variant
+ - @color/system_on_tertiary_fixed
+ - @color/system_on_tertiary_fixed_variant
+ - @color/system_primary_fixed
+ - @color/system_primary_fixed_dim
+ - @color/system_secondary_fixed
+ - @color/system_secondary_fixed_dim
+ - @color/system_tertiary_fixed
+ - @color/system_tertiary_fixed_dim
- @color/system_brand_a_light
- @color/system_brand_b_light
- @color/system_brand_c_light
- @color/system_brand_d_light
- - @color/system_under_surface_light
- - @color/system_shade_active_light
+ - @color/system_clock_hour_light
+ - @color/system_clock_minute_light
+ - @color/system_clock_second_light
- @color/system_on_shade_active_light
- @color/system_on_shade_active_variant_light
- - @color/system_shade_inactive_light
- @color/system_on_shade_inactive_light
- @color/system_on_shade_inactive_variant_light
- - @color/system_shade_disabled_light
+ - @color/system_on_theme_app_light
- @color/system_overview_background_light
+ - @color/system_shade_active_light
+ - @color/system_shade_disabled_light
+ - @color/system_shade_inactive_light
+ - @color/system_theme_app_light
+ - @color/system_theme_app_ring_light
+ - @color/system_theme_notif_light
+ - @color/system_under_surface_light
+ - @color/system_weather_temp_light
+ - @color/system_widget_background_light
- @style/Widget.DeviceDefault.Toolbar
- - @color/system_on_secondary_fixed_variant
- - @color/system_on_tertiary_fixed_variant
- - @color/system_surface_container_lowest_light
- - @color/system_on_primary_fixed_variant
- - @color/system_on_secondary_container_light
- - @color/system_on_tertiary_container_light
- - @color/system_surface_container_low_light
- - @color/system_on_primary_container_light
- - @color/system_secondary_fixed_dim
- - @color/system_on_error_container_light
- - @color/system_on_secondary_fixed
- - @color/system_on_surface_dark
- - @color/system_tertiary_fixed_dim
- - @color/system_on_tertiary_fixed
- - @color/system_primary_fixed_dim
- - @color/system_secondary_container_light
+ - @color/system_background_light
+ - @color/system_control_activated_light
+ - @color/system_control_highlight_light
+ - @color/system_control_normal_light
+ - @color/system_error_light
- @color/system_error_container_light
- - @color/system_on_primary_fixed
- - @color/system_primary_dark
- - @color/system_secondary_fixed
- - @color/system_surface_dark
- - @color/system_surface_variant_light
- - @color/system_tertiary_container_light
- - @color/system_tertiary_fixed
- - @color/system_primary_container_light
+ - @color/system_inverse_on_surface_light
+ - @color/system_inverse_primary_light
+ - @color/system_inverse_surface_light
- @color/system_on_background_light
- - @color/system_primary_fixed
- - @color/system_on_secondary_light
- - @color/system_on_tertiary_light
- - @color/system_surface_dim_light
- - @color/system_surface_bright_light
- @color/system_on_error_light
- - @color/system_surface_light
- - @color/system_surface_container_high_light
- - @color/system_surface_container_highest_light
+ - @color/system_on_error_container_light
+ - @color/system_on_primary_light
+ - @color/system_on_primary_container_light
+ - @color/system_on_secondary_light
+ - @color/system_on_secondary_container_light
+ - @color/system_on_surface_light
- @color/system_on_surface_variant_light
+ - @color/system_on_tertiary_light
+ - @color/system_on_tertiary_container_light
- @color/system_outline_light
- @color/system_outline_variant_light
- - @color/system_on_primary_light
- - @color/system_on_surface_light
- - @color/system_surface_container_light
+ - @color/system_palette_key_color_neutral_light
+ - @color/system_palette_key_color_neutral_variant_light
+ - @color/system_palette_key_color_primary_light
+ - @color/system_palette_key_color_secondary_light
+ - @color/system_palette_key_color_tertiary_light
- @color/system_primary_light
+ - @color/system_primary_container_light
+ - @color/system_scrim_light
- @color/system_secondary_light
+ - @color/system_secondary_container_light
+ - @color/system_shadow_light
+ - @color/system_surface_light
+ - @color/system_surface_bright_light
+ - @color/system_surface_container_light
+ - @color/system_surface_container_high_light
+ - @color/system_surface_container_highest_light
+ - @color/system_surface_container_low_light
+ - @color/system_surface_container_lowest_light
+ - @color/system_surface_dim_light
+ - @color/system_surface_tint_light
+ - @color/system_surface_variant_light
- @color/system_tertiary_light
- - @color/system_error_light
-
- - @color/system_widget_background_light
- - @color/system_clock_hour_light
- - @color/system_clock_minute_light
- - @color/system_clock_second_light
- - @color/system_theme_app_light
- - @color/system_on_theme_app_light
- - @color/system_theme_app_ring_light
- - @color/system_theme_notif_light
+ - @color/system_tertiary_container_light
+ - @color/system_text_hint_inverse_light
+ - @color/system_text_primary_inverse_light
+ - @color/system_text_primary_inverse_disable_only_light
+ - @color/system_text_secondary_and_tertiary_inverse_light
+ - @color/system_text_secondary_and_tertiary_inverse_disabled_light
+ - @color/system_on_primary_fixed
+ - @color/system_on_primary_fixed_variant
+ - @color/system_on_secondary_fixed
+ - @color/system_on_secondary_fixed_variant
+ - @color/system_on_tertiary_fixed
+ - @color/system_on_tertiary_fixed_variant
+ - @color/system_primary_fixed
+ - @color/system_primary_fixed_dim
+ - @color/system_secondary_fixed
+ - @color/system_secondary_fixed_dim
+ - @color/system_tertiary_fixed
+ - @color/system_tertiary_fixed_dim
- @color/system_brand_a_light
- @color/system_brand_b_light
- @color/system_brand_c_light
- @color/system_brand_d_light
- - @color/system_under_surface_light
- - @color/system_shade_active_light
+ - @color/system_clock_hour_light
+ - @color/system_clock_minute_light
+ - @color/system_clock_second_light
- @color/system_on_shade_active_light
- @color/system_on_shade_active_variant_light
- - @color/system_shade_inactive_light
- @color/system_on_shade_inactive_light
- @color/system_on_shade_inactive_variant_light
- - @color/system_shade_disabled_light
+ - @color/system_on_theme_app_light
- @color/system_overview_background_light
+ - @color/system_shade_active_light
+ - @color/system_shade_disabled_light
+ - @color/system_shade_inactive_light
+ - @color/system_theme_app_light
+ - @color/system_theme_app_ring_light
+ - @color/system_theme_notif_light
+ - @color/system_under_surface_light
+ - @color/system_weather_temp_light
+ - @color/system_widget_background_light
- @style/Widget.DeviceDefault.Toolbar
- - @color/system_on_secondary_fixed_variant
- - @color/system_on_tertiary_fixed_variant
- - @color/system_surface_container_lowest_light
- - @color/system_on_primary_fixed_variant
- - @color/system_on_secondary_container_light
- - @color/system_on_tertiary_container_light
- - @color/system_surface_container_low_light
- - @color/system_on_primary_container_light
- - @color/system_secondary_fixed_dim
- - @color/system_on_error_container_light
- - @color/system_on_secondary_fixed
- - @color/system_on_surface_dark
- - @color/system_tertiary_fixed_dim
- - @color/system_on_tertiary_fixed
- - @color/system_primary_fixed_dim
- - @color/system_secondary_container_light
+ - @color/system_background_light
+ - @color/system_control_activated_light
+ - @color/system_control_highlight_light
+ - @color/system_control_normal_light
+ - @color/system_error_light
- @color/system_error_container_light
- - @color/system_on_primary_fixed
- - @color/system_primary_dark
- - @color/system_secondary_fixed
- - @color/system_surface_dark
- - @color/system_surface_variant_light
- - @color/system_tertiary_container_light
- - @color/system_tertiary_fixed
- - @color/system_primary_container_light
+ - @color/system_inverse_on_surface_light
+ - @color/system_inverse_primary_light
+ - @color/system_inverse_surface_light
- @color/system_on_background_light
- - @color/system_primary_fixed
- - @color/system_on_secondary_light
- - @color/system_on_tertiary_light
- - @color/system_surface_dim_light
- - @color/system_surface_bright_light
- @color/system_on_error_light
- - @color/system_surface_light
- - @color/system_surface_container_high_light
- - @color/system_surface_container_highest_light
+ - @color/system_on_error_container_light
+ - @color/system_on_primary_light
+ - @color/system_on_primary_container_light
+ - @color/system_on_secondary_light
+ - @color/system_on_secondary_container_light
+ - @color/system_on_surface_light
- @color/system_on_surface_variant_light
+ - @color/system_on_tertiary_light
+ - @color/system_on_tertiary_container_light
- @color/system_outline_light
- @color/system_outline_variant_light
- - @color/system_on_primary_light
- - @color/system_on_surface_light
- - @color/system_surface_container_light
+ - @color/system_palette_key_color_neutral_light
+ - @color/system_palette_key_color_neutral_variant_light
+ - @color/system_palette_key_color_primary_light
+ - @color/system_palette_key_color_secondary_light
+ - @color/system_palette_key_color_tertiary_light
- @color/system_primary_light
+ - @color/system_primary_container_light
+ - @color/system_scrim_light
- @color/system_secondary_light
+ - @color/system_secondary_container_light
+ - @color/system_shadow_light
+ - @color/system_surface_light
+ - @color/system_surface_bright_light
+ - @color/system_surface_container_light
+ - @color/system_surface_container_high_light
+ - @color/system_surface_container_highest_light
+ - @color/system_surface_container_low_light
+ - @color/system_surface_container_lowest_light
+ - @color/system_surface_dim_light
+ - @color/system_surface_tint_light
+ - @color/system_surface_variant_light
- @color/system_tertiary_light
- - @color/system_error_light
-
- - @color/system_widget_background_light
- - @color/system_clock_hour_light
- - @color/system_clock_minute_light
- - @color/system_clock_second_light
- - @color/system_theme_app_light
- - @color/system_on_theme_app_light
- - @color/system_theme_app_ring_light
- - @color/system_theme_notif_light
+ - @color/system_tertiary_container_light
+ - @color/system_text_hint_inverse_light
+ - @color/system_text_primary_inverse_light
+ - @color/system_text_primary_inverse_disable_only_light
+ - @color/system_text_secondary_and_tertiary_inverse_light
+ - @color/system_text_secondary_and_tertiary_inverse_disabled_light
+ - @color/system_on_primary_fixed
+ - @color/system_on_primary_fixed_variant
+ - @color/system_on_secondary_fixed
+ - @color/system_on_secondary_fixed_variant
+ - @color/system_on_tertiary_fixed
+ - @color/system_on_tertiary_fixed_variant
+ - @color/system_primary_fixed
+ - @color/system_primary_fixed_dim
+ - @color/system_secondary_fixed
+ - @color/system_secondary_fixed_dim
+ - @color/system_tertiary_fixed
+ - @color/system_tertiary_fixed_dim
- @color/system_brand_a_light
- @color/system_brand_b_light
- @color/system_brand_c_light
- @color/system_brand_d_light
- - @color/system_under_surface_light
- - @color/system_shade_active_light
+ - @color/system_clock_hour_light
+ - @color/system_clock_minute_light
+ - @color/system_clock_second_light
- @color/system_on_shade_active_light
- @color/system_on_shade_active_variant_light
- - @color/system_shade_inactive_light
- @color/system_on_shade_inactive_light
- @color/system_on_shade_inactive_variant_light
- - @color/system_shade_disabled_light
+ - @color/system_on_theme_app_light
- @color/system_overview_background_light
+ - @color/system_shade_active_light
+ - @color/system_shade_disabled_light
+ - @color/system_shade_inactive_light
+ - @color/system_theme_app_light
+ - @color/system_theme_app_ring_light
+ - @color/system_theme_notif_light
+ - @color/system_under_surface_light
+ - @color/system_weather_temp_light
+ - @color/system_widget_background_light
@@ -3697,73 +4173,90 @@ easier.
- @style/Widget.DeviceDefault.Toolbar
- - @color/system_on_secondary_fixed_variant
- - @color/system_on_tertiary_fixed_variant
- - @color/system_surface_container_lowest_light
- - @color/system_on_primary_fixed_variant
- - @color/system_on_secondary_container_light
- - @color/system_on_tertiary_container_light
- - @color/system_surface_container_low_light
- - @color/system_on_primary_container_light
- - @color/system_secondary_fixed_dim
- - @color/system_on_error_container_light
- - @color/system_on_secondary_fixed
- - @color/system_on_surface_dark
- - @color/system_tertiary_fixed_dim
- - @color/system_on_tertiary_fixed
- - @color/system_primary_fixed_dim
- - @color/system_secondary_container_light
+ - @color/system_background_light
+ - @color/system_control_activated_light
+ - @color/system_control_highlight_light
+ - @color/system_control_normal_light
+ - @color/system_error_light
- @color/system_error_container_light
- - @color/system_on_primary_fixed
- - @color/system_primary_dark
- - @color/system_secondary_fixed
- - @color/system_surface_dark
- - @color/system_surface_variant_light
- - @color/system_tertiary_container_light
- - @color/system_tertiary_fixed
- - @color/system_primary_container_light
+ - @color/system_inverse_on_surface_light
+ - @color/system_inverse_primary_light
+ - @color/system_inverse_surface_light
- @color/system_on_background_light
- - @color/system_primary_fixed
- - @color/system_on_secondary_light
- - @color/system_on_tertiary_light
- - @color/system_surface_dim_light
- - @color/system_surface_bright_light
- @color/system_on_error_light
- - @color/system_surface_light
- - @color/system_surface_container_high_light
- - @color/system_surface_container_highest_light
+ - @color/system_on_error_container_light
+ - @color/system_on_primary_light
+ - @color/system_on_primary_container_light
+ - @color/system_on_secondary_light
+ - @color/system_on_secondary_container_light
+ - @color/system_on_surface_light
- @color/system_on_surface_variant_light
+ - @color/system_on_tertiary_light
+ - @color/system_on_tertiary_container_light
- @color/system_outline_light
- @color/system_outline_variant_light
- - @color/system_on_primary_light
- - @color/system_on_surface_light
- - @color/system_surface_container_light
+ - @color/system_palette_key_color_neutral_light
+ - @color/system_palette_key_color_neutral_variant_light
+ - @color/system_palette_key_color_primary_light
+ - @color/system_palette_key_color_secondary_light
+ - @color/system_palette_key_color_tertiary_light
- @color/system_primary_light
+ - @color/system_primary_container_light
+ - @color/system_scrim_light
- @color/system_secondary_light
+ - @color/system_secondary_container_light
+ - @color/system_shadow_light
+ - @color/system_surface_light
+ - @color/system_surface_bright_light
+ - @color/system_surface_container_light
+ - @color/system_surface_container_high_light
+ - @color/system_surface_container_highest_light
+ - @color/system_surface_container_low_light
+ - @color/system_surface_container_lowest_light
+ - @color/system_surface_dim_light
+ - @color/system_surface_tint_light
+ - @color/system_surface_variant_light
- @color/system_tertiary_light
- - @color/system_error_light
-
- - @color/system_widget_background_light
- - @color/system_clock_hour_light
- - @color/system_clock_minute_light
- - @color/system_clock_second_light
- - @color/system_theme_app_light
- - @color/system_on_theme_app_light
- - @color/system_theme_app_ring_light
- - @color/system_theme_notif_light
+ - @color/system_tertiary_container_light
+ - @color/system_text_hint_inverse_light
+ - @color/system_text_primary_inverse_light
+ - @color/system_text_primary_inverse_disable_only_light
+ - @color/system_text_secondary_and_tertiary_inverse_light
+ - @color/system_text_secondary_and_tertiary_inverse_disabled_light
+ - @color/system_on_primary_fixed
+ - @color/system_on_primary_fixed_variant
+ - @color/system_on_secondary_fixed
+ - @color/system_on_secondary_fixed_variant
+ - @color/system_on_tertiary_fixed
+ - @color/system_on_tertiary_fixed_variant
+ - @color/system_primary_fixed
+ - @color/system_primary_fixed_dim
+ - @color/system_secondary_fixed
+ - @color/system_secondary_fixed_dim
+ - @color/system_tertiary_fixed
+ - @color/system_tertiary_fixed_dim
- @color/system_brand_a_light
- @color/system_brand_b_light
- @color/system_brand_c_light
- @color/system_brand_d_light
- - @color/system_under_surface_light
- - @color/system_shade_active_light
+ - @color/system_clock_hour_light
+ - @color/system_clock_minute_light
+ - @color/system_clock_second_light
- @color/system_on_shade_active_light
- @color/system_on_shade_active_variant_light
- - @color/system_shade_inactive_light
- @color/system_on_shade_inactive_light
- @color/system_on_shade_inactive_variant_light
- - @color/system_shade_disabled_light
+ - @color/system_on_theme_app_light
- @color/system_overview_background_light
+ - @color/system_shade_active_light
+ - @color/system_shade_disabled_light
+ - @color/system_shade_inactive_light
+ - @color/system_theme_app_light
+ - @color/system_theme_app_ring_light
+ - @color/system_theme_notif_light
+ - @color/system_under_surface_light
+ - @color/system_weather_temp_light
+ - @color/system_widget_background_light
- @style/Widget.DeviceDefault.Toolbar
- - @color/system_on_secondary_fixed_variant
- - @color/system_on_tertiary_fixed_variant
- - @color/system_surface_container_lowest_light
- - @color/system_on_primary_fixed_variant
- - @color/system_on_secondary_container_light
- - @color/system_on_tertiary_container_light
- - @color/system_surface_container_low_light
- - @color/system_on_primary_container_light
- - @color/system_secondary_fixed_dim
- - @color/system_on_error_container_light
- - @color/system_on_secondary_fixed
- - @color/system_on_surface_dark
- - @color/system_tertiary_fixed_dim
- - @color/system_on_tertiary_fixed
- - @color/system_primary_fixed_dim
- - @color/system_secondary_container_light
+ - @color/system_background_light
+ - @color/system_control_activated_light
+ - @color/system_control_highlight_light
+ - @color/system_control_normal_light
+ - @color/system_error_light
- @color/system_error_container_light
- - @color/system_on_primary_fixed
- - @color/system_primary_dark
- - @color/system_secondary_fixed
- - @color/system_surface_dark
- - @color/system_surface_variant_light
- - @color/system_tertiary_container_light
- - @color/system_tertiary_fixed
- - @color/system_primary_container_light
+ - @color/system_inverse_on_surface_light
+ - @color/system_inverse_primary_light
+ - @color/system_inverse_surface_light
- @color/system_on_background_light
- - @color/system_primary_fixed
- - @color/system_on_secondary_light
- - @color/system_on_tertiary_light
- - @color/system_surface_dim_light
- - @color/system_surface_bright_light
- @color/system_on_error_light
- - @color/system_surface_light
- - @color/system_surface_container_high_light
- - @color/system_surface_container_highest_light
+ - @color/system_on_error_container_light
+ - @color/system_on_primary_light
+ - @color/system_on_primary_container_light
+ - @color/system_on_secondary_light
+ - @color/system_on_secondary_container_light
+ - @color/system_on_surface_light
- @color/system_on_surface_variant_light
+ - @color/system_on_tertiary_light
+ - @color/system_on_tertiary_container_light
- @color/system_outline_light
- @color/system_outline_variant_light
- - @color/system_on_primary_light
- - @color/system_on_surface_light
- - @color/system_surface_container_light
+ - @color/system_palette_key_color_neutral_light
+ - @color/system_palette_key_color_neutral_variant_light
+ - @color/system_palette_key_color_primary_light
+ - @color/system_palette_key_color_secondary_light
+ - @color/system_palette_key_color_tertiary_light
- @color/system_primary_light
+ - @color/system_primary_container_light
+ - @color/system_scrim_light
- @color/system_secondary_light
+ - @color/system_secondary_container_light
+ - @color/system_shadow_light
+ - @color/system_surface_light
+ - @color/system_surface_bright_light
+ - @color/system_surface_container_light
+ - @color/system_surface_container_high_light
+ - @color/system_surface_container_highest_light
+ - @color/system_surface_container_low_light
+ - @color/system_surface_container_lowest_light
+ - @color/system_surface_dim_light
+ - @color/system_surface_tint_light
+ - @color/system_surface_variant_light
- @color/system_tertiary_light
- - @color/system_error_light
-
- - @color/system_widget_background_light
- - @color/system_clock_hour_light
- - @color/system_clock_minute_light
- - @color/system_clock_second_light
- - @color/system_theme_app_light
- - @color/system_on_theme_app_light
- - @color/system_theme_app_ring_light
- - @color/system_theme_notif_light
+ - @color/system_tertiary_container_light
+ - @color/system_text_hint_inverse_light
+ - @color/system_text_primary_inverse_light
+ - @color/system_text_primary_inverse_disable_only_light
+ - @color/system_text_secondary_and_tertiary_inverse_light
+ - @color/system_text_secondary_and_tertiary_inverse_disabled_light
+ - @color/system_on_primary_fixed
+ - @color/system_on_primary_fixed_variant
+ - @color/system_on_secondary_fixed
+ - @color/system_on_secondary_fixed_variant
+ - @color/system_on_tertiary_fixed
+ - @color/system_on_tertiary_fixed_variant
+ - @color/system_primary_fixed
+ - @color/system_primary_fixed_dim
+ - @color/system_secondary_fixed
+ - @color/system_secondary_fixed_dim
+ - @color/system_tertiary_fixed
+ - @color/system_tertiary_fixed_dim
- @color/system_brand_a_light
- @color/system_brand_b_light
- @color/system_brand_c_light
- @color/system_brand_d_light
- - @color/system_under_surface_light
- - @color/system_shade_active_light
+ - @color/system_clock_hour_light
+ - @color/system_clock_minute_light
+ - @color/system_clock_second_light
- @color/system_on_shade_active_light
- @color/system_on_shade_active_variant_light
- - @color/system_shade_inactive_light
- @color/system_on_shade_inactive_light
- @color/system_on_shade_inactive_variant_light
- - @color/system_shade_disabled_light
+ - @color/system_on_theme_app_light
- @color/system_overview_background_light
+ - @color/system_shade_active_light
+ - @color/system_shade_disabled_light
+ - @color/system_shade_inactive_light
+ - @color/system_theme_app_light
+ - @color/system_theme_app_ring_light
+ - @color/system_theme_notif_light
+ - @color/system_under_surface_light
+ - @color/system_weather_temp_light
+ - @color/system_widget_background_light
@@ -3918,73 +4428,90 @@ easier.
- @color/foreground_device_default_light
- @color/foreground_device_default_dark
- - @color/system_on_secondary_fixed_variant
- - @color/system_on_tertiary_fixed_variant
- - @color/system_surface_container_lowest_light
- - @color/system_on_primary_fixed_variant
- - @color/system_on_secondary_container_light
- - @color/system_on_tertiary_container_light
- - @color/system_surface_container_low_light
- - @color/system_on_primary_container_light
- - @color/system_secondary_fixed_dim
- - @color/system_on_error_container_light
- - @color/system_on_secondary_fixed
- - @color/system_on_surface_dark
- - @color/system_tertiary_fixed_dim
- - @color/system_on_tertiary_fixed
- - @color/system_primary_fixed_dim
- - @color/system_secondary_container_light
+ - @color/system_background_light
+ - @color/system_control_activated_light
+ - @color/system_control_highlight_light
+ - @color/system_control_normal_light
+ - @color/system_error_light
- @color/system_error_container_light
- - @color/system_on_primary_fixed
- - @color/system_primary_dark
- - @color/system_secondary_fixed
- - @color/system_surface_dark
- - @color/system_surface_variant_light
- - @color/system_tertiary_container_light
- - @color/system_tertiary_fixed
- - @color/system_primary_container_light
+ - @color/system_inverse_on_surface_light
+ - @color/system_inverse_primary_light
+ - @color/system_inverse_surface_light
- @color/system_on_background_light
- - @color/system_primary_fixed
- - @color/system_on_secondary_light
- - @color/system_on_tertiary_light
- - @color/system_surface_dim_light
- - @color/system_surface_bright_light
- @color/system_on_error_light
- - @color/system_surface_light
- - @color/system_surface_container_high_light
- - @color/system_surface_container_highest_light
+ - @color/system_on_error_container_light
+ - @color/system_on_primary_light
+ - @color/system_on_primary_container_light
+ - @color/system_on_secondary_light
+ - @color/system_on_secondary_container_light
+ - @color/system_on_surface_light
- @color/system_on_surface_variant_light
+ - @color/system_on_tertiary_light
+ - @color/system_on_tertiary_container_light
- @color/system_outline_light
- @color/system_outline_variant_light
- - @color/system_on_primary_light
- - @color/system_on_surface_light
- - @color/system_surface_container_light
+ - @color/system_palette_key_color_neutral_light
+ - @color/system_palette_key_color_neutral_variant_light
+ - @color/system_palette_key_color_primary_light
+ - @color/system_palette_key_color_secondary_light
+ - @color/system_palette_key_color_tertiary_light
- @color/system_primary_light
+ - @color/system_primary_container_light
+ - @color/system_scrim_light
- @color/system_secondary_light
+ - @color/system_secondary_container_light
+ - @color/system_shadow_light
+ - @color/system_surface_light
+ - @color/system_surface_bright_light
+ - @color/system_surface_container_light
+ - @color/system_surface_container_high_light
+ - @color/system_surface_container_highest_light
+ - @color/system_surface_container_low_light
+ - @color/system_surface_container_lowest_light
+ - @color/system_surface_dim_light
+ - @color/system_surface_tint_light
+ - @color/system_surface_variant_light
- @color/system_tertiary_light
- - @color/system_error_light
-
- - @color/system_widget_background_light
+ - @color/system_tertiary_container_light
+ - @color/system_text_hint_inverse_light
+ - @color/system_text_primary_inverse_light
+ - @color/system_text_primary_inverse_disable_only_light
+ - @color/system_text_secondary_and_tertiary_inverse_light
+ - @color/system_text_secondary_and_tertiary_inverse_disabled_light
+ - @color/system_on_primary_fixed
+ - @color/system_on_primary_fixed_variant
+ - @color/system_on_secondary_fixed
+ - @color/system_on_secondary_fixed_variant
+ - @color/system_on_tertiary_fixed
+ - @color/system_on_tertiary_fixed_variant
+ - @color/system_primary_fixed
+ - @color/system_primary_fixed_dim
+ - @color/system_secondary_fixed
+ - @color/system_secondary_fixed_dim
+ - @color/system_tertiary_fixed
+ - @color/system_tertiary_fixed_dim
+ - @color/system_brand_a_light
+ - @color/system_brand_b_light
+ - @color/system_brand_c_light
+ - @color/system_brand_d_light
- @color/system_clock_hour_light
- @color/system_clock_minute_light
- @color/system_clock_second_light
- - @color/system_theme_app_light
- - @color/system_on_theme_app_light
- - @color/system_theme_app_ring_light
- - @color/system_theme_notif_light
- - @color/system_brand_a_light
- - @color/system_brand_b_light
- - @color/system_brand_c_light
- - @color/system_brand_d_light
- - @color/system_under_surface_light
- - @color/system_shade_active_light
- @color/system_on_shade_active_light
- @color/system_on_shade_active_variant_light
- - @color/system_shade_inactive_light
- @color/system_on_shade_inactive_light
- @color/system_on_shade_inactive_variant_light
- - @color/system_shade_disabled_light
+ - @color/system_on_theme_app_light
- @color/system_overview_background_light
+ - @color/system_shade_active_light
+ - @color/system_shade_disabled_light
+ - @color/system_shade_inactive_light
+ - @color/system_theme_app_light
+ - @color/system_theme_app_ring_light
+ - @color/system_theme_notif_light
+ - @color/system_under_surface_light
+ - @color/system_weather_temp_light
+ - @color/system_widget_background_light
@@ -4019,73 +4546,90 @@ easier.
- @color/foreground_device_default_light
- @color/foreground_device_default_dark
- - @color/system_on_secondary_fixed_variant
- - @color/system_on_tertiary_fixed_variant
- - @color/system_surface_container_lowest_light
- - @color/system_on_primary_fixed_variant
- - @color/system_on_secondary_container_light
- - @color/system_on_tertiary_container_light
- - @color/system_surface_container_low_light
- - @color/system_on_primary_container_light
- - @color/system_secondary_fixed_dim
- - @color/system_on_error_container_light
- - @color/system_on_secondary_fixed
- - @color/system_on_surface_dark
- - @color/system_tertiary_fixed_dim
- - @color/system_on_tertiary_fixed
- - @color/system_primary_fixed_dim
- - @color/system_secondary_container_light
+ - @color/system_background_light
+ - @color/system_control_activated_light
+ - @color/system_control_highlight_light
+ - @color/system_control_normal_light
+ - @color/system_error_light
- @color/system_error_container_light
- - @color/system_on_primary_fixed
- - @color/system_primary_dark
- - @color/system_secondary_fixed
- - @color/system_surface_dark
- - @color/system_surface_variant_light
- - @color/system_tertiary_container_light
- - @color/system_tertiary_fixed
- - @color/system_primary_container_light
+ - @color/system_inverse_on_surface_light
+ - @color/system_inverse_primary_light
+ - @color/system_inverse_surface_light
- @color/system_on_background_light
- - @color/system_primary_fixed
- - @color/system_on_secondary_light
- - @color/system_on_tertiary_light
- - @color/system_surface_dim_light
- - @color/system_surface_bright_light
- @color/system_on_error_light
- - @color/system_surface_light
- - @color/system_surface_container_high_light
- - @color/system_surface_container_highest_light
+ - @color/system_on_error_container_light
+ - @color/system_on_primary_light
+ - @color/system_on_primary_container_light
+ - @color/system_on_secondary_light
+ - @color/system_on_secondary_container_light
+ - @color/system_on_surface_light
- @color/system_on_surface_variant_light
+ - @color/system_on_tertiary_light
+ - @color/system_on_tertiary_container_light
- @color/system_outline_light
- @color/system_outline_variant_light
- - @color/system_on_primary_light
- - @color/system_on_surface_light
- - @color/system_surface_container_light
+ - @color/system_palette_key_color_neutral_light
+ - @color/system_palette_key_color_neutral_variant_light
+ - @color/system_palette_key_color_primary_light
+ - @color/system_palette_key_color_secondary_light
+ - @color/system_palette_key_color_tertiary_light
- @color/system_primary_light
+ - @color/system_primary_container_light
+ - @color/system_scrim_light
- @color/system_secondary_light
+ - @color/system_secondary_container_light
+ - @color/system_shadow_light
+ - @color/system_surface_light
+ - @color/system_surface_bright_light
+ - @color/system_surface_container_light
+ - @color/system_surface_container_high_light
+ - @color/system_surface_container_highest_light
+ - @color/system_surface_container_low_light
+ - @color/system_surface_container_lowest_light
+ - @color/system_surface_dim_light
+ - @color/system_surface_tint_light
+ - @color/system_surface_variant_light
- @color/system_tertiary_light
- - @color/system_error_light
-
- - @color/system_widget_background_light
- - @color/system_clock_hour_light
- - @color/system_clock_minute_light
- - @color/system_clock_second_light
- - @color/system_theme_app_light
- - @color/system_on_theme_app_light
- - @color/system_theme_app_ring_light
- - @color/system_theme_notif_light
+ - @color/system_tertiary_container_light
+ - @color/system_text_hint_inverse_light
+ - @color/system_text_primary_inverse_light
+ - @color/system_text_primary_inverse_disable_only_light
+ - @color/system_text_secondary_and_tertiary_inverse_light
+ - @color/system_text_secondary_and_tertiary_inverse_disabled_light
+ - @color/system_on_primary_fixed
+ - @color/system_on_primary_fixed_variant
+ - @color/system_on_secondary_fixed
+ - @color/system_on_secondary_fixed_variant
+ - @color/system_on_tertiary_fixed
+ - @color/system_on_tertiary_fixed_variant
+ - @color/system_primary_fixed
+ - @color/system_primary_fixed_dim
+ - @color/system_secondary_fixed
+ - @color/system_secondary_fixed_dim
+ - @color/system_tertiary_fixed
+ - @color/system_tertiary_fixed_dim
- @color/system_brand_a_light
- @color/system_brand_b_light
- @color/system_brand_c_light
- @color/system_brand_d_light
- - @color/system_under_surface_light
- - @color/system_shade_active_light
+ - @color/system_clock_hour_light
+ - @color/system_clock_minute_light
+ - @color/system_clock_second_light
- @color/system_on_shade_active_light
- @color/system_on_shade_active_variant_light
- - @color/system_shade_inactive_light
- @color/system_on_shade_inactive_light
- @color/system_on_shade_inactive_variant_light
- - @color/system_shade_disabled_light
+ - @color/system_on_theme_app_light
- @color/system_overview_background_light
+ - @color/system_shade_active_light
+ - @color/system_shade_disabled_light
+ - @color/system_shade_inactive_light
+ - @color/system_theme_app_light
+ - @color/system_theme_app_ring_light
+ - @color/system_theme_notif_light
+ - @color/system_under_surface_light
+ - @color/system_weather_temp_light
+ - @color/system_widget_background_light
- @style/Widget.DeviceDefault.Toolbar
- - @color/system_on_secondary_fixed_variant
- - @color/system_on_tertiary_fixed_variant
- - @color/system_surface_container_lowest_light
- - @color/system_on_primary_fixed_variant
- - @color/system_on_secondary_container_light
- - @color/system_on_tertiary_container_light
- - @color/system_surface_container_low_light
- - @color/system_on_primary_container_light
- - @color/system_secondary_fixed_dim
- - @color/system_on_error_container_light
- - @color/system_on_secondary_fixed
- - @color/system_on_surface_dark
- - @color/system_tertiary_fixed_dim
- - @color/system_on_tertiary_fixed
- - @color/system_primary_fixed_dim
- - @color/system_secondary_container_light
+ - @color/system_background_light
+ - @color/system_control_activated_light
+ - @color/system_control_highlight_light
+ - @color/system_control_normal_light
+ - @color/system_error_light
- @color/system_error_container_light
- - @color/system_on_primary_fixed
- - @color/system_primary_dark
- - @color/system_secondary_fixed
- - @color/system_surface_dark
- - @color/system_surface_variant_light
- - @color/system_tertiary_container_light
- - @color/system_tertiary_fixed
- - @color/system_primary_container_light
+ - @color/system_inverse_on_surface_light
+ - @color/system_inverse_primary_light
+ - @color/system_inverse_surface_light
- @color/system_on_background_light
- - @color/system_primary_fixed
- - @color/system_on_secondary_light
- - @color/system_on_tertiary_light
- - @color/system_surface_dim_light
- - @color/system_surface_bright_light
- @color/system_on_error_light
- - @color/system_surface_light
- - @color/system_surface_container_high_light
- - @color/system_surface_container_highest_light
+ - @color/system_on_error_container_light
+ - @color/system_on_primary_light
+ - @color/system_on_primary_container_light
+ - @color/system_on_secondary_light
+ - @color/system_on_secondary_container_light
+ - @color/system_on_surface_light
- @color/system_on_surface_variant_light
+ - @color/system_on_tertiary_light
+ - @color/system_on_tertiary_container_light
- @color/system_outline_light
- @color/system_outline_variant_light
- - @color/system_on_primary_light
- - @color/system_on_surface_light
- - @color/system_surface_container_light
+ - @color/system_palette_key_color_neutral_light
+ - @color/system_palette_key_color_neutral_variant_light
+ - @color/system_palette_key_color_primary_light
+ - @color/system_palette_key_color_secondary_light
+ - @color/system_palette_key_color_tertiary_light
- @color/system_primary_light
+ - @color/system_primary_container_light
+ - @color/system_scrim_light
- @color/system_secondary_light
+ - @color/system_secondary_container_light
+ - @color/system_shadow_light
+ - @color/system_surface_light
+ - @color/system_surface_bright_light
+ - @color/system_surface_container_light
+ - @color/system_surface_container_high_light
+ - @color/system_surface_container_highest_light
+ - @color/system_surface_container_low_light
+ - @color/system_surface_container_lowest_light
+ - @color/system_surface_dim_light
+ - @color/system_surface_tint_light
+ - @color/system_surface_variant_light
- @color/system_tertiary_light
- - @color/system_error_light
-
- - @color/system_widget_background_light
- - @color/system_clock_hour_light
- - @color/system_clock_minute_light
- - @color/system_clock_second_light
- - @color/system_theme_app_light
- - @color/system_on_theme_app_light
- - @color/system_theme_app_ring_light
- - @color/system_theme_notif_light
+ - @color/system_tertiary_container_light
+ - @color/system_text_hint_inverse_light
+ - @color/system_text_primary_inverse_light
+ - @color/system_text_primary_inverse_disable_only_light
+ - @color/system_text_secondary_and_tertiary_inverse_light
+ - @color/system_text_secondary_and_tertiary_inverse_disabled_light
+ - @color/system_on_primary_fixed
+ - @color/system_on_primary_fixed_variant
+ - @color/system_on_secondary_fixed
+ - @color/system_on_secondary_fixed_variant
+ - @color/system_on_tertiary_fixed
+ - @color/system_on_tertiary_fixed_variant
+ - @color/system_primary_fixed
+ - @color/system_primary_fixed_dim
+ - @color/system_secondary_fixed
+ - @color/system_secondary_fixed_dim
+ - @color/system_tertiary_fixed
+ - @color/system_tertiary_fixed_dim
- @color/system_brand_a_light
- @color/system_brand_b_light
- @color/system_brand_c_light
- @color/system_brand_d_light
- - @color/system_under_surface_light
- - @color/system_shade_active_light
+ - @color/system_clock_hour_light
+ - @color/system_clock_minute_light
+ - @color/system_clock_second_light
- @color/system_on_shade_active_light
- @color/system_on_shade_active_variant_light
- - @color/system_shade_inactive_light
- @color/system_on_shade_inactive_light
- @color/system_on_shade_inactive_variant_light
- - @color/system_shade_disabled_light
+ - @color/system_on_theme_app_light
- @color/system_overview_background_light
+ - @color/system_shade_active_light
+ - @color/system_shade_disabled_light
+ - @color/system_shade_inactive_light
+ - @color/system_theme_app_light
+ - @color/system_theme_app_ring_light
+ - @color/system_theme_notif_light
+ - @color/system_under_surface_light
+ - @color/system_weather_temp_light
+ - @color/system_widget_background_light
- @style/Widget.DeviceDefault.Toolbar
- - @color/system_on_secondary_fixed_variant
- - @color/system_on_tertiary_fixed_variant
- - @color/system_surface_container_lowest_light
- - @color/system_on_primary_fixed_variant
- - @color/system_on_secondary_container_light
- - @color/system_on_tertiary_container_light
- - @color/system_surface_container_low_light
- - @color/system_on_primary_container_light
- - @color/system_secondary_fixed_dim
- - @color/system_on_error_container_light
- - @color/system_on_secondary_fixed
- - @color/system_on_surface_dark
- - @color/system_tertiary_fixed_dim
- - @color/system_on_tertiary_fixed
- - @color/system_primary_fixed_dim
- - @color/system_secondary_container_light
+ - @color/system_background_light
+ - @color/system_control_activated_light
+ - @color/system_control_highlight_light
+ - @color/system_control_normal_light
+ - @color/system_error_light
- @color/system_error_container_light
- - @color/system_on_primary_fixed
- - @color/system_primary_dark
- - @color/system_secondary_fixed
- - @color/system_surface_dark
- - @color/system_surface_variant_light
- - @color/system_tertiary_container_light
- - @color/system_tertiary_fixed
- - @color/system_primary_container_light
+ - @color/system_inverse_on_surface_light
+ - @color/system_inverse_primary_light
+ - @color/system_inverse_surface_light
- @color/system_on_background_light
- - @color/system_primary_fixed
- - @color/system_on_secondary_light
- - @color/system_on_tertiary_light
- - @color/system_surface_dim_light
- - @color/system_surface_bright_light
- @color/system_on_error_light
- - @color/system_surface_light
- - @color/system_surface_container_high_light
- - @color/system_surface_container_highest_light
+ - @color/system_on_error_container_light
+ - @color/system_on_primary_light
+ - @color/system_on_primary_container_light
+ - @color/system_on_secondary_light
+ - @color/system_on_secondary_container_light
+ - @color/system_on_surface_light
- @color/system_on_surface_variant_light
+ - @color/system_on_tertiary_light
+ - @color/system_on_tertiary_container_light
- @color/system_outline_light
- @color/system_outline_variant_light
- - @color/system_on_primary_light
- - @color/system_on_surface_light
- - @color/system_surface_container_light
+ - @color/system_palette_key_color_neutral_light
+ - @color/system_palette_key_color_neutral_variant_light
+ - @color/system_palette_key_color_primary_light
+ - @color/system_palette_key_color_secondary_light
+ - @color/system_palette_key_color_tertiary_light
- @color/system_primary_light
+ - @color/system_primary_container_light
+ - @color/system_scrim_light
- @color/system_secondary_light
+ - @color/system_secondary_container_light
+ - @color/system_shadow_light
+ - @color/system_surface_light
+ - @color/system_surface_bright_light
+ - @color/system_surface_container_light
+ - @color/system_surface_container_high_light
+ - @color/system_surface_container_highest_light
+ - @color/system_surface_container_low_light
+ - @color/system_surface_container_lowest_light
+ - @color/system_surface_dim_light
+ - @color/system_surface_tint_light
+ - @color/system_surface_variant_light
- @color/system_tertiary_light
- - @color/system_error_light
-
- - @color/system_widget_background_light
- - @color/system_clock_hour_light
- - @color/system_clock_minute_light
- - @color/system_clock_second_light
- - @color/system_theme_app_light
- - @color/system_on_theme_app_light
- - @color/system_theme_app_ring_light
- - @color/system_theme_notif_light
+ - @color/system_tertiary_container_light
+ - @color/system_text_hint_inverse_light
+ - @color/system_text_primary_inverse_light
+ - @color/system_text_primary_inverse_disable_only_light
+ - @color/system_text_secondary_and_tertiary_inverse_light
+ - @color/system_text_secondary_and_tertiary_inverse_disabled_light
+ - @color/system_on_primary_fixed
+ - @color/system_on_primary_fixed_variant
+ - @color/system_on_secondary_fixed
+ - @color/system_on_secondary_fixed_variant
+ - @color/system_on_tertiary_fixed
+ - @color/system_on_tertiary_fixed_variant
+ - @color/system_primary_fixed
+ - @color/system_primary_fixed_dim
+ - @color/system_secondary_fixed
+ - @color/system_secondary_fixed_dim
+ - @color/system_tertiary_fixed
+ - @color/system_tertiary_fixed_dim
- @color/system_brand_a_light
- @color/system_brand_b_light
- @color/system_brand_c_light
- @color/system_brand_d_light
- - @color/system_under_surface_light
- - @color/system_shade_active_light
+ - @color/system_clock_hour_light
+ - @color/system_clock_minute_light
+ - @color/system_clock_second_light
- @color/system_on_shade_active_light
- @color/system_on_shade_active_variant_light
- - @color/system_shade_inactive_light
- @color/system_on_shade_inactive_light
- @color/system_on_shade_inactive_variant_light
- - @color/system_shade_disabled_light
+ - @color/system_on_theme_app_light
- @color/system_overview_background_light
+ - @color/system_shade_active_light
+ - @color/system_shade_disabled_light
+ - @color/system_shade_inactive_light
+ - @color/system_theme_app_light
+ - @color/system_theme_app_ring_light
+ - @color/system_theme_notif_light
+ - @color/system_under_surface_light
+ - @color/system_weather_temp_light
+ - @color/system_widget_background_light
@@ -4379,73 +4957,90 @@ easier.
- @style/Widget.DeviceDefault.Toolbar
- - @color/system_on_secondary_fixed_variant
- - @color/system_on_tertiary_fixed_variant
- - @color/system_surface_container_lowest_light
- - @color/system_on_primary_fixed_variant
- - @color/system_on_secondary_container_light
- - @color/system_on_tertiary_container_light
- - @color/system_surface_container_low_light
- - @color/system_on_primary_container_light
- - @color/system_secondary_fixed_dim
- - @color/system_on_error_container_light
- - @color/system_on_secondary_fixed
- - @color/system_on_surface_dark
- - @color/system_tertiary_fixed_dim
- - @color/system_on_tertiary_fixed
- - @color/system_primary_fixed_dim
- - @color/system_secondary_container_light
+ - @color/system_background_light
+ - @color/system_control_activated_light
+ - @color/system_control_highlight_light
+ - @color/system_control_normal_light
+ - @color/system_error_light
- @color/system_error_container_light
- - @color/system_on_primary_fixed
- - @color/system_primary_dark
- - @color/system_secondary_fixed
- - @color/system_surface_dark
- - @color/system_surface_variant_light
- - @color/system_tertiary_container_light
- - @color/system_tertiary_fixed
- - @color/system_primary_container_light
+ - @color/system_inverse_on_surface_light
+ - @color/system_inverse_primary_light
+ - @color/system_inverse_surface_light
- @color/system_on_background_light
- - @color/system_primary_fixed
- - @color/system_on_secondary_light
- - @color/system_on_tertiary_light
- - @color/system_surface_dim_light
- - @color/system_surface_bright_light
- @color/system_on_error_light
- - @color/system_surface_light
- - @color/system_surface_container_high_light
- - @color/system_surface_container_highest_light
+ - @color/system_on_error_container_light
+ - @color/system_on_primary_light
+ - @color/system_on_primary_container_light
+ - @color/system_on_secondary_light
+ - @color/system_on_secondary_container_light
+ - @color/system_on_surface_light
- @color/system_on_surface_variant_light
+ - @color/system_on_tertiary_light
+ - @color/system_on_tertiary_container_light
- @color/system_outline_light
- @color/system_outline_variant_light
- - @color/system_on_primary_light
- - @color/system_on_surface_light
- - @color/system_surface_container_light
+ - @color/system_palette_key_color_neutral_light
+ - @color/system_palette_key_color_neutral_variant_light
+ - @color/system_palette_key_color_primary_light
+ - @color/system_palette_key_color_secondary_light
+ - @color/system_palette_key_color_tertiary_light
- @color/system_primary_light
+ - @color/system_primary_container_light
+ - @color/system_scrim_light
- @color/system_secondary_light
+ - @color/system_secondary_container_light
+ - @color/system_shadow_light
+ - @color/system_surface_light
+ - @color/system_surface_bright_light
+ - @color/system_surface_container_light
+ - @color/system_surface_container_high_light
+ - @color/system_surface_container_highest_light
+ - @color/system_surface_container_low_light
+ - @color/system_surface_container_lowest_light
+ - @color/system_surface_dim_light
+ - @color/system_surface_tint_light
+ - @color/system_surface_variant_light
- @color/system_tertiary_light
- - @color/system_error_light
-
- - @color/system_widget_background_light
- - @color/system_clock_hour_light
- - @color/system_clock_minute_light
- - @color/system_clock_second_light
- - @color/system_theme_app_light
- - @color/system_on_theme_app_light
- - @color/system_theme_app_ring_light
- - @color/system_theme_notif_light
+ - @color/system_tertiary_container_light
+ - @color/system_text_hint_inverse_light
+ - @color/system_text_primary_inverse_light
+ - @color/system_text_primary_inverse_disable_only_light
+ - @color/system_text_secondary_and_tertiary_inverse_light
+ - @color/system_text_secondary_and_tertiary_inverse_disabled_light
+ - @color/system_on_primary_fixed
+ - @color/system_on_primary_fixed_variant
+ - @color/system_on_secondary_fixed
+ - @color/system_on_secondary_fixed_variant
+ - @color/system_on_tertiary_fixed
+ - @color/system_on_tertiary_fixed_variant
+ - @color/system_primary_fixed
+ - @color/system_primary_fixed_dim
+ - @color/system_secondary_fixed
+ - @color/system_secondary_fixed_dim
+ - @color/system_tertiary_fixed
+ - @color/system_tertiary_fixed_dim
- @color/system_brand_a_light
- @color/system_brand_b_light
- @color/system_brand_c_light
- @color/system_brand_d_light
- - @color/system_under_surface_light
- - @color/system_shade_active_light
+ - @color/system_clock_hour_light
+ - @color/system_clock_minute_light
+ - @color/system_clock_second_light
- @color/system_on_shade_active_light
- @color/system_on_shade_active_variant_light
- - @color/system_shade_inactive_light
- @color/system_on_shade_inactive_light
- @color/system_on_shade_inactive_variant_light
- - @color/system_shade_disabled_light
+ - @color/system_on_theme_app_light
- @color/system_overview_background_light
+ - @color/system_shade_active_light
+ - @color/system_shade_disabled_light
+ - @color/system_shade_inactive_light
+ - @color/system_theme_app_light
+ - @color/system_theme_app_ring_light
+ - @color/system_theme_notif_light
+ - @color/system_under_surface_light
+ - @color/system_weather_temp_light
+ - @color/system_widget_background_light
- @style/Widget.DeviceDefault.Toolbar
- - @color/system_on_secondary_fixed_variant
- - @color/system_on_tertiary_fixed_variant
- - @color/system_surface_container_lowest_light
- - @color/system_on_primary_fixed_variant
- - @color/system_on_secondary_container_light
- - @color/system_on_tertiary_container_light
- - @color/system_surface_container_low_light
- - @color/system_on_primary_container_light
- - @color/system_secondary_fixed_dim
- - @color/system_on_error_container_light
- - @color/system_on_secondary_fixed
- - @color/system_on_surface_dark
- - @color/system_tertiary_fixed_dim
- - @color/system_on_tertiary_fixed
- - @color/system_primary_fixed_dim
- - @color/system_secondary_container_light
+ - @color/system_background_light
+ - @color/system_control_activated_light
+ - @color/system_control_highlight_light
+ - @color/system_control_normal_light
+ - @color/system_error_light
- @color/system_error_container_light
- - @color/system_on_primary_fixed
- - @color/system_primary_dark
- - @color/system_secondary_fixed
- - @color/system_surface_dark
- - @color/system_surface_variant_light
- - @color/system_tertiary_container_light
- - @color/system_tertiary_fixed
- - @color/system_primary_container_light
+ - @color/system_inverse_on_surface_light
+ - @color/system_inverse_primary_light
+ - @color/system_inverse_surface_light
- @color/system_on_background_light
- - @color/system_primary_fixed
- - @color/system_on_secondary_light
- - @color/system_on_tertiary_light
- - @color/system_surface_dim_light
- - @color/system_surface_bright_light
- @color/system_on_error_light
- - @color/system_surface_light
- - @color/system_surface_container_high_light
- - @color/system_surface_container_highest_light
+ - @color/system_on_error_container_light
+ - @color/system_on_primary_light
+ - @color/system_on_primary_container_light
+ - @color/system_on_secondary_light
+ - @color/system_on_secondary_container_light
+ - @color/system_on_surface_light
- @color/system_on_surface_variant_light
+ - @color/system_on_tertiary_light
+ - @color/system_on_tertiary_container_light
- @color/system_outline_light
- @color/system_outline_variant_light
- - @color/system_on_primary_light
- - @color/system_on_surface_light
- - @color/system_surface_container_light
+ - @color/system_palette_key_color_neutral_light
+ - @color/system_palette_key_color_neutral_variant_light
+ - @color/system_palette_key_color_primary_light
+ - @color/system_palette_key_color_secondary_light
+ - @color/system_palette_key_color_tertiary_light
- @color/system_primary_light
+ - @color/system_primary_container_light
+ - @color/system_scrim_light
- @color/system_secondary_light
+ - @color/system_secondary_container_light
+ - @color/system_shadow_light
+ - @color/system_surface_light
+ - @color/system_surface_bright_light
+ - @color/system_surface_container_light
+ - @color/system_surface_container_high_light
+ - @color/system_surface_container_highest_light
+ - @color/system_surface_container_low_light
+ - @color/system_surface_container_lowest_light
+ - @color/system_surface_dim_light
+ - @color/system_surface_tint_light
+ - @color/system_surface_variant_light
- @color/system_tertiary_light
- - @color/system_error_light
-
- - @color/system_widget_background_light
- - @color/system_clock_hour_light
- - @color/system_clock_minute_light
- - @color/system_clock_second_light
- - @color/system_theme_app_light
- - @color/system_on_theme_app_light
- - @color/system_theme_app_ring_light
- - @color/system_theme_notif_light
+ - @color/system_tertiary_container_light
+ - @color/system_text_hint_inverse_light
+ - @color/system_text_primary_inverse_light
+ - @color/system_text_primary_inverse_disable_only_light
+ - @color/system_text_secondary_and_tertiary_inverse_light
+ - @color/system_text_secondary_and_tertiary_inverse_disabled_light
+ - @color/system_on_primary_fixed
+ - @color/system_on_primary_fixed_variant
+ - @color/system_on_secondary_fixed
+ - @color/system_on_secondary_fixed_variant
+ - @color/system_on_tertiary_fixed
+ - @color/system_on_tertiary_fixed_variant
+ - @color/system_primary_fixed
+ - @color/system_primary_fixed_dim
+ - @color/system_secondary_fixed
+ - @color/system_secondary_fixed_dim
+ - @color/system_tertiary_fixed
+ - @color/system_tertiary_fixed_dim
- @color/system_brand_a_light
- @color/system_brand_b_light
- @color/system_brand_c_light
- @color/system_brand_d_light
- - @color/system_under_surface_light
- - @color/system_shade_active_light
+ - @color/system_clock_hour_light
+ - @color/system_clock_minute_light
+ - @color/system_clock_second_light
- @color/system_on_shade_active_light
- @color/system_on_shade_active_variant_light
- - @color/system_shade_inactive_light
- @color/system_on_shade_inactive_light
- @color/system_on_shade_inactive_variant_light
- - @color/system_shade_disabled_light
+ - @color/system_on_theme_app_light
- @color/system_overview_background_light
+ - @color/system_shade_active_light
+ - @color/system_shade_disabled_light
+ - @color/system_shade_inactive_light
+ - @color/system_theme_app_light
+ - @color/system_theme_app_ring_light
+ - @color/system_theme_notif_light
+ - @color/system_under_surface_light
+ - @color/system_weather_temp_light
+ - @color/system_widget_background_light
@@ -4731,73 +5360,90 @@ easier.
- @style/Widget.DeviceDefault.Toolbar
- - @color/system_on_secondary_fixed_variant
- - @color/system_on_tertiary_fixed_variant
- - @color/system_surface_container_lowest_light
- - @color/system_on_primary_fixed_variant
- - @color/system_on_secondary_container_light
- - @color/system_on_tertiary_container_light
- - @color/system_surface_container_low_light
- - @color/system_on_primary_container_light
- - @color/system_secondary_fixed_dim
- - @color/system_on_error_container_light
- - @color/system_on_secondary_fixed
- - @color/system_on_surface_dark
- - @color/system_tertiary_fixed_dim
- - @color/system_on_tertiary_fixed
- - @color/system_primary_fixed_dim
- - @color/system_secondary_container_light
+ - @color/system_background_light
+ - @color/system_control_activated_light
+ - @color/system_control_highlight_light
+ - @color/system_control_normal_light
+ - @color/system_error_light
- @color/system_error_container_light
- - @color/system_on_primary_fixed
- - @color/system_primary_dark
- - @color/system_secondary_fixed
- - @color/system_surface_dark
- - @color/system_surface_variant_light
- - @color/system_tertiary_container_light
- - @color/system_tertiary_fixed
- - @color/system_primary_container_light
+ - @color/system_inverse_on_surface_light
+ - @color/system_inverse_primary_light
+ - @color/system_inverse_surface_light
- @color/system_on_background_light
- - @color/system_primary_fixed
- - @color/system_on_secondary_light
- - @color/system_on_tertiary_light
- - @color/system_surface_dim_light
- - @color/system_surface_bright_light
- @color/system_on_error_light
- - @color/system_surface_light
- - @color/system_surface_container_high_light
- - @color/system_surface_container_highest_light
+ - @color/system_on_error_container_light
+ - @color/system_on_primary_light
+ - @color/system_on_primary_container_light
+ - @color/system_on_secondary_light
+ - @color/system_on_secondary_container_light
+ - @color/system_on_surface_light
- @color/system_on_surface_variant_light
+ - @color/system_on_tertiary_light
+ - @color/system_on_tertiary_container_light
- @color/system_outline_light
- @color/system_outline_variant_light
- - @color/system_on_primary_light
- - @color/system_on_surface_light
- - @color/system_surface_container_light
+ - @color/system_palette_key_color_neutral_light
+ - @color/system_palette_key_color_neutral_variant_light
+ - @color/system_palette_key_color_primary_light
+ - @color/system_palette_key_color_secondary_light
+ - @color/system_palette_key_color_tertiary_light
- @color/system_primary_light
+ - @color/system_primary_container_light
+ - @color/system_scrim_light
- @color/system_secondary_light
+ - @color/system_secondary_container_light
+ - @color/system_shadow_light
+ - @color/system_surface_light
+ - @color/system_surface_bright_light
+ - @color/system_surface_container_light
+ - @color/system_surface_container_high_light
+ - @color/system_surface_container_highest_light
+ - @color/system_surface_container_low_light
+ - @color/system_surface_container_lowest_light
+ - @color/system_surface_dim_light
+ - @color/system_surface_tint_light
+ - @color/system_surface_variant_light
- @color/system_tertiary_light
- - @color/system_error_light
-
- - @color/system_widget_background_light
- - @color/system_clock_hour_light
- - @color/system_clock_minute_light
- - @color/system_clock_second_light
- - @color/system_theme_app_light
- - @color/system_on_theme_app_light
- - @color/system_theme_app_ring_light
- - @color/system_theme_notif_light
+ - @color/system_tertiary_container_light
+ - @color/system_text_hint_inverse_light
+ - @color/system_text_primary_inverse_light
+ - @color/system_text_primary_inverse_disable_only_light
+ - @color/system_text_secondary_and_tertiary_inverse_light
+ - @color/system_text_secondary_and_tertiary_inverse_disabled_light
+ - @color/system_on_primary_fixed
+ - @color/system_on_primary_fixed_variant
+ - @color/system_on_secondary_fixed
+ - @color/system_on_secondary_fixed_variant
+ - @color/system_on_tertiary_fixed
+ - @color/system_on_tertiary_fixed_variant
+ - @color/system_primary_fixed
+ - @color/system_primary_fixed_dim
+ - @color/system_secondary_fixed
+ - @color/system_secondary_fixed_dim
+ - @color/system_tertiary_fixed
+ - @color/system_tertiary_fixed_dim
- @color/system_brand_a_light
- @color/system_brand_b_light
- @color/system_brand_c_light
- @color/system_brand_d_light
- - @color/system_under_surface_light
- - @color/system_shade_active_light
+ - @color/system_clock_hour_light
+ - @color/system_clock_minute_light
+ - @color/system_clock_second_light
- @color/system_on_shade_active_light
- @color/system_on_shade_active_variant_light
- - @color/system_shade_inactive_light
- @color/system_on_shade_inactive_light
- @color/system_on_shade_inactive_variant_light
- - @color/system_shade_disabled_light
+ - @color/system_on_theme_app_light
- @color/system_overview_background_light
+ - @color/system_shade_active_light
+ - @color/system_shade_disabled_light
+ - @color/system_shade_inactive_light
+ - @color/system_theme_app_light
+ - @color/system_theme_app_ring_light
+ - @color/system_theme_notif_light
+ - @color/system_under_surface_light
+ - @color/system_weather_temp_light
+ - @color/system_widget_background_light
@@ -4968,74 +5631,90 @@ easier.
- @color/list_divider_color_light
- @color/list_divider_opacity_device_default_light
- - @color/system_on_secondary_fixed_variant
- - @color/system_on_tertiary_fixed_variant
- - @color/system_surface_container_lowest_light
- - @color/system_on_primary_fixed_variant
+ - @color/system_background_light
+ - @color/system_control_activated_light
+ - @color/system_control_highlight_light
+ - @color/system_control_normal_light
+ - @color/system_error_light
+ - @color/system_error_container_light
+ - @color/system_inverse_on_surface_light
+ - @color/system_inverse_primary_light
+ - @color/system_inverse_surface_light
+ - @color/system_on_background_light
+ - @color/system_on_error_light
+ - @color/system_on_error_container_light
+ - @color/system_on_primary_light
+ - @color/system_on_primary_container_light
+ - @color/system_on_secondary_light
- @color/system_on_secondary_container_light
+ - @color/system_on_surface_light
+ - @color/system_on_surface_variant_light
+ - @color/system_on_tertiary_light
- @color/system_on_tertiary_container_light
- - @color/system_surface_container_low_light
- - @color/system_on_primary_container_light
- - @color/system_secondary_fixed_dim
- - @color/system_on_error_container_light
- - @color/system_on_secondary_fixed
- - @color/system_on_surface_dark
- - @color/system_tertiary_fixed_dim
- - @color/system_on_tertiary_fixed
- - @color/system_primary_fixed_dim
- - @color/system_secondary_container_light
- - @color/system_error_container_light
- - @color/system_on_primary_fixed
- - @color/system_primary_dark
- - @color/system_secondary_fixed
- - @color/system_surface_dark
- - @color/system_surface_variant_light
- - @color/system_tertiary_container_light
- - @color/system_tertiary_fixed
- - @color/system_primary_container_light
- - @color/system_on_background_light
- - @color/system_primary_fixed
-
- - @color/system_on_secondary_light
- - @color/system_on_tertiary_light
- - @color/system_surface_dim_light
- - @color/system_surface_bright_light
- - @color/system_on_error_light
- - @color/system_surface_light
- - @color/system_surface_container_high_light
- - @color/system_surface_container_highest_light
- - @color/system_on_surface_variant_light
- @color/system_outline_light
- @color/system_outline_variant_light
- - @color/system_on_primary_light
- - @color/system_on_surface_light
- - @color/system_surface_container_light
+ - @color/system_palette_key_color_neutral_light
+ - @color/system_palette_key_color_neutral_variant_light
+ - @color/system_palette_key_color_primary_light
+ - @color/system_palette_key_color_secondary_light
+ - @color/system_palette_key_color_tertiary_light
- @color/system_primary_light
+ - @color/system_primary_container_light
+ - @color/system_scrim_light
- @color/system_secondary_light
+ - @color/system_secondary_container_light
+ - @color/system_shadow_light
+ - @color/system_surface_light
+ - @color/system_surface_bright_light
+ - @color/system_surface_container_light
+ - @color/system_surface_container_high_light
+ - @color/system_surface_container_highest_light
+ - @color/system_surface_container_low_light
+ - @color/system_surface_container_lowest_light
+ - @color/system_surface_dim_light
+ - @color/system_surface_tint_light
+ - @color/system_surface_variant_light
- @color/system_tertiary_light
- - @color/system_error_light
-
- - @color/system_widget_background_light
- - @color/system_clock_hour_light
- - @color/system_clock_minute_light
- - @color/system_clock_second_light
- - @color/system_theme_app_light
- - @color/system_on_theme_app_light
- - @color/system_theme_app_ring_light
- - @color/system_theme_notif_light
+ - @color/system_tertiary_container_light
+ - @color/system_text_hint_inverse_light
+ - @color/system_text_primary_inverse_light
+ - @color/system_text_primary_inverse_disable_only_light
+ - @color/system_text_secondary_and_tertiary_inverse_light
+ - @color/system_text_secondary_and_tertiary_inverse_disabled_light
+ - @color/system_on_primary_fixed
+ - @color/system_on_primary_fixed_variant
+ - @color/system_on_secondary_fixed
+ - @color/system_on_secondary_fixed_variant
+ - @color/system_on_tertiary_fixed
+ - @color/system_on_tertiary_fixed_variant
+ - @color/system_primary_fixed
+ - @color/system_primary_fixed_dim
+ - @color/system_secondary_fixed
+ - @color/system_secondary_fixed_dim
+ - @color/system_tertiary_fixed
+ - @color/system_tertiary_fixed_dim
- @color/system_brand_a_light
- @color/system_brand_b_light
- @color/system_brand_c_light
- @color/system_brand_d_light
- - @color/system_under_surface_light
- - @color/system_shade_active_light
+ - @color/system_clock_hour_light
+ - @color/system_clock_minute_light
+ - @color/system_clock_second_light
- @color/system_on_shade_active_light
- @color/system_on_shade_active_variant_light
- - @color/system_shade_inactive_light
- @color/system_on_shade_inactive_light
- @color/system_on_shade_inactive_variant_light
- - @color/system_shade_disabled_light
+ - @color/system_on_theme_app_light
- @color/system_overview_background_light
+ - @color/system_shade_active_light
+ - @color/system_shade_disabled_light
+ - @color/system_shade_inactive_light
+ - @color/system_theme_app_light
+ - @color/system_theme_app_ring_light
+ - @color/system_theme_notif_light
+ - @color/system_under_surface_light
+ - @color/system_weather_temp_light
+ - @color/system_widget_background_light
-
-
-
+
+
+
@@ -5792,73 +6571,90 @@ easier.
- @color/system_secondary_dark
- @color/system_tertiary_dark
- - @color/system_on_secondary_fixed_variant
- - @color/system_on_tertiary_fixed_variant
- - @color/system_surface_container_lowest_dark
- - @color/system_on_primary_fixed_variant
- - @color/system_on_secondary_container_dark
- - @color/system_on_tertiary_container_dark
- - @color/system_surface_container_low_dark
- - @color/system_on_primary_container_dark
- - @color/system_secondary_fixed_dim
- - @color/system_on_error_container_dark
- - @color/system_on_secondary_fixed
- - @color/system_on_surface_light
- - @color/system_tertiary_fixed_dim
- - @color/system_on_tertiary_fixed
- - @color/system_primary_fixed_dim
- - @color/system_secondary_container_dark
+ - @color/system_background_dark
+ - @color/system_control_activated_dark
+ - @color/system_control_highlight_dark
+ - @color/system_control_normal_dark
+ - @color/system_error_dark
- @color/system_error_container_dark
- - @color/system_on_primary_fixed
- - @color/system_primary_light
- - @color/system_secondary_fixed
- - @color/system_surface_light
- - @color/system_surface_variant_dark
- - @color/system_tertiary_container_dark
- - @color/system_tertiary_fixed
- - @color/system_primary_container_dark
+ - @color/system_inverse_on_surface_dark
+ - @color/system_inverse_primary_dark
+ - @color/system_inverse_surface_dark
- @color/system_on_background_dark
- - @color/system_primary_fixed
- - @color/system_on_secondary_dark
- - @color/system_on_tertiary_dark
- - @color/system_surface_dim_dark
- - @color/system_surface_bright_dark
- @color/system_on_error_dark
- - @color/system_surface_dark
- - @color/system_surface_container_high_dark
- - @color/system_surface_container_highest_dark
+ - @color/system_on_error_container_dark
+ - @color/system_on_primary_dark
+ - @color/system_on_primary_container_dark
+ - @color/system_on_secondary_dark
+ - @color/system_on_secondary_container_dark
+ - @color/system_on_surface_dark
- @color/system_on_surface_variant_dark
+ - @color/system_on_tertiary_dark
+ - @color/system_on_tertiary_container_dark
- @color/system_outline_dark
- @color/system_outline_variant_dark
- - @color/system_on_primary_dark
- - @color/system_on_surface_dark
- - @color/system_surface_container_dark
+ - @color/system_palette_key_color_neutral_dark
+ - @color/system_palette_key_color_neutral_variant_dark
+ - @color/system_palette_key_color_primary_dark
+ - @color/system_palette_key_color_secondary_dark
+ - @color/system_palette_key_color_tertiary_dark
- @color/system_primary_dark
+ - @color/system_primary_container_dark
+ - @color/system_scrim_dark
- @color/system_secondary_dark
+ - @color/system_secondary_container_dark
+ - @color/system_shadow_dark
+ - @color/system_surface_dark
+ - @color/system_surface_bright_dark
+ - @color/system_surface_container_dark
+ - @color/system_surface_container_high_dark
+ - @color/system_surface_container_highest_dark
+ - @color/system_surface_container_low_dark
+ - @color/system_surface_container_lowest_dark
+ - @color/system_surface_dim_dark
+ - @color/system_surface_tint_dark
+ - @color/system_surface_variant_dark
- @color/system_tertiary_dark
- - @color/system_error_dark
-
- - @color/system_widget_background_dark
- - @color/system_clock_hour_dark
- - @color/system_clock_minute_dark
- - @color/system_clock_second_dark
- - @color/system_theme_app_dark
- - @color/system_on_theme_app_dark
- - @color/system_theme_app_ring_dark
- - @color/system_theme_notif_dark
+ - @color/system_tertiary_container_dark
+ - @color/system_text_hint_inverse_dark
+ - @color/system_text_primary_inverse_dark
+ - @color/system_text_primary_inverse_disable_only_dark
+ - @color/system_text_secondary_and_tertiary_inverse_dark
+ - @color/system_text_secondary_and_tertiary_inverse_disabled_dark
+ - @color/system_on_primary_fixed
+ - @color/system_on_primary_fixed_variant
+ - @color/system_on_secondary_fixed
+ - @color/system_on_secondary_fixed_variant
+ - @color/system_on_tertiary_fixed
+ - @color/system_on_tertiary_fixed_variant
+ - @color/system_primary_fixed
+ - @color/system_primary_fixed_dim
+ - @color/system_secondary_fixed
+ - @color/system_secondary_fixed_dim
+ - @color/system_tertiary_fixed
+ - @color/system_tertiary_fixed_dim
- @color/system_brand_a_dark
- @color/system_brand_b_dark
- @color/system_brand_c_dark
- @color/system_brand_d_dark
- - @color/system_under_surface_dark
- - @color/system_shade_active_dark
+ - @color/system_clock_hour_dark
+ - @color/system_clock_minute_dark
+ - @color/system_clock_second_dark
- @color/system_on_shade_active_dark
- @color/system_on_shade_active_variant_dark
- - @color/system_shade_inactive_dark
- @color/system_on_shade_inactive_dark
- @color/system_on_shade_inactive_variant_dark
- - @color/system_shade_disabled_dark
+ - @color/system_on_theme_app_dark
- @color/system_overview_background_dark
+ - @color/system_shade_active_dark
+ - @color/system_shade_disabled_dark
+ - @color/system_shade_inactive_dark
+ - @color/system_theme_app_dark
+ - @color/system_theme_app_ring_dark
+ - @color/system_theme_notif_dark
+ - @color/system_under_surface_dark
+ - @color/system_weather_temp_dark
+ - @color/system_widget_background_dark
@@ -5946,73 +6759,90 @@ easier.
- @color/system_secondary_dark
- @color/system_tertiary_dark
- - @color/system_on_secondary_fixed_variant
- - @color/system_on_tertiary_fixed_variant
- - @color/system_surface_container_lowest_dark
- - @color/system_on_primary_fixed_variant
- - @color/system_on_secondary_container_dark
- - @color/system_on_tertiary_container_dark
- - @color/system_surface_container_low_dark
- - @color/system_on_primary_container_dark
- - @color/system_secondary_fixed_dim
- - @color/system_on_error_container_dark
- - @color/system_on_secondary_fixed
- - @color/system_on_surface_light
- - @color/system_tertiary_fixed_dim
- - @color/system_on_tertiary_fixed
- - @color/system_primary_fixed_dim
- - @color/system_secondary_container_dark
+ - @color/system_background_dark
+ - @color/system_control_activated_dark
+ - @color/system_control_highlight_dark
+ - @color/system_control_normal_dark
+ - @color/system_error_dark
- @color/system_error_container_dark
- - @color/system_on_primary_fixed
- - @color/system_primary_light
- - @color/system_secondary_fixed
- - @color/system_surface_light
- - @color/system_surface_variant_dark
- - @color/system_tertiary_container_dark
- - @color/system_tertiary_fixed
- - @color/system_primary_container_dark
+ - @color/system_inverse_on_surface_dark
+ - @color/system_inverse_primary_dark
+ - @color/system_inverse_surface_dark
- @color/system_on_background_dark
- - @color/system_primary_fixed
- - @color/system_on_secondary_dark
- - @color/system_on_tertiary_dark
- - @color/system_surface_dim_dark
- - @color/system_surface_bright_dark
- @color/system_on_error_dark
- - @color/system_surface_dark
- - @color/system_surface_container_high_dark
- - @color/system_surface_container_highest_dark
+ - @color/system_on_error_container_dark
+ - @color/system_on_primary_dark
+ - @color/system_on_primary_container_dark
+ - @color/system_on_secondary_dark
+ - @color/system_on_secondary_container_dark
+ - @color/system_on_surface_dark
- @color/system_on_surface_variant_dark
+ - @color/system_on_tertiary_dark
+ - @color/system_on_tertiary_container_dark
- @color/system_outline_dark
- @color/system_outline_variant_dark
- - @color/system_on_primary_dark
- - @color/system_on_surface_dark
- - @color/system_surface_container_dark
+ - @color/system_palette_key_color_neutral_dark
+ - @color/system_palette_key_color_neutral_variant_dark
+ - @color/system_palette_key_color_primary_dark
+ - @color/system_palette_key_color_secondary_dark
+ - @color/system_palette_key_color_tertiary_dark
- @color/system_primary_dark
+ - @color/system_primary_container_dark
+ - @color/system_scrim_dark
- @color/system_secondary_dark
+ - @color/system_secondary_container_dark
+ - @color/system_shadow_dark
+ - @color/system_surface_dark
+ - @color/system_surface_bright_dark
+ - @color/system_surface_container_dark
+ - @color/system_surface_container_high_dark
+ - @color/system_surface_container_highest_dark
+ - @color/system_surface_container_low_dark
+ - @color/system_surface_container_lowest_dark
+ - @color/system_surface_dim_dark
+ - @color/system_surface_tint_dark
+ - @color/system_surface_variant_dark
- @color/system_tertiary_dark
- - @color/system_error_dark
-
- - @color/system_widget_background_dark
- - @color/system_clock_hour_dark
- - @color/system_clock_minute_dark
- - @color/system_clock_second_dark
- - @color/system_theme_app_dark
- - @color/system_on_theme_app_dark
- - @color/system_theme_app_ring_dark
- - @color/system_theme_notif_dark
+ - @color/system_tertiary_container_dark
+ - @color/system_text_hint_inverse_dark
+ - @color/system_text_primary_inverse_dark
+ - @color/system_text_primary_inverse_disable_only_dark
+ - @color/system_text_secondary_and_tertiary_inverse_dark
+ - @color/system_text_secondary_and_tertiary_inverse_disabled_dark
+ - @color/system_on_primary_fixed
+ - @color/system_on_primary_fixed_variant
+ - @color/system_on_secondary_fixed
+ - @color/system_on_secondary_fixed_variant
+ - @color/system_on_tertiary_fixed
+ - @color/system_on_tertiary_fixed_variant
+ - @color/system_primary_fixed
+ - @color/system_primary_fixed_dim
+ - @color/system_secondary_fixed
+ - @color/system_secondary_fixed_dim
+ - @color/system_tertiary_fixed
+ - @color/system_tertiary_fixed_dim
- @color/system_brand_a_dark
- @color/system_brand_b_dark
- @color/system_brand_c_dark
- @color/system_brand_d_dark
- - @color/system_under_surface_dark
- - @color/system_shade_active_dark
+ - @color/system_clock_hour_dark
+ - @color/system_clock_minute_dark
+ - @color/system_clock_second_dark
- @color/system_on_shade_active_dark
- @color/system_on_shade_active_variant_dark
- - @color/system_shade_inactive_dark
- @color/system_on_shade_inactive_dark
- @color/system_on_shade_inactive_variant_dark
- - @color/system_shade_disabled_dark
+ - @color/system_on_theme_app_dark
- @color/system_overview_background_dark
+ - @color/system_shade_active_dark
+ - @color/system_shade_disabled_dark
+ - @color/system_shade_inactive_dark
+ - @color/system_theme_app_dark
+ - @color/system_theme_app_ring_dark
+ - @color/system_theme_notif_dark
+ - @color/system_under_surface_dark
+ - @color/system_weather_temp_dark
+ - @color/system_widget_background_dark
\ No newline at end of file
diff --git a/packages/SettingsLib/CollapsingToolbarBaseActivity/res/values-v35/themes.xml b/packages/SettingsLib/CollapsingToolbarBaseActivity/res/values-v35/themes.xml
index 7c9d1a47b7efe636771cf82943eb8d7b1f144185..f7c9aac686295f52ba9eb6b288f18cb8246ec450 100644
--- a/packages/SettingsLib/CollapsingToolbarBaseActivity/res/values-v35/themes.xml
+++ b/packages/SettingsLib/CollapsingToolbarBaseActivity/res/values-v35/themes.xml
@@ -18,7 +18,7 @@
\ No newline at end of file
diff --git a/packages/SettingsLib/Graph/src/com/android/settingslib/graph/GetPreferenceGraphApiHandler.kt b/packages/SettingsLib/Graph/src/com/android/settingslib/graph/GetPreferenceGraphApiHandler.kt
index 5ceee6d09978af58fcb4c817516205f8f0f9b585..088bef2303741a4da4c1357a150d4694466169ff 100644
--- a/packages/SettingsLib/Graph/src/com/android/settingslib/graph/GetPreferenceGraphApiHandler.kt
+++ b/packages/SettingsLib/Graph/src/com/android/settingslib/graph/GetPreferenceGraphApiHandler.kt
@@ -22,11 +22,13 @@ import com.android.settingslib.graph.proto.PreferenceGraphProto
import com.android.settingslib.ipc.ApiHandler
import com.android.settingslib.ipc.MessageCodec
import com.android.settingslib.metadata.PreferenceScreenRegistry
+import com.android.settingslib.preference.PreferenceScreenProvider
import java.util.Locale
/** API to get preference graph. */
-abstract class GetPreferenceGraphApiHandler :
- ApiHandler {
+abstract class GetPreferenceGraphApiHandler(
+ private val preferenceScreenProviders: Set>
+) : ApiHandler {
override val requestCodec: MessageCodec
get() = GetPreferenceGraphRequestCodec
@@ -40,14 +42,16 @@ abstract class GetPreferenceGraphApiHandler :
callingUid: Int,
request: GetPreferenceGraphRequest,
): PreferenceGraphProto {
- val builderRequest =
- if (request.screenKeys.isEmpty()) {
- val keys = PreferenceScreenRegistry.preferenceScreens.keys
- GetPreferenceGraphRequest(keys, request.visitedScreens, request.locale)
- } else {
- request
+ val builder = PreferenceGraphBuilder.of(application, request)
+ if (request.screenKeys.isEmpty()) {
+ for (key in PreferenceScreenRegistry.preferenceScreens.keys) {
+ builder.addPreferenceScreenFromRegistry(key)
}
- return PreferenceGraphBuilder.of(application, builderRequest).build()
+ for (provider in preferenceScreenProviders) {
+ builder.addPreferenceScreenProvider(provider)
+ }
+ }
+ return builder.build()
}
}
diff --git a/packages/SettingsLib/Graph/src/com/android/settingslib/graph/PreferenceGraphBuilder.kt b/packages/SettingsLib/Graph/src/com/android/settingslib/graph/PreferenceGraphBuilder.kt
index 2256bb38dd2c15c44e0b03c5cce554007ddf4917..6760e72be4a68bd42184b3822f0663645c8e3f94 100644
--- a/packages/SettingsLib/Graph/src/com/android/settingslib/graph/PreferenceGraphBuilder.kt
+++ b/packages/SettingsLib/Graph/src/com/android/settingslib/graph/PreferenceGraphBuilder.kt
@@ -133,7 +133,7 @@ private constructor(private val context: Context, private val request: GetPrefer
null
}
- private suspend fun addPreferenceScreenFromRegistry(key: String): Boolean {
+ suspend fun addPreferenceScreenFromRegistry(key: String): Boolean {
val metadata = PreferenceScreenRegistry[key] ?: return false
return addPreferenceScreenMetadata(metadata)
}
@@ -146,7 +146,7 @@ private constructor(private val context: Context, private val request: GetPrefer
}
}
- private suspend fun addPreferenceScreenProvider(activityClass: Class<*>) {
+ suspend fun addPreferenceScreenProvider(activityClass: Class<*>) {
Log.d(TAG, "add $activityClass")
createPreferenceScreen { activityClass.newInstance() }
?.let {
diff --git a/packages/SettingsLib/Graph/src/com/android/settingslib/graph/PreferenceSetterApi.kt b/packages/SettingsLib/Graph/src/com/android/settingslib/graph/PreferenceSetterApi.kt
index 6e4db1d904848e2be79f5c31639a2cfdee4d70d3..7cfce0d85cd4e329d7a2a2a0e67f4fa9f5f93946 100644
--- a/packages/SettingsLib/Graph/src/com/android/settingslib/graph/PreferenceSetterApi.kt
+++ b/packages/SettingsLib/Graph/src/com/android/settingslib/graph/PreferenceSetterApi.kt
@@ -22,6 +22,7 @@ import androidx.annotation.IntDef
import com.android.settingslib.graph.proto.PreferenceValueProto
import com.android.settingslib.ipc.ApiDescriptor
import com.android.settingslib.ipc.ApiHandler
+import com.android.settingslib.ipc.ApiPermissionChecker
import com.android.settingslib.ipc.IntMessageCodec
import com.android.settingslib.ipc.MessageCodec
import com.android.settingslib.metadata.BooleanValue
@@ -45,7 +46,11 @@ data class PreferenceSetterRequest(
PreferenceSetterResult.OK,
PreferenceSetterResult.UNSUPPORTED,
PreferenceSetterResult.DISABLED,
+ PreferenceSetterResult.RESTRICTED,
PreferenceSetterResult.UNAVAILABLE,
+ PreferenceSetterResult.REQUIRE_APP_PERMISSION,
+ PreferenceSetterResult.REQUIRE_USER_AGREEMENT,
+ PreferenceSetterResult.DISALLOW,
PreferenceSetterResult.INVALID_REQUEST,
PreferenceSetterResult.INTERNAL_ERROR,
)
@@ -87,14 +92,17 @@ class PreferenceSetterApiDescriptor(override val id: Int) :
}
/** Preference setter API implementation. */
-class PreferenceSetterApiHandler(override val id: Int) : ApiHandler {
+class PreferenceSetterApiHandler(
+ override val id: Int,
+ private val permissionChecker: ApiPermissionChecker,
+) : ApiHandler {
override fun hasPermission(
application: Application,
myUid: Int,
callingUid: Int,
request: PreferenceSetterRequest,
- ): Boolean = true
+ ) = permissionChecker.hasPermission(application, myUid, callingUid, request)
override suspend fun invoke(
application: Application,
diff --git a/packages/SettingsLib/Graph/src/com/android/settingslib/graph/ProtoConverters.kt b/packages/SettingsLib/Graph/src/com/android/settingslib/graph/ProtoConverters.kt
index d9b9590f60e2865f63dcf771e24108e4c6b9015a..1bda277f20187b327598964a290e3302e2dd20d2 100644
--- a/packages/SettingsLib/Graph/src/com/android/settingslib/graph/ProtoConverters.kt
+++ b/packages/SettingsLib/Graph/src/com/android/settingslib/graph/ProtoConverters.kt
@@ -16,8 +16,10 @@
package com.android.settingslib.graph
+import android.content.ComponentName
import android.content.Context
import android.content.Intent
+import android.net.Uri
import android.os.Bundle
import com.android.settingslib.graph.proto.BundleProto
import com.android.settingslib.graph.proto.BundleProto.BundleValue
@@ -42,6 +44,20 @@ fun Intent.toProto(): IntentProto = intentProto {
this@toProto.type?.let { mimeType = it }
}
+fun IntentProto.toIntent(): Intent? {
+ if (!hasComponent()) return null
+ val componentName = ComponentName.unflattenFromString(component) ?: return null
+ val intent = Intent()
+ intent.component = componentName
+ if (hasAction()) intent.action = action
+ if (hasData()) intent.data = Uri.parse(data)
+ if (hasPkg()) intent.`package` = pkg
+ if (hasFlags()) intent.flags = flags
+ if (hasExtras()) intent.putExtras(extras.toBundle())
+ if (hasMimeType()) intent.setType(mimeType)
+ return intent
+}
+
fun Bundle.toProto(): BundleProto = bundleProto {
fun toProto(value: Any): BundleValue = bundleValueProto {
when (value) {
@@ -61,14 +77,18 @@ fun Bundle.toProto(): BundleProto = bundleProto {
}
}
-fun BundleValue.stringify(): String =
- when {
- hasBooleanValue() -> "$valueCase"
- hasBytesValue() -> "$bytesValue"
- hasIntValue() -> "$intValue"
- hasLongValue() -> "$longValue"
- hasStringValue() -> stringValue
- hasDoubleValue() -> "$doubleValue"
- hasBundleValue() -> "$bundleValue"
- else -> "Unknown"
+fun BundleProto.toBundle(): Bundle =
+ Bundle().apply {
+ for ((key, value) in valuesMap) {
+ when {
+ value.hasBooleanValue() -> putBoolean(key, value.booleanValue)
+ value.hasBytesValue() -> putByteArray(key, value.bytesValue.toByteArray())
+ value.hasIntValue() -> putInt(key, value.intValue)
+ value.hasLongValue() -> putLong(key, value.longValue)
+ value.hasStringValue() -> putString(key, value.stringValue)
+ value.hasDoubleValue() -> putDouble(key, value.doubleValue)
+ value.hasBundleValue() -> putBundle(key, value.bundleValue.toBundle())
+ else -> throw IllegalArgumentException("Unknown type: ${value.javaClass} $value")
+ }
+ }
}
diff --git a/packages/SettingsLib/Ipc/src/com/android/settingslib/ipc/ApiHandler.kt b/packages/SettingsLib/Ipc/src/com/android/settingslib/ipc/ApiHandler.kt
index 802141dae7ecd6e8e59c5d62bc8cfcf088780070..4febd89a7da42035520db430ce94c9c08cf3c354 100644
--- a/packages/SettingsLib/Ipc/src/com/android/settingslib/ipc/ApiHandler.kt
+++ b/packages/SettingsLib/Ipc/src/com/android/settingslib/ipc/ApiHandler.kt
@@ -56,6 +56,27 @@ interface ApiDescriptor {
val responseCodec: MessageCodec
}
+/** Permission checker for api. */
+fun interface ApiPermissionChecker {
+ /**
+ * Returns if the request is permitted.
+ *
+ * @param application application context
+ * @param myUid uid of current process
+ * @param callingUid uid of peer process
+ * @param request API request
+ * @return `false` if permission is denied, otherwise `true`
+ */
+ fun hasPermission(application: Application, myUid: Int, callingUid: Int, request: R): Boolean
+
+ companion object {
+ private val ALWAYS_ALLOW = ApiPermissionChecker { _, _, _, _ -> true }
+
+ @Suppress("UNCHECKED_CAST")
+ fun alwaysAllow(): ApiPermissionChecker = ALWAYS_ALLOW as ApiPermissionChecker
+ }
+}
+
/**
* Handler of API.
*
@@ -64,18 +85,8 @@ interface ApiDescriptor {
*
* The implementation must be threadsafe.
*/
-interface ApiHandler : ApiDescriptor {
- /**
- * Returns if the request is permitted.
- *
- * @return `false` if permission is denied, otherwise `true`
- */
- fun hasPermission(
- application: Application,
- myUid: Int,
- callingUid: Int,
- request: Request,
- ): Boolean
+interface ApiHandler :
+ ApiDescriptor, ApiPermissionChecker {
/**
* Invokes the API.
diff --git a/packages/SettingsLib/Ipc/src/com/android/settingslib/ipc/MessengerServiceClient.kt b/packages/SettingsLib/Ipc/src/com/android/settingslib/ipc/MessengerServiceClient.kt
index 7ffefed239a46e9aed769011e46a40fbfc9ce6ff..ef907e17d824aa180787a7cd7500d0840958db83 100644
--- a/packages/SettingsLib/Ipc/src/com/android/settingslib/ipc/MessengerServiceClient.kt
+++ b/packages/SettingsLib/Ipc/src/com/android/settingslib/ipc/MessengerServiceClient.kt
@@ -320,6 +320,11 @@ constructor(
}
}
+ override fun onNullBinding(name: ComponentName) {
+ Log.i(TAG, "onNullBinding $name")
+ close(ClientBindServiceException(null))
+ }
+
internal open fun drainPendingRequests() {
disposableHandle = null
if (pendingRequests.isEmpty()) {
diff --git a/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceHierarchy.kt b/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceHierarchy.kt
index bde4217b396278cc09cc7a7e38104b7d063b3416..a2b826a50e5874b9cb211866262a180c926e632f 100644
--- a/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceHierarchy.kt
+++ b/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceHierarchy.kt
@@ -166,10 +166,6 @@ class PreferenceHierarchy internal constructor(metadata: PreferenceMetadata) :
}
return null
}
-
- /** Returns all the [PreferenceHierarchyNode]s appear in the hierarchy. */
- fun getAllPreferences(): List =
- mutableListOf().apply { forEachRecursively { add(it) } }
}
/**
diff --git a/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceBinding.kt b/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceBinding.kt
index 49acc1d44144a0bea335672725c34c8b4f5f5e77..6b7be91c19030c7080122fa7f42c8d0a03a8d20f 100644
--- a/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceBinding.kt
+++ b/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceBinding.kt
@@ -108,6 +108,9 @@ interface PreferenceBinding {
}
}
+/** Interface indicates that a virtual [Preference] should be created for binding. */
+interface PreferenceBindingPlaceholder
+
/** Abstract preference screen to provide preference hierarchy and binding factory. */
interface PreferenceScreenCreator : PreferenceScreenMetadata, PreferenceScreenProvider {
diff --git a/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceScreenBindingHelper.kt b/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceScreenBindingHelper.kt
index fbe892710d4078cbafca9829e6437f2cafb37ae5..cfe6089169d37ec90e8b01637ce7b3d7751d5f79 100644
--- a/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceScreenBindingHelper.kt
+++ b/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceScreenBindingHelper.kt
@@ -218,34 +218,47 @@ class PreferenceScreenBindingHelper(
preferenceScreen: PreferenceScreen,
preferenceBindingFactory: PreferenceBindingFactory,
preferenceHierarchy: PreferenceHierarchy,
- ) =
- preferenceScreen.bindRecursively(
- preferenceBindingFactory,
- preferenceHierarchy.getAllPreferences().associateBy { it.metadata.key },
- )
-
- private fun PreferenceGroup.bindRecursively(
- preferenceBindingFactory: PreferenceBindingFactory,
- preferences: Map,
- storages: MutableMap = mutableMapOf(),
) {
- preferences[key]?.let { preferenceBindingFactory.bind(this, it) }
- val count = preferenceCount
- for (index in 0 until count) {
- val preference = getPreference(index)
- if (preference is PreferenceGroup) {
- preference.bindRecursively(preferenceBindingFactory, preferences, storages)
- } else {
- preferences[preference.key]?.let {
- val metadata = it.metadata
- (metadata as? PersistentPreference<*>)?.storage(context)?.let { storage ->
- preference.preferenceDataStore =
- storages.getOrPut(storage) { PreferenceDataStoreAdapter(storage) }
+ val preferences = mutableMapOf()
+ preferenceHierarchy.forEachRecursively {
+ val metadata = it.metadata
+ preferences[metadata.key] = it
+ }
+ val storages = mutableMapOf()
+
+ fun Preference.setPreferenceDataStore(metadata: PreferenceMetadata) {
+ (metadata as? PersistentPreference<*>)?.storage(context)?.let { storage ->
+ preferenceDataStore =
+ storages.getOrPut(storage) { PreferenceDataStoreAdapter(storage) }
+ }
+ }
+
+ fun PreferenceGroup.bindRecursively() {
+ preferences.remove(key)?.let { preferenceBindingFactory.bind(this, it) }
+ val count = preferenceCount
+ for (index in 0 until count) {
+ val preference = getPreference(index)
+ if (preference is PreferenceGroup) {
+ preference.bindRecursively()
+ } else {
+ preferences.remove(preference.key)?.let {
+ preference.setPreferenceDataStore(it.metadata)
+ preferenceBindingFactory.bind(preference, it)
}
- preferenceBindingFactory.bind(preference, it)
}
}
}
+
+ preferenceScreen.bindRecursively()
+ for (node in preferences.values) {
+ val metadata = node.metadata
+ val binding = preferenceBindingFactory.getPreferenceBinding(metadata)
+ if (binding !is PreferenceBindingPlaceholder) continue
+ val preference = binding.createWidget(preferenceScreen.context)
+ preference.setPreferenceDataStore(metadata)
+ preferenceBindingFactory.bind(preference, node, binding)
+ preferenceScreen.addPreference(preference)
+ }
}
}
}
diff --git a/packages/SettingsLib/Service/src/com/android/settingslib/service/PreferenceGraphApi.kt b/packages/SettingsLib/Service/src/com/android/settingslib/service/PreferenceGraphApi.kt
index 6e38df11156f8fdba70dcc827bdb5fbd50d1d4ca..1823ba641775122460a6c2ff84c95cbfc540894b 100644
--- a/packages/SettingsLib/Service/src/com/android/settingslib/service/PreferenceGraphApi.kt
+++ b/packages/SettingsLib/Service/src/com/android/settingslib/service/PreferenceGraphApi.kt
@@ -19,9 +19,14 @@ package com.android.settingslib.service
import android.app.Application
import com.android.settingslib.graph.GetPreferenceGraphApiHandler
import com.android.settingslib.graph.GetPreferenceGraphRequest
+import com.android.settingslib.ipc.ApiPermissionChecker
+import com.android.settingslib.preference.PreferenceScreenProvider
/** Api to get preference graph. */
-internal class PreferenceGraphApi : GetPreferenceGraphApiHandler() {
+internal class PreferenceGraphApi(
+ preferenceScreenProviders: Set>,
+ private val permissionChecker: ApiPermissionChecker,
+) : GetPreferenceGraphApiHandler(preferenceScreenProviders) {
override val id: Int
get() = API_GET_PREFERENCE_GRAPH
@@ -31,5 +36,5 @@ internal class PreferenceGraphApi : GetPreferenceGraphApiHandler() {
myUid: Int,
callingUid: Int,
request: GetPreferenceGraphRequest,
- ) = true
+ ) = permissionChecker.hasPermission(application, myUid, callingUid, request)
}
diff --git a/packages/SettingsLib/Service/src/com/android/settingslib/service/PreferenceService.kt b/packages/SettingsLib/Service/src/com/android/settingslib/service/PreferenceService.kt
index 8ebb14522c3dae3289b74fccf361c65e38b732f0..ed748bb58a9a239506ef6ee912e351ef9f1f79f6 100644
--- a/packages/SettingsLib/Service/src/com/android/settingslib/service/PreferenceService.kt
+++ b/packages/SettingsLib/Service/src/com/android/settingslib/service/PreferenceService.kt
@@ -16,10 +16,14 @@
package com.android.settingslib.service
+import com.android.settingslib.graph.GetPreferenceGraphRequest
import com.android.settingslib.graph.PreferenceSetterApiHandler
+import com.android.settingslib.graph.PreferenceSetterRequest
import com.android.settingslib.ipc.ApiHandler
+import com.android.settingslib.ipc.ApiPermissionChecker
import com.android.settingslib.ipc.MessengerService
import com.android.settingslib.ipc.PermissionChecker
+import com.android.settingslib.preference.PreferenceScreenProvider
/**
* Preference service providing a bunch of APIs.
@@ -28,14 +32,21 @@ import com.android.settingslib.ipc.PermissionChecker
* [PREFERENCE_SERVICE_ACTION].
*/
open class PreferenceService(
- permissionChecker: PermissionChecker,
name: String = "PreferenceService",
+ permissionChecker: PermissionChecker = PermissionChecker { _, _, _ -> true },
+ preferenceScreenProviders: Set> = setOf(),
+ graphPermissionChecker: ApiPermissionChecker? = null,
+ setterPermissionChecker: ApiPermissionChecker? = null,
+ vararg apiHandlers: ApiHandler<*, *>,
) :
MessengerService(
- listOf>(
- PreferenceGraphApi(),
- PreferenceSetterApiHandler(API_PREFERENCE_SETTER),
- ),
+ mutableListOf>().apply {
+ graphPermissionChecker?.let { add(PreferenceGraphApi(preferenceScreenProviders, it)) }
+ setterPermissionChecker?.let {
+ add(PreferenceSetterApiHandler(API_PREFERENCE_SETTER, it))
+ }
+ addAll(apiHandlers)
+ },
permissionChecker,
name,
)
diff --git a/packages/SettingsLib/Service/src/com/android/settingslib/service/ServiceApiConstants.kt b/packages/SettingsLib/Service/src/com/android/settingslib/service/ServiceApiConstants.kt
index 1f38a6678eae943df4f22579a558053c32ad7ffa..7655daa6cf213b8dfc5374271bdcc775202fbb52 100644
--- a/packages/SettingsLib/Service/src/com/android/settingslib/service/ServiceApiConstants.kt
+++ b/packages/SettingsLib/Service/src/com/android/settingslib/service/ServiceApiConstants.kt
@@ -18,5 +18,14 @@ package com.android.settingslib.service
const val PREFERENCE_SERVICE_ACTION = "com.android.settingslib.PREFERENCE_SERVICE"
+/** API id for retrieving preference graph. */
internal const val API_GET_PREFERENCE_GRAPH = 1
+
+/** API id for preference value setter. */
internal const val API_PREFERENCE_SETTER = 2
+
+/**
+ * The max API id reserved for internal preference service usages. Custom API id should start with
+ * **1000** to avoid conflict.
+ */
+internal const val API_MAX_RESERVED = 999
diff --git a/packages/SettingsLib/SettingsTheme/res/color-v31/settingslib_surface_light.xml b/packages/SettingsLib/SettingsTheme/res/color-v31/settingslib_surface_light.xml
index b46181e20eaa842dac055d1103cdcd988f50233b..8b574aa951760b809bed23c0aa860a7451ce5a3a 100644
--- a/packages/SettingsLib/SettingsTheme/res/color-v31/settingslib_surface_light.xml
+++ b/packages/SettingsLib/SettingsTheme/res/color-v31/settingslib_surface_light.xml
@@ -13,7 +13,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-
+
\ No newline at end of file
diff --git a/packages/SettingsLib/SettingsTheme/res/values-night-v31/colors.xml b/packages/SettingsLib/SettingsTheme/res/values-night-v31/colors.xml
index 313748d8f091f346403362008d0517c8c84a9457..46ec62e7a5efc4b7c03b26c864a7af01618ac318 100644
--- a/packages/SettingsLib/SettingsTheme/res/values-night-v31/colors.xml
+++ b/packages/SettingsLib/SettingsTheme/res/values-night-v31/colors.xml
@@ -51,7 +51,7 @@
@android:color/system_accent1_100
-
+
@android:color/system_neutral1_800
diff --git a/packages/SettingsLib/SettingsTheme/res/values-night-v35/colors.xml b/packages/SettingsLib/SettingsTheme/res/values-night-v35/colors.xml
index 94ff02d898db2685d946706f3d441685f4cb566f..84a3ed68af01281b4728f7dd76134d0eb71bea7e 100644
--- a/packages/SettingsLib/SettingsTheme/res/values-night-v35/colors.xml
+++ b/packages/SettingsLib/SettingsTheme/res/values-night-v35/colors.xml
@@ -53,11 +53,11 @@
@android:color/system_surface_container_low_dark
@android:color/system_on_primary_container_dark
@android:color/system_on_error_container_dark
- @android:color/system_on_surface_light
+ @android:color/system_on_surface_light
@android:color/system_secondary_container_dark
@android:color/system_error_container_dark
- @android:color/system_primary_light
- @android:color/system_surface_light
+ @android:color/system_primary_light
+ @android:color/system_surface_light
@android:color/system_surface_variant_dark
@android:color/system_tertiary_container_dark
@android:color/system_primary_container_dark
diff --git a/packages/SettingsLib/SettingsTheme/res/values-v31/colors.xml b/packages/SettingsLib/SettingsTheme/res/values-v31/colors.xml
index b99ee51234914ab543baaabb2a29de9011fdfb98..fef92b792bec04093c36592bb17f716adc9508e6 100644
--- a/packages/SettingsLib/SettingsTheme/res/values-v31/colors.xml
+++ b/packages/SettingsLib/SettingsTheme/res/values-v31/colors.xml
@@ -67,9 +67,9 @@
@android:color/system_accent1_600
@android:color/system_accent2_100
-
+
@android:color/system_neutral1_900
-
+
@android:color/system_neutral1_50
@android:color/system_neutral1_900
diff --git a/packages/SettingsLib/SettingsTheme/res/values-v35/colors.xml b/packages/SettingsLib/SettingsTheme/res/values-v35/colors.xml
index 8b9501608000c3656220903343a64c5c3c9a2e81..90c19e1aa67695ac30f50ff0a3048d8c5a16082a 100644
--- a/packages/SettingsLib/SettingsTheme/res/values-v35/colors.xml
+++ b/packages/SettingsLib/SettingsTheme/res/values-v35/colors.xml
@@ -66,16 +66,16 @@
@android:color/system_secondary_fixed_dim
@android:color/system_on_error_container_light
@android:color/system_on_secondary_fixed
- @android:color/system_on_surface_dark
+ @android:color/system_on_surface_dark
@android:color/system_tertiary_fixed_dim
@android:color/system_on_tertiary_fixed
@android:color/system_primary_fixed_dim
@android:color/system_secondary_container_light
@android:color/system_error_container_light
@android:color/system_on_primary_fixed
- @android:color/system_primary_dark
+ @android:color/system_primary_dark
@android:color/system_secondary_fixed
- @android:color/system_surface_dark
+ @android:color/system_surface_dark
@android:color/system_surface_variant_light
@android:color/system_tertiary_container_light
@android:color/system_tertiary_fixed
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/ui/CategoryPageProvider.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/ui/CategoryPageProvider.kt
index 4d3a78a583fc55257fce98682ebe7efbc7168759..f2bc380a93de62f1d5e704dab4a2d70e55734692 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/ui/CategoryPageProvider.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/ui/CategoryPageProvider.kt
@@ -17,8 +17,12 @@
package com.android.settingslib.spa.gallery.ui
import android.os.Bundle
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.height
import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
import com.android.settingslib.spa.framework.common.SettingsEntry
import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
import com.android.settingslib.spa.framework.common.SettingsPageProvider
@@ -30,6 +34,7 @@ import com.android.settingslib.spa.widget.preference.PreferenceModel
import com.android.settingslib.spa.widget.preference.SimplePreferenceMacro
import com.android.settingslib.spa.widget.scaffold.RegularScaffold
import com.android.settingslib.spa.widget.ui.Category
+import com.android.settingslib.spa.widget.ui.LazyCategory
private const val TITLE = "Sample Category"
@@ -65,7 +70,7 @@ object CategoryPageProvider : SettingsPageProvider {
)
entryList.add(
SettingsEntryBuilder.create("Preference 3", owner)
- .setMacro { SimplePreferenceMacro(title = "Preference 2", summary = "Summary 3") }
+ .setMacro { SimplePreferenceMacro(title = "Preference 3", summary = "Summary 3") }
.build()
)
entryList.add(
@@ -88,6 +93,13 @@ object CategoryPageProvider : SettingsPageProvider {
entries[2].UiLayout()
entries[3].UiLayout()
}
+ Column(Modifier.height(200.dp)) {
+ LazyCategory(
+ list = entries,
+ entry = { index: Int -> @Composable { entries[index].UiLayout() } },
+ title = { index: Int -> if (index == 0 || index == 2) "LazyCategory" else null },
+ ) {}
+ }
}
}
}
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Category.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Category.kt
index 66680fa547b157745cf3e0efab3dad5aabc3fbe3..28b2b4ab1662fcd2ccb878310cdd1f8badb6d2ff 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Category.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Category.kt
@@ -19,8 +19,13 @@ package com.android.settingslib.spa.widget.ui
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ColumnScope
+import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.lazy.LazyListState
+import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.TouchApp
import androidx.compose.material3.MaterialTheme
@@ -34,6 +39,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import com.android.settingslib.spa.framework.theme.SettingsDimension
import com.android.settingslib.spa.framework.theme.SettingsShape
@@ -98,6 +104,57 @@ fun Category(title: String? = null, content: @Composable ColumnScope.() -> Unit)
}
}
+/**
+ * A container that is used to group items with lazy loading.
+ *
+ * @param list The list of items to display.
+ * @param entry The entry for each list item according to its index in list.
+ * @param key Optional. The key for each item in list to provide unique item identifiers, making
+ * the list more efficient.
+ * @param title Optional. Category title for each item or each group of items in the list. It
+ * should be decided by the index.
+ * @param bottomPadding Optional. Bottom outside padding of the category.
+ * @param state Optional. State of LazyList.
+ * @param content Optional. Content to be shown at the top of the category.
+ */
+
+@Composable
+fun LazyCategory(
+ list: List,
+ entry: (Int) -> @Composable () -> Unit,
+ key: ((Int) -> Any)? = null,
+ title: ((Int) -> String?)? = null,
+ bottomPadding: Dp = SettingsDimension.paddingSmall,
+ state: LazyListState = rememberLazyListState(),
+ content: @Composable () -> Unit,
+) {
+ Column(
+ Modifier.padding(
+ PaddingValues(
+ start = SettingsDimension.paddingLarge,
+ end = SettingsDimension.paddingLarge,
+ top = SettingsDimension.paddingSmall,
+ bottom = bottomPadding,
+ )
+ )
+ .clip(SettingsShape.CornerMedium2)
+ ) {
+ LazyColumn(
+ modifier = Modifier.fillMaxSize(),
+ verticalArrangement = Arrangement.spacedBy(SettingsDimension.paddingTiny),
+ state = state,
+ ) {
+ item { content() }
+
+ items(count = list.size, key = key) {
+ title?.invoke(it)?.let { title -> CategoryTitle(title) }
+ val entryPreference = entry(it)
+ entryPreference()
+ }
+ }
+ }
+}
+
@Preview
@Composable
private fun CategoryPreview() {
diff --git a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/ui/CategoryTest.kt b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/ui/CategoryTest.kt
index 09a6e6ddc7f0718e05f1bbb712c6104c7dc06a37..4b4a8c20b39e4f0d9690d3c263b2e88ba3a927dd 100644
--- a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/ui/CategoryTest.kt
+++ b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/ui/CategoryTest.kt
@@ -16,10 +16,16 @@
package com.android.settingslib.spa.widget.ui
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.height
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
+import androidx.compose.ui.Modifier
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithText
+import androidx.compose.ui.unit.dp
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settingslib.spa.widget.preference.Preference
import com.android.settingslib.spa.widget.preference.PreferenceModel
@@ -30,14 +36,11 @@ import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class CategoryTest {
- @get:Rule
- val composeTestRule = createComposeRule()
+ @get:Rule val composeTestRule = createComposeRule()
@Test
fun categoryTitle() {
- composeTestRule.setContent {
- CategoryTitle(title = "CategoryTitle")
- }
+ composeTestRule.setContent { CategoryTitle(title = "CategoryTitle") }
composeTestRule.onNodeWithText("CategoryTitle").assertIsDisplayed()
}
@@ -46,12 +49,14 @@ class CategoryTest {
fun category_hasContent_titleDisplayed() {
composeTestRule.setContent {
Category(title = "CategoryTitle") {
- Preference(remember {
- object : PreferenceModel {
- override val title = "Some Preference"
- override val summary = { "Some summary" }
+ Preference(
+ remember {
+ object : PreferenceModel {
+ override val title = "Some Preference"
+ override val summary = { "Some summary" }
+ }
}
- })
+ )
}
}
@@ -60,10 +65,45 @@ class CategoryTest {
@Test
fun category_noContent_titleNotDisplayed() {
- composeTestRule.setContent {
- Category(title = "CategoryTitle") {}
- }
+ composeTestRule.setContent { Category(title = "CategoryTitle") {} }
composeTestRule.onNodeWithText("CategoryTitle").assertDoesNotExist()
}
+
+ @Test
+ fun lazyCategory_content_displayed() {
+ composeTestRule.setContent { TestLazyCategory() }
+
+ composeTestRule.onNodeWithText("text").assertExists()
+ }
+
+ @Test
+ fun lazyCategory_title_displayed() {
+ composeTestRule.setContent { TestLazyCategory() }
+
+ composeTestRule.onNodeWithText("LazyCategory 0").assertExists()
+ composeTestRule.onNodeWithText("LazyCategory 1").assertDoesNotExist()
+ }
+}
+
+@Composable
+private fun TestLazyCategory() {
+ val list: List =
+ listOf(
+ object : PreferenceModel {
+ override val title = "title"
+ },
+ object : PreferenceModel {
+ override val title = "title"
+ },
+ )
+ Column(Modifier.height(200.dp)) {
+ LazyCategory(
+ list = list,
+ entry = { index: Int -> @Composable { Preference(list[index]) } },
+ title = { index: Int -> if (index == 0) "LazyCategory $index" else null },
+ ) {
+ Text("text")
+ }
+ }
}
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppList.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppList.kt
index bededf03a0f4acd6a0508351a8e338f94b1ddf45..2a214b6f74a6393097494196cc8c00cec1a0b1fb 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppList.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppList.kt
@@ -37,7 +37,9 @@ import com.android.settingslib.spa.framework.compose.LifecycleEffect
import com.android.settingslib.spa.framework.compose.LogCompositions
import com.android.settingslib.spa.framework.compose.TimeMeasurer.Companion.rememberTimeMeasurer
import com.android.settingslib.spa.framework.compose.rememberLazyListStateAndHideKeyboardWhenStartScroll
+import com.android.settingslib.spa.framework.theme.isSpaExpressiveEnabled
import com.android.settingslib.spa.widget.ui.CategoryTitle
+import com.android.settingslib.spa.widget.ui.LazyCategory
import com.android.settingslib.spa.widget.ui.PlaceholderTitle
import com.android.settingslib.spa.widget.ui.Spinner
import com.android.settingslib.spa.widget.ui.SpinnerOption
@@ -55,19 +57,14 @@ import kotlinx.coroutines.flow.MutableStateFlow
private const val TAG = "AppList"
private const val CONTENT_TYPE_HEADER = "header"
-/**
- * The config used to load the App List.
- */
+/** The config used to load the App List. */
data class AppListConfig(
val userIds: List,
val showInstantApps: Boolean,
val matchAnyUserForAdmin: Boolean,
)
-data class AppListState(
- val showSystem: () -> Boolean,
- val searchQuery: () -> String,
-)
+data class AppListState(val showSystem: () -> Boolean, val searchQuery: () -> String)
data class AppListInput(
val config: AppListConfig,
@@ -90,7 +87,7 @@ fun AppListInput.AppList() {
@Composable
internal fun AppListInput.AppListImpl(
- viewModelSupplier: @Composable () -> IAppListViewModel,
+ viewModelSupplier: @Composable () -> IAppListViewModel
) {
LogCompositions(TAG, config.userIds.toString())
val viewModel = viewModelSupplier()
@@ -125,7 +122,7 @@ private fun AppListModel.AppListWidget(
appListData: State?>,
header: @Composable () -> Unit,
bottomPadding: Dp,
- noItemMessage: String?
+ noItemMessage: String?,
) {
val timeMeasurer = rememberTimeMeasurer(TAG)
appListData.value?.let { (list, option) ->
@@ -135,40 +132,61 @@ private fun AppListModel.AppListWidget(
PlaceholderTitle(noItemMessage ?: stringResource(R.string.no_applications))
return
}
- LazyColumn(
- modifier = Modifier.fillMaxSize(),
- state = rememberLazyListStateAndHideKeyboardWhenStartScroll(),
- contentPadding = PaddingValues(bottom = bottomPadding),
- ) {
- item(contentType = CONTENT_TYPE_HEADER) {
+ if (isSpaExpressiveEnabled) {
+ LazyCategory(
+ list = list,
+ entry = { index: Int ->
+ @Composable {
+ val appEntry = list[index]
+ val summary = getSummary(option, appEntry.record) ?: { "" }
+ remember(appEntry) {
+ AppListItemModel(appEntry.record, appEntry.label, summary)
+ }
+ .AppItem()
+ }
+ },
+ key = { index: Int -> list[index].record.itemKey(option) },
+ title = { index: Int -> getGroupTitle(option, list[index].record) },
+ bottomPadding = bottomPadding,
+ state = rememberLazyListStateAndHideKeyboardWhenStartScroll(),
+ ) {
header()
}
-
- items(count = list.size, key = { list[it].record.itemKey(option) }) {
- remember(list) { getGroupTitleIfFirst(option, list, it) }
- ?.let { group -> CategoryTitle(title = group) }
-
- val appEntry = list[it]
- val summary = getSummary(option, appEntry.record) ?: { "" }
- remember(appEntry) {
- AppListItemModel(appEntry.record, appEntry.label, summary)
- }.AppItem()
+ } else {
+ LazyColumn(
+ modifier = Modifier.fillMaxSize(),
+ state = rememberLazyListStateAndHideKeyboardWhenStartScroll(),
+ contentPadding = PaddingValues(bottom = bottomPadding),
+ ) {
+ item(contentType = CONTENT_TYPE_HEADER) { header() }
+
+ items(count = list.size, key = { list[it].record.itemKey(option) }) {
+ remember(list) { getGroupTitleIfFirst(option, list, it) }
+ ?.let { group -> CategoryTitle(title = group) }
+
+ val appEntry = list[it]
+ val summary = getSummary(option, appEntry.record) ?: { "" }
+ remember(appEntry) {
+ AppListItemModel(appEntry.record, appEntry.label, summary)
+ }
+ .AppItem()
+ }
}
}
}
}
-private fun T.itemKey(option: Int) =
- listOf(option, app.packageName, app.userId)
+private fun T.itemKey(option: Int) = listOf(option, app.packageName, app.userId)
/** Returns group title if this is the first item of the group. */
private fun AppListModel.getGroupTitleIfFirst(
option: Int,
list: List>,
index: Int,
-): String? = getGroupTitle(option, list[index].record)?.takeIf {
- index == 0 || it != getGroupTitle(option, list[index - 1].record)
-}
+): String? =
+ getGroupTitle(option, list[index].record)?.takeIf {
+ index == 0 || it != getGroupTitle(option, list[index - 1].record)
+ }
@Composable
private fun rememberViewModel(
@@ -183,16 +201,19 @@ private fun rememberViewModel(
viewModel.searchQuery.Sync(state.searchQuery)
LifecycleEffect(onStart = { viewModel.reloadApps() })
- val intentFilter = IntentFilter(Intent.ACTION_PACKAGE_ADDED).apply {
- addAction(Intent.ACTION_PACKAGE_REMOVED)
- addAction(Intent.ACTION_PACKAGE_CHANGED)
- addDataScheme("package")
- }
+ val intentFilter =
+ IntentFilter(Intent.ACTION_PACKAGE_ADDED).apply {
+ addAction(Intent.ACTION_PACKAGE_REMOVED)
+ addAction(Intent.ACTION_PACKAGE_CHANGED)
+ addDataScheme("package")
+ }
for (userId in config.userIds) {
DisposableBroadcastReceiverAsUser(
intentFilter = intentFilter,
userHandle = UserHandle.of(userId),
- ) { viewModel.reloadApps() }
+ ) {
+ viewModel.reloadApps()
+ }
}
return viewModel
}
diff --git a/packages/SettingsLib/aconfig/settingslib.aconfig b/packages/SettingsLib/aconfig/settingslib.aconfig
index 81a2e6aeccc1c6edd4830b09852d034545fdba26..076f82acce0998cf83de8dd90fea9d21f722f2b7 100644
--- a/packages/SettingsLib/aconfig/settingslib.aconfig
+++ b/packages/SettingsLib/aconfig/settingslib.aconfig
@@ -73,16 +73,6 @@ flag {
}
}
-flag {
- name: "volume_panel_broadcast_fix"
- namespace: "systemui"
- description: "Make the volume panel's repository listen for the new ACTION_CONSOLIDATED_NOTIFICATION_POLICY_CHANGED broadcast instead of ACTION_NOTIFICATION_POLICY_CHANGED"
- bug: "347707024"
- metadata {
- purpose: PURPOSE_BUGFIX
- }
-}
-
flag {
name: "volume_dialog_audio_sharing_fix"
namespace: "cross_device_experiences"
@@ -110,6 +100,14 @@ flag {
bug: "323791114"
}
+flag {
+ name: "write_system_preference_permission_enabled"
+ is_fixed_read_only: true
+ namespace: "android_settings"
+ description: "Enable WRITE_SYSTEM_PREFERENCE permission and appop"
+ bug: "375193223"
+}
+
flag {
name: "asha_profile_access_profile_enabled_true"
namespace: "accessibility"
@@ -166,3 +164,17 @@ flag {
description: "Enable the ambient volume control in device details and hearing devices dialog."
bug: "357878944"
}
+
+flag {
+ name: "settings_preference_write_consent_enabled"
+ namespace: "android_settings"
+ description: "Enable the user consent prompt before writing sensitive preferences via service"
+ bug: "378552675"
+}
+
+flag {
+ name: "hearing_devices_input_routing_control"
+ namespace: "accessibility"
+ description: "Enable the input routing control in device details and hearing devices dialog."
+ bug: "349255906"
+}
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index 79c379996d8bfddf4694279585b73a54872c5490..6f6a357a4a95d812e49697700a4bd058452daefb 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -591,6 +591,12 @@
"Eksterne toestel"
"Gekoppelde toestel"
"Hierdie foon"
+
+
+
+
+
+
"Kan nie op hierdie toestel speel nie"
"Gradeer rekening op om oor te skakel"
"Kan nie aflaaie hier speel nie"
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index 5cde078af81129be099998d22bf6ea4276a751a7..4d7731c5dd459d5d95c7e8afa0b6e2727244880b 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -591,6 +591,12 @@
"የውጭ መሣሪያ"
"የተገናኘ መሣሪያ"
"ይህ ስልክ"
+
+
+
+
+
+
"በዚህ መሣሪያ ላይ ማጫወት አልተቻለም"
"ለመቀየር መለያ ያልቁ"
"ውርዶችን እዚህ ማጫወት አይቻልም"
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index f2d722ebe5cec9c9a63ac81142fc532b2161fbb1..8b8131342b7d31c74405b2ac8aa7fab0753f8f78 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -237,7 +237,7 @@
"تحديد الملف"
"الملف الشخصي"
"ملف العمل"
- "الملف الخاص"
+ "المساخة الخاصة"
"استنساخ"
"خيارات المطورين"
"تفعيل خيارات المطورين"
@@ -591,6 +591,12 @@
"جهاز خارجي"
"جهاز متّصل"
"هذا الهاتف"
+
+
+
+
+
+
"لا يمكن تشغيل الوسائط هنا"
"يجب ترقية الحساب للتبديل"
"المحتوى المنزَّل غير متوافق"
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index 62d6f68e36115d6b4d8be4736ab933fcd6fd8e01..02324de0276f2d64ba3ab57e58bc9fda1f97aee5 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -591,6 +591,12 @@
"বাহ্যিক ডিভাইচ"
"সংযোগ হৈ থকা ডিভাইচ"
"এই ফ’নটো"
+
+
+
+
+
+
"এই ডিভাইচটো প্লে\' কৰিব নোৱাৰি"
"সলনি কৰিবলৈ একাউণ্ট আপগ্ৰে’ড কৰক"
"ইয়াত ডাউনল’ডসমূহ প্লে’ কৰিব নোৱাৰি"
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index 459cfaaae9c4714c472112a88e3c21e64a7d8efa..25e85d53cdceadb260470c8352a1357dfca652d7 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -591,6 +591,12 @@
"Xarici cihaz"
"Qoşulmuş cihaz"
"Bu telefon"
+
+
+
+
+
+
"Bu cihazda oxutmaq olmur"
"Keçirmək üçün hesabı güncəllə"
"Burada endirmələri oxutmaq olmur"
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index f883c93fd15e6e0579a76641d6fdb98bb9318e4f..4214a401696540be1d2bec3a946de3628d2a69ba 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -591,6 +591,12 @@
"Spoljni uređaj"
"Povezani uređaj"
"Ovaj telefon"
+
+
+
+
+
+
"Ne možete da pustite na ovom uređaju"
"Nadogradite nalog radi prebacivanja"
"Preuzimanja ne mogu da se puštaju ovde"
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index ca07c4def3a0ce9ea91a3d19eb054f1ea13f1ab4..3e645b3f1ae06cc125337a0af959668e2bb5230a 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -591,6 +591,12 @@
"Знешняя прылада"
"Падключаная прылада"
"Гэты тэлефон"
+
+
+
+
+
+
"Не ўдаецца прайграць на гэтай прыладзе"
"Для пераключэння перайдзіце на іншую версію ўліковага запісу"
"Тут не ўдаецца прайграць спампоўкі"
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index 7661a31d4dc23c439e6fe96773d07538b0b84dd3..8bdd17ebd861d708d024a105ef15380a89b41d7c 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -591,6 +591,12 @@
"Външно устройство"
"Свързано устройство"
"Този телефон"
+
+
+
+
+
+
"Възпроизвеждането не е възможно на това устройство"
"Надстройте профила, за да превключите"
"Изтеглянията не могат да се възпроизвеждат тук"
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index ca98e0e510a55b9f2d2d82aab4666966795653d1..834eb1eef1ce5b3406293c10cbbdd7f27450ebd7 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -591,6 +591,12 @@
"এক্সটার্নাল ডিভাইস"
"কানেক্ট থাকা ডিভাইস"
"এই ফোনটি"
+
+
+
+
+
+
"এই ডিভাইসে চালানো যাবে না"
"পাল্টাতে অ্যাকাউন্ট আপগ্রেড করুন"
"এতে ডাউনলোড করা কন্টেন্ট প্লে করা যাবে না"
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index 72c2cbb9e73fbf2b35b90568e798dd214ccbcd70..75fe8181489dd5842d0ef4a9474e78762165d1d8 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -591,6 +591,12 @@
"Vanjski uređaj"
"Povezani uređaj"
"Ovaj telefon"
+
+
+
+
+
+
"Nije moguće reproducirati na uređaju"
"Nadogradite račun da promijenite"
"Nije moguće reproducirati preuzimanja ovdje"
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 43653582576d61acaf575dc73cd2811d4c2192fe..2c41b1aee8ef9f72089f0ac2c0ef3f494ec51de0 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -591,6 +591,12 @@
"Dispositiu extern"
"Dispositiu connectat"
"Aquest telèfon"
+
+
+
+
+
+
"No es pot reproduir en aquest dispositiu"
"Actualitza el compte per canviar"
"Les baixades no es poden reproduir aquí"
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index 0a88338cf2645bb5dc98f7e7c0c21420ba1b2481..a4b491bfc1f038777696eefa748d4722be2e7c32 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -591,6 +591,12 @@
"Externí zařízení"
"Připojené zařízení"
"Tento telefon"
+
+
+
+
+
+
"V zařízení nelze přehrávat"
"Účet je třeba upgradovat"
"Stažený obsah zde nelze přehrát"
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index 983003bf1550f4f023511d0a1debc5ab164ff5d9..f7402732299b0ced95a128f84bb70f866ca46294 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -591,6 +591,12 @@
"Ekstern enhed"
"Forbundet enhed"
"Denne telefon"
+
+
+
+
+
+
"Kan ikke afspilles på denne enhed"
"Opgrader kontoen for at skifte"
"Downloads kan ikke afspilles her"
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index 75ebb57843b9a97649de08e2b34b2c278e422b4b..c8d8cb55de992dae3740770f7fe55897bb485210 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -591,6 +591,12 @@
"Externes Gerät"
"Verbundenes Gerät"
"Dieses Smartphone"
+
+
+
+
+
+
"Wiedergabe auf diesem Gerät nicht möglich"
"Zum Umstellen Kontoupgrade durchführen"
"Downloads können hier nicht abgespielt werden"
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index c838f689528ec23d4f55da9faac1d38b589ece0b..c773372790b412058aa4ea7b59b73e9984965c7e 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -520,7 +520,7 @@
"Γρήγορη φόρτιση"
"Ελέγχονται από το διαχειριστή"
"Ελέγχεται από τη Ρύθμιση με περιορισμό"
- "Απενεργοποιημένο"
+ "Απενεργοποιημένη"
"Επιτρέπεται"
"Δεν επιτρέπεται"
"Εγκατ. άγνωστων εφ."
@@ -591,6 +591,12 @@
"Εξωτερική συσκευή"
"Συνδεδεμένη συσκευή"
"Αυτό το τηλέφ."
+
+
+
+
+
+
"Δεν είναι δυνατή η αναπαραγωγή σε αυτήν τη συσκευή"
"Αναβαθμίστε τον λογαριασμό για εναλλαγή"
"Δεν είναι δυνατή η αναπαραγωγή των λήψεων εδώ"
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index b4bf2055df0efa6b09d6edf87902147015d96e9e..8fe14350f3d90a8a8c17f84afea0703cc3e7270f 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -591,6 +591,12 @@
"External device"
"Connected device"
"This phone"
+
+
+
+
+
+
"Can\'t play on this device"
"Upgrade account to switch"
"Can\'t play downloads here"
diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml
index af392b83cfb122f5c1ddf952982c780f38f16daf..0d560ea7c8b9336d3668f31a0c1fd41b844007d2 100644
--- a/packages/SettingsLib/res/values-en-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-en-rCA/strings.xml
@@ -591,6 +591,9 @@
"External Device"
"Connected device"
"This phone"
+ "S/PDIF"
+ "Analog"
+ "AUX"
"Cant play on this device"
"Upgrade account to switch"
"Cant play downloads here"
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index b4bf2055df0efa6b09d6edf87902147015d96e9e..8fe14350f3d90a8a8c17f84afea0703cc3e7270f 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -591,6 +591,12 @@
"External device"
"Connected device"
"This phone"
+
+
+
+
+
+
"Can\'t play on this device"
"Upgrade account to switch"
"Can\'t play downloads here"
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index b4bf2055df0efa6b09d6edf87902147015d96e9e..8fe14350f3d90a8a8c17f84afea0703cc3e7270f 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -591,6 +591,12 @@
"External device"
"Connected device"
"This phone"
+
+
+
+
+
+
"Can\'t play on this device"
"Upgrade account to switch"
"Can\'t play downloads here"
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 3c1a27822a3cedcb375580d1e5d05e549bed681b..99dd4d9a56b97dd4b18fc55adad11f0445fafe1c 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -591,6 +591,12 @@
"Dispositivo externo"
"Dispositivo conectado"
"Este teléfono"
+
+
+
+
+
+
"No se puede reproducir en este dispositivo"
"Actualiza la cuenta para cambiar"
"No se pueden reproducir las descargas aquí"
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index bafa654a5284479d14e81e046ec2732888983bbe..cbbadd44d357c7162a34bdb552e4ee76d6fef21e 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -591,6 +591,12 @@
"Dispositivo externo"
"Dispositivo conectado"
"Este teléfono"
+
+
+
+
+
+
"No se puede reproducir en este dispositivo"
"Actualiza la cuenta para cambiar"
"No se pueden reproducir descargas aquí"
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index 5f5a38c1464bbbd9aa6610576bca8002a2ee267f..3c337933fbfbeca4aaa90153481c47a64f8098fc 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -591,6 +591,12 @@
"Väline seade"
"Ühendatud seade"
"See telefon"
+
+
+
+
+
+
"Selles seadmes ei saa esitada"
"Lülitamiseks täiendage kontot"
"Siin ei saa allalaaditud faile esitada"
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index 48e4f62e5865fa88561740ad03f74103cf0e41a5..c9947485e5f253d5772acb9bbef171660b10ccd3 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -591,6 +591,12 @@
"Kanpoko gailua"
"Konektatutako gailua"
"Telefono hau"
+
+
+
+
+
+
"Ezin da erreproduzitu gailu honetan"
"Aldatzeko, bertsio-berritu kontua"
"Deskargak ezin dira hemen erreproduzitu"
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 1aeca86aed6c8644c966f4786b3b946c22b86f8e..75b8051098240603edbec8b927ff0be649fb088b 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -591,6 +591,12 @@
"دستگاه خارجی"
"دستگاه متصل"
"این تلفن"
+
+
+
+
+
+
"نمیتوان در این دستگاه پخش کرد"
"برای تغییر، حساب را ارتقا دهید"
"نمیتوان بارگیریها را در اینجا پخش کرد"
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index 53724a3b7d8617e2d6915d763376b40d6a7a023a..9cc33b013979cb9a5e2e53dc35488f1b4400649f 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -591,6 +591,12 @@
"Ulkoinen laite"
"Yhdistetty laite"
"Tämä puhelin"
+
+
+
+
+
+
"Ei voi toistaa tällä laitteella"
"Vaihda päivittämällä tili"
"Latauksia ei voi toistaa täällä"
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index 1e4bbc43ed084bf3a7d9bb03c741db9357c57c02..28692d0afa55e2067f7d548d04381160bc202367 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -512,7 +512,7 @@
"En recharge sans fil"
"Recharge en cours…"
"N\'est pas en charge"
- "Connecté, mais ne se recharge pas"
+ "Appareil connecté, mais pas en cours de recharge"
"Chargée"
"Complètement rechargée"
"Recharge en pause"
@@ -591,6 +591,12 @@
"Appareil externe"
"Appareil connecté"
"Ce téléphone"
+
+
+
+
+
+
"Impossible de faire jouer le contenu sur cet appareil"
"Mettez à jour le compte pour passer à la version payante"
"Lecture des téléchargements impossible ici"
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index f4afc8701609c0a0b330c093c95fc1970c27d4d7..4e7abc938ccf5336c88277ad76d9c5afd102ad6c 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -464,7 +464,7 @@
"Désactiver la cache de transcodage"
"Services en cours d\'exécution"
"Afficher et contrôler les services en cours d\'exécution"
- "Mise en œuvre WebView"
+ "Implémentation WebView"
"Définir la mise en œuvre WebView"
"Ce choix n\'est plus valide. Réessayez."
"Mode de couleur des images"
@@ -591,6 +591,12 @@
"Appareil externe"
"Appareil connecté"
"Ce téléphone"
+
+
+
+
+
+
"Impossible de lire du contenu sur cet appareil"
"Mettez à niveau le compte pour changer"
"Impossible de lire les téléchargements ici"
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index be1fac816f7d92b73ad26227430be8973819b212..a4d3a0a4f751165a903ba77553b644494d804c97 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -591,6 +591,12 @@
"Dispositivo externo"
"Dispositivo conectado"
"Este teléfono"
+
+
+
+
+
+
"Non se pode reproducir contido neste dispositivo"
"Cambia a conta a un plan superior para facer a modificación"
"Non se poden reproducir as descargas neste dispositivo"
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index 05ec0e15da65eb5a04ad10e31a71c9691906ceb5..7a26463bc9bd3a7745f79e8eb7bfed38e86ebb6a 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -591,6 +591,12 @@
"બહારનું ડિવાઇસ"
"કનેક્ટ કરેલું ડિવાઇસ"
"આ ફોન"
+
+
+
+
+
+
"આ ડિવાઇસ પર ચલાવી શકતા નથી"
"સ્વિચ કરવા માટે એકાઉન્ટ અપગ્રેડ કરો"
"ડાઉનલોડ કરેલું કન્ટેન્ટ અહીં ચલાવી શકતા નથી"
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index 352dba79565d0286998d433f7f42a5536e0e4f6f..83cb3989e909fb42afdb60fb109cfc80d5e01c38 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -591,6 +591,12 @@
"बाहरी डिवाइस"
"कनेक्ट किया गया डिवाइस"
"यह फ़ोन"
+
+
+
+
+
+
"इस डिवाइस पर मीडिया नहीं चलाया जा सकता"
"प्रीमियम खाते में स्विच करने के लिए, अपना खाता अपग्रेड करें"
"डाउनलोड किए गए वीडियो यहां नहीं चलाए जा सकते"
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index 2cf02fc2ff39e63514f71be80a46a57f41ab72ef..e78884d65538f38979d713ee1def030646c01578 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -591,6 +591,12 @@
"Vanjski uređaj"
"Povezani uređaj"
"Ovaj telefon"
+
+
+
+
+
+
"Ne može se reproducirati ovdje"
"Nadogradite i prebacite se"
"Ne može se tu reproducirati"
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index 86a959a97cd098ce77f92c7e645ed3978b500de8..ca18ac2e191fa820b3bfa21a62cc6cb67e95f1a5 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -591,6 +591,12 @@
"Külső eszköz"
"Csatlakoztatott eszköz"
"Ez a telefon"
+
+
+
+
+
+
"Nem játszható le ezen az eszközön"
"A váltáshoz frissítse fiókját"
"Itt nem játszhatók le a letöltések"
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index 4c29740b552af4e99ad1e0ff060cb248c8eb6eb0..0749d6042b6baf6723301adc0fd7db4d80ad50e4 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -591,6 +591,12 @@
"Արտաքին սարք"
"Միացված սարք"
"Այս հեռախոսը"
+
+
+
+
+
+
"Հնարավոր չէ նվագարկել այս սարքում"
"Փոխելու համար անցեք հաշվի պրեմիում տարբերակին"
"Ներբեռնումները չեն նվագարկվում այստեղ"
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index bfd8f397be601e451a379e3203628c1100b595fa..7d652c9db6835ef883f952b5dbf405598b3f70b9 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -591,6 +591,12 @@
"Perangkat Eksternal"
"Perangkat yang terhubung"
"Ponsel ini"
+
+
+
+
+
+
"Tidak dapat memutar di perangkat ini"
"Upgrade akun untuk beralih"
"Tidak dapat memutar hasil download di sini"
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index d0184e112fc0185bf24f122eb0382f09cb36a5f7..67f4fe1b9562a32b319bb69a411814a80c16d07c 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -591,6 +591,12 @@
"Ytra tæki"
"Tengt tæki"
"Þessi sími"
+
+
+
+
+
+
"Ekki er hægt að spila í þessu tæki"
"Uppfærðu reikninginn til að skipta"
"Ekki er hægt að spila niðurhal hér"
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index 773aa2659171a78398bd545049fd17b18bd6d4a2..9f7f41b8b16f5401751cf8d9958c620bdd6d7dc2 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -591,6 +591,12 @@
"Dispositivo esterno"
"Dispositivo connesso"
"Questo smartphone"
+
+
+
+
+
+
"Impossibile riprodurre su questo dispositivo"
"Esegui l\'upgrade dell\'account per cambiare"
"Qui non è possibile riprodurre i download"
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index 5f63ed371f424d81cd648040a87d722147336591..056aae170610e7ab6220ccf49a81665f24713c82 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -591,6 +591,12 @@
"מכשיר חיצוני"
"המכשיר המחובר"
"הטלפון הזה"
+
+
+
+
+
+
"לא ניתן להפעיל במכשיר"
"יש לשדרג חשבון כדי לעבור"
"לא ניתן להפעיל הורדות"
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index ae3f1970d20624d52e7b8323f91aa23f5a86ce35..833d1dcf4aefa0369aed61b4d39275899500f4be 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -591,6 +591,12 @@
"外部デバイス"
"接続済みのデバイス"
"このデバイス"
+
+
+
+
+
+
"このデバイスでは再生できません"
"アカウントを更新して切り替えてください"
"再生不可: ダウンロードしたコンテンツ"
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index fe9dbb52cdd06a577d710226eed70ba4cbf1f2b1..acad174698fb1593ce838a12df3e8d3e655be469 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -591,6 +591,12 @@
"გარე მოწყობილობა"
"დაკავშირებული მოწყობილობა"
"ეს ტელეფონი"
+
+
+
+
+
+
"ამ მოწყობილობაზე დაკვრა შეუძლებელია"
"გადასართავად განაახლეთ ანგარიში"
"შეუძლებელია აქ ჩამოტვირ. თამაში"
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index 1162e8f8a00f1130372d409ab0a3aed791e346b9..e2ce5b0e8ef32090825c12cf04d2bbc9b0099740 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -591,6 +591,12 @@
"Сыртқы құрылғы"
"Жалғанған құрылғы"
"Осы телефон"
+
+
+
+
+
+
"Осы құрылғыда ойнату мүмкін емес."
"Ауысу үшін аккаунтты жаңартыңыз."
"Жүктеп алынғандарды осы жерде ойнату мүмкін емес."
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index e6935d0d034eb238ba36bfa82a0305b659dfc882..c06aaeeb4bda182dd6dd0119d8a18eaf0f81a9b3 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -591,6 +591,12 @@
"ឧបករណ៍ខាងក្រៅ"
"ឧបករណ៍ដែលបានភ្ជាប់"
"ទូរសព្ទនេះ"
+
+
+
+
+
+
"មិនអាចចាក់នៅលើឧបករណ៍នេះបានទេ"
"ដំឡើងកម្រិតគណនី ដើម្បីប្ដូរ"
"មិនអាចចាក់ខ្លឹមសារដែលបានទាញយកនៅទីនេះបានទេ"
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index f34a43cfdd195fff91f8b360c26eea0612fb1aff..2c25501e60a79fb4fe95de7111ee4dfa2fb4a4da 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -591,6 +591,12 @@
"ಬಾಹ್ಯ ಸಾಧನ"
"ಕನೆಕ್ಟ್ ಮಾಡಿರುವ ಸಾಧನ"
"ಈ ಫೋನ್"
+
+
+
+
+
+
"ಈ ಸಾಧನದಲ್ಲಿ ಪ್ಲೇ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ"
"ಬದಲಾಯಿಸಲು ಖಾತೆಯನ್ನು ಅಪ್ಗ್ರೇಡ್ ಮಾಡಿ"
"ಇಲ್ಲಿ ಡೌನ್ಲೋಡ್ಗಳನ್ನು ಪ್ಲೇ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ"
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index 1e51ae640301bd5e445b1a5b6bdded3368c58355..f7dc6ae8603dae475b67c9c1a0788830b1509e04 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -591,6 +591,12 @@
"외부 기기"
"연결된 기기"
"이 휴대전화"
+
+
+
+
+
+
"이 기기에서 재생할 수 없음"
"계정을 업그레이드하여 전환하기"
"여기서 다운로드한 콘텐츠를 재생할 수 없습니다."
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index 785bf43bb4d139579dca1ab945e468afcb200c7b..6105db0bf071e97c9abc34429a0c9392db8a56d7 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -591,6 +591,12 @@
"Тышкы түзмөк"
"Туташкан түзмөк"
"Ушул телефон"
+
+
+
+
+
+
"Бул түзмөктө ойнотууга болбойт"
"Премиум аккаунтка которулуу керек"
"Жүктөлүп алынгандар ойнотулбайт"
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index 740586e91f562eeffb52d8d1f2550c260f32901e..df3689e72249d39aa1a0dfbaa4c9c6f0968551d4 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -591,6 +591,12 @@
"ອຸປະກອນພາຍນອກ"
"ອຸປະກອນທີ່ເຊື່ອມຕໍ່"
"ໂທລະສັບນີ້"
+
+
+
+
+
+
"ຫຼິ້ນຢູ່ອຸປະກອນນີ້ບໍ່ໄດ້"
"ອັບເກຣດບັນຊີເພື່ອສະຫຼັບ"
"ບໍ່ສາມາດຫຼິ້ນເນື້ອຫາທີ່ດາວໂຫຼດຢູ່ນີ້ໄດ້"
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index 0c235b8a6f35ff867a2b7fa40b205853aa8a1631..4d9858733f863e8f538e483fca5248b4b0b93918 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -591,6 +591,12 @@
"Išorinis įrenginys"
"Prijungtas įrenginys"
"Šis telefonas"
+
+
+
+
+
+
"Negalima leisti šiame įrenginyje"
"Jei norite perjungti, naujovinkite paskyrą"
"Čia negalima paleisti atsisiuntimų"
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index daaebc880ec9e021109048fbb47a65d3a404ff71..5829826734410e826a09b0a7f49cbf2f9bf7e4f4 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -591,6 +591,12 @@
"Ārēja ierīce"
"Pievienotā ierīce"
"Šis tālrunis"
+
+
+
+
+
+
"Nevar atskaņot šajā ierīcē."
"Lai pārslēgtu, jauniniet kontu"
"Šeit nevar atskaņot lejupielādes"
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index b9d970d8388f9515c63069a9fb08938f0f47a5c9..5d5d480ecd689ec8a493f176865f1931fa9fe202 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -591,6 +591,12 @@
"Надворешен уред"
"Поврзан уред"
"Овој телефон"
+
+
+
+
+
+
"Не може да се пушти на уредов"
"Надградете ја сметката за да се префрлите"
"Не може да се пуштаат преземања тука"
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index 7dd2073642f3902c1b642db9866281f599963508..71406232cb64e0334f35254d9f57ae19178e2d06 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -591,6 +591,12 @@
"ബാഹ്യ ഉപകരണം"
"കണക്റ്റ് ചെയ്ത ഉപകരണം"
"ഈ ഫോൺ"
+
+
+
+
+
+
"ഈ ഉപകരണത്തിൽ പ്ലേ ചെയ്യാൻ കഴിയില്ല"
"അക്കൗണ്ട് മാറാൻ അപ്ഗ്രേഡ് ചെയ്യുക"
"ഡൗൺലോഡുകൾ പ്ലേ ചെയ്യാനാകില്ല"
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index 4f247ab410a55c36b4f68137507b63d53f712c7a..c9e0178ce54fa174aca534326ffff876ef198d43 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -591,6 +591,12 @@
"Гадаад төхөөрөмж"
"Холбогдсон төхөөрөмж"
"Энэ утас"
+
+
+
+
+
+
"Энэ төхөөрөмжид тоглуулах боломжгүй"
"Сэлгэхийн тулд бүртгэлийг сайжруулна уу"
"Татаж авсан файлыг энд тоглуулах боломжгүй"
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index be9464c30241dc31dbcb00240cfe59db0f24fb04..a6596cdf7d0c844762cd317cff5eacabfb8d152a 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -591,6 +591,12 @@
"बाह्य डिव्हाइस"
"कनेक्ट केलेले डिव्हाइस"
"हा फोन"
+
+
+
+
+
+
"या डिव्हाइसवर प्ले करू शकत नाही"
"स्विच करण्यासाठी खाते अपग्रेड करा"
"येथे डाउनलोड प्ले केले जाऊ शकत नाहीत"
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index 8f67d339fba0e8e05228cd9a24fe9d471242e18f..ebde3319a806a675706c46a5429248fab9c10a2f 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -591,6 +591,12 @@
"Peranti Luar"
"Peranti yang disambungkan"
"Telefon ini"
+
+
+
+
+
+
"Tidak dapat dimainkan pada peranti ini"
"Tingkatkan akaun untuk beralih"
"Tidak dapat memainkan muat turun di sini"
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index 2ced73bba26aea1720cd1cb3be83f6532d2051d1..1131007fe1bd2abc062d7d5c8a6fa0863970c39b 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -591,6 +591,12 @@
"ပြင်ပစက်"
"ချိတ်ဆက်ကိရိယာ"
"ဤဖုန်း"
+
+
+
+
+
+
"ဤစက်ပစ္စည်းတွင် ဖွင့်၍မရပါ"
"ပြောင်းရန် အကောင့်အဆင့်ကိုမြှင့်ပါ"
"ဤနေရာတွင် ဒေါင်းလုဒ်များ ဖွင့်မရပါ"
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index e16fea25271ef8d68bdc807c7eccc75bf574a756..1a71ec07457ee918b1f6e0b5928ce33b2124f7ca 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -591,6 +591,12 @@
"Ekstern enhet"
"Tilkoblet enhet"
"Denne telefonen"
+
+
+
+
+
+
"Kan ikke spille på denne enheten"
"Oppgrader kontoen for å bytte"
"Kan ikke spille av nedlastinger her"
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index b26376179c6231d87c57cf2d8f69ccc3efe82ff7..dea9fcce87cf830d60d86f8785a2af04ee5c9690 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -184,7 +184,7 @@
"Android OS"
"हटाइएका एपहरू"
"एपहरू र प्रयोगकर्ताहरू हटाइयो।"
- "प्रणालीसम्बन्धी अद्यावधिकहरू"
+ "प्रणालीसम्बन्धी अपडेटहरू"
"USB टेदरिङ"
"पोर्टेबल हटस्पट"
"ब्लुटुथ टेदर गर्दै"
@@ -591,6 +591,12 @@
"बाह्य डिभाइस"
"कनेक्ट गरिएको डिभाइस"
"यो फोन"
+
+
+
+
+
+
"यो डिभाइसमा मिडिया प्ले गर्न मिल्दैन"
"आफूले प्रयोग गर्न चाहेको खाता अपग्रेड गर्नुहोस्"
"डाउनलोड गरिएका सामग्री यसमा प्ले गर्न मिल्दैन"
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index 75d561762967791c05c4bcb6ae94dbe6d8f24e50..e3be50736a88691be83d9a13e46507dfd39471a9 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -591,6 +591,12 @@
"Extern apparaat"
"Verbonden apparaat"
"Deze telefoon"
+
+
+
+
+
+
"Kan niet afspelen op dit apparaat"
"Upgrade het account om te schakelen"
"Kan hier geen downloads afspelen"
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index ae1df210bce3e1c87f94b38052c01c1928bc3805..ea6fdba27506e3e5465d6d8cc00a8ce81feff805 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -591,6 +591,12 @@
"ଏକ୍ସଟର୍ନଲ ଡିଭାଇସ"
"କନେକ୍ଟ କରାଯାଇଥିବା ଡିଭାଇସ"
"ଏହି ଫୋନ୍"
+
+
+
+
+
+
"ଏହି ଡିଭାଇସରେ ପ୍ଲେ କରାଯାଇପାରିବ ନାହିଁ"
"ସ୍ୱିଚ କରିବା ପାଇଁ ଆକାଉଣ୍ଟକୁ ଅପଗ୍ରେଡ କରନ୍ତୁ"
"ଏଠାରେ ଡାଉନଲୋଡଗୁଡ଼ିକୁ ପ୍ଲେ କରାଯାଇପାରିବ ନାହିଁ"
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index c1ef613f046e4fc795f09349fb694cba38baa0d7..853405167e01feda75fdbd85db614d89722735d4 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -591,6 +591,12 @@
"ਬਾਹਰੀ ਡੀਵਾਈਸ"
"ਕਨੈਕਟ ਕੀਤਾ ਡੀਵਾਈਸ"
"ਇਹ ਫ਼ੋਨ"
+
+
+
+
+
+
"ਇਸ ਡੀਵਾਈਸ \'ਤੇ ਨਹੀਂ ਚਲਾਇਆ ਜਾ ਸਕਦਾ"
"ਸਵਿੱਚ ਕਰਨ ਲਈ ਖਾਤੇ ਨੂੰ ਅੱਪਗ੍ਰੇਡ ਕਰੋ"
"ਡਾਊਨਲੋਡਾਂ ਨੂੰ ਇੱਥੇ ਨਹੀਂ ਚਲਾਇਆ ਜਾ ਸਕਦਾ"
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index 0a8ea16b0279dcbbb8df481ba84e81422bd304a7..a9d4dcbf577aa6de0c05ac4bf373aff0d4987f0c 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -520,7 +520,7 @@
"Szybkie ładowanie"
"Kontrolowane przez administratora"
"Obowiązują ustawienia z ograniczonym dostępem"
- "Wyłączone"
+ "Wyłączona"
"Dozwolone"
"Niedozwolone"
"Instalowanie nieznanych aplikacji"
@@ -591,6 +591,12 @@
"Urządzenie zewnętrzne"
"Połączone urządzenie"
"Ten telefon"
+
+
+
+
+
+
"Nie można odtworzyć na tym urządzeniu"
"Aby przełączyć, potrzebujesz konta premium"
"Tutaj nie można odtworzyć pobranych plików"
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index c39648817af92b7448801cf9c8d4c692a1e0016a..eac646ff4c105fd892fd1fa7d2c6f921a3d89476 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -591,6 +591,12 @@
"Dispositivo externo"
"Dispositivo conectado"
"Neste telefone"
+
+
+
+
+
+
"Não é possível reproduzir neste dispositivo"
"Faça upgrade da conta para trocar"
"Não é possível abrir os downloads aqui"
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index be91222c38f266937e2aca5b7ac7f043677791ef..d8d172d25192c371a9f935bfc9cd73b987252851 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -591,6 +591,12 @@
"Dispositivo externo"
"Dispositivo associado"
"Este telemóvel"
+
+
+
+
+
+
"Não é possível reproduzir neste dispositivo"
"Atualize a conta para mudar"
"Não é possível reproduzir as transferências aqui"
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index c39648817af92b7448801cf9c8d4c692a1e0016a..eac646ff4c105fd892fd1fa7d2c6f921a3d89476 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -591,6 +591,12 @@
"Dispositivo externo"
"Dispositivo conectado"
"Neste telefone"
+
+
+
+
+
+
"Não é possível reproduzir neste dispositivo"
"Faça upgrade da conta para trocar"
"Não é possível abrir os downloads aqui"
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index 4a0023fd63873404907a8c54fe57901e0df9988b..d507b8526c8d102dffed888a017e22c9599b6677 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -196,7 +196,7 @@
"Unele valori prestabilite sunt configurate"
"Nu este configurată nicio valoare prestabilită"
"Setări redare vocală a textului"
- "Setări pentru redarea vocală a textului"
+ "Redare vocală a textului"
"Ritmul vorbirii"
"Viteza cu care este vorbit textul"
"Înălțime"
@@ -591,6 +591,12 @@
"Dispozitiv extern"
"Dispozitiv conectat"
"Acest telefon"
+
+
+
+
+
+
"Nu se poate reda pe acest dispozitiv"
"Fă upgrade contului pentru a comuta"
"Aici nu se pot reda descărcări"
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 91648df5f96fef870802fcb1e4587300d9448589..8d07c57fec56dcb1df666203da4176e2b57955b5 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -283,7 +283,7 @@
"Во время зарядки экран будет всегда включен"
"Включить snoop-логи Bluetooth HCI"
"Сохранять все пакеты Bluetooth (перезапустите Bluetooth после изменения этой настройки)"
- "Заводская разблокировка"
+ "Разблокировка загрузчика"
"Разрешить разблокировку загрузчика ОС"
"Разрешить заводскую разблокировку?"
"ВНИМАНИЕ! Функции защиты не будут работать на устройстве, пока включен этот параметр."
@@ -591,6 +591,12 @@
"Внешнее устройство"
"Подключенное устройство"
"Этот смартфон"
+
+
+
+
+
+
"Невозможно воспроизвести на этом устройстве."
"Для переключения требуется премиум-аккаунт"
"Не удается воспроизвести скачанные файлы"
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index a9004d0ebedc70a8a6bae12564262482bd3e50c8..6694bc552e11130645f978f9bf417f6a34ce433b 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -591,6 +591,12 @@
"බාහිර උපාංගය"
"සම්බන්ධ කළ උපාංගය"
"මෙම දුරකථනය"
+
+
+
+
+
+
"මෙම උපාංගය මත ධාවනය කළ නොහැක"
"මාරු වීමට ගිණුම උත්ශ්රේණි කරන්න"
"මෙහි බාගැනීම් වාදනය කළ නොහැක"
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index 8fc99cfd7416f560efe5dde957cb5a88bd5ed286..fa525a20ca66c9a27935eb4d85082eda7c314b09 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -591,6 +591,12 @@
"Externé zariadenie"
"Pripojené zariadenie"
"Tento telefón"
+
+
+
+
+
+
"V tomto zariadení sa nedá prehrávať obsah"
"Inovujte účet a prejdite naň"
"Tu sa nedajú prehrať stiahnuté súbory"
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index 0945cc042dc5d56059ac167c648fb9d95622b0a4..9b426aa27e19688bcd656c7a395b554882458d0d 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -591,6 +591,12 @@
"Zunanja naprava"
"Povezana naprava"
"Ta telefon"
+
+
+
+
+
+
"Ni mogoče predvajati v tej napravi."
"Za preklop je potrebna nadgradnja računa"
"Prenosov tu ni mogoče predvajati"
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index 0b39551065572d1be0f6d16c16854f75b5d516b8..73cc518dac0aa6ee392c31a586be82cf9c62ae01 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -304,12 +304,12 @@
"Zgjidh versionin AVRCP të Bluetooth-it"
"Versioni MAP i Bluetooth-it"
"Zgjidh versionin MAP të Bluetooth-it"
- "Kodeku Bluetooth Audio"
+ "Kodeku i audios me Bluetooth"
"Aktivizo kodekun e audios me Bluetooth\nZgjedhja"
"Shpejtësia e shembullit të Bluetooth Audio"
"Aktivizo kodekun e audios me Bluetooth\nZgjedhja: Shpejtësia e shembullit"
"Çaktivizimi do të thotë se nuk mbështetet nga telefoni ose kufjet"
- "Bite për shembull Bluetooth Audio"
+ "Bite të audios me Bluetooth për shembull"
"Aktivizo kodekun e audios me Bluetooth\nZgjedhja: Bite për shembull"
"Modaliteti i kanalit të audios me Bluetooth"
"Aktivizo kodekun e audios me Bluetooth\nZgjedhja: Modaliteti i kanalit"
@@ -591,6 +591,12 @@
"Pajisja e jashtme"
"Pajisja e lidhur"
"Ky telefon"
+
+
+
+
+
+
"Nuk mund të luhet në këtë pajisje"
"Përmirëso llogarinë për të ndryshuar"
"Shkarkimet nuk mund të luhen këtu"
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index d351a12bac21cc1a65c3f15fa88c2f11ad4bafd3..d8003d75bd4e176bc997bf68e09837402efbed04 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -591,6 +591,12 @@
"Спољни уређај"
"Повезани уређај"
"Овај телефон"
+
+
+
+
+
+
"Не можете да пустите на овом уређају"
"Надоградите налог ради пребацивања"
"Преузимања не могу да се пуштају овде"
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index 1d7f62ac6c9397b75942e28b55584edf7a031885..f9bd295253a6227ccc2a124132043d1f75359b33 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -235,7 +235,7 @@
- "400 %"
"Välj profil"
- "Privat"
+ "Personlig"
"Jobb"
"Privat"
"Klon"
@@ -591,6 +591,12 @@
"Extern enhet"
"Ansluten enhet"
"Den här telefonen"
+
+
+
+
+
+
"Kan inte spelas på denna enhet"
"Uppgradera kontot för att byta"
"Det går inte att spela upp nedladdningar här"
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index 599113ce6a07203c834e4280f545d8cbe67f79a6..b86be31ec352b531b9c97a423628c1392a5b13d7 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -591,6 +591,12 @@
"Kifaa cha Nje"
"Kifaa kilichounganishwa"
"Simu hii"
+
+
+
+
+
+
"Huwezi kucheza maudhui kwenye kifaa hiki"
"Pata toleo jipya la akaunti ili ubadilishe"
"Imeshindwa kucheza maudhui yaliyopakuliwa hapa"
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index 98412c1f41f47480678e2b66810a6ce9771bdf06..1fd78d3842eb6c5a1f66d17168fdec9280d445b9 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -591,6 +591,12 @@
"வெளிப்புறச் சாதனம்"
"இணைக்கப்பட்டுள்ள சாதனம்"
"இந்த மொபைல்"
+
+
+
+
+
+
"இந்தச் சாதனத்தில் பிளே செய்ய முடியவில்லை"
"மாற்ற, கணக்கை மேம்படுத்துங்கள்"
"பதிவிறக்கங்களை இங்கே பிளே செய்ய முடியாது"
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index 3770bb776627fc21462bcd8d53018aaa371759a3..fc45d2c8e1495281dcab410818915dbf069eab86 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -591,6 +591,12 @@
"ఎక్స్టర్నల్ పరికరం"
"కనెక్ట్ చేసిన పరికరం"
"ఈ ఫోన్"
+
+
+
+
+
+
"ఈ పరికరంలో ప్లే చేయడం సాధ్యపడదు"
"మారడానికి ఖాతాను అప్గ్రేడ్ చేయండి"
"ఇక్కడ డౌన్లోడ్లను ప్లే చేయడం సాధ్యపడదు"
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index 060b7b267624ef983a201c39e2476111b86aeac6..d525bc538ef83548dd06467303bec81b2c4087c1 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -591,6 +591,12 @@
"อุปกรณ์ภายนอก"
"อุปกรณ์ที่เชื่อมต่อ"
"โทรศัพท์เครื่องนี้"
+
+
+
+
+
+
"เล่นในอุปกรณ์นี้ไม่ได้"
"อัปเกรดบัญชีเพื่อเปลี่ยน"
"เล่นเนื้อหาที่ดาวน์โหลดที่นี่ไม่ได้"
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index e869e7f3bbb49020f41a3b394c0ea08027d2dbe0..1df74736d879212b75a316edbf9e394a0d287f3d 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -591,6 +591,12 @@
"External na Device"
"Nakakonektang device"
"Ang teleponong ito"
+
+
+
+
+
+
"Hindi ma-play sa device na ito"
"I-upgrade ang account para lumipat"
"Hindi mape-play ang mga download dito"
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 188f5aa2ce8e96ec5cef71312772e0e5e0b89a7a..d62269605e846dac53a78a9d2c70c57bb40f80a5 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -591,6 +591,12 @@
"Harici Cihaz"
"Bağlı cihaz"
"Bu telefon"
+
+
+
+
+
+
"Bu cihazda oynatılamıyor"
"Geçiş yapmak için hesabı yükseltin"
"İndirilenler burada oynatılamaz"
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index b82db3a8a85fdb0a1c6e22ff6ee0f777e9e4e938..eb10cb209c2093fe823db68dfd4c9fa266aaaff6 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -591,6 +591,12 @@
"Зовнішній пристрій"
"Підключений пристрій"
"Цей телефон"
+
+
+
+
+
+
"Не можна відтворювати тут"
"Потрібний платний обліковий запис"
"Завантаження не відтворюватимуться"
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index 43f03a20e0fc733adac5ccfa04f47553a2f78915..8b2eb3fb018908e71b91425f7cbea5783e2e2a88 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -591,6 +591,12 @@
"بیرونی آلہ"
"منسلک آلہ"
"یہ فون"
+
+
+
+
+
+
"اس آلے پر چلایا نہیں جا سکتا"
"سوئچ کرنے کے لیے اکاؤنٹ اپ گریڈ کریں"
"ڈاؤن لوڈز کو یہاں چلایا نہیں جا سکتا"
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index 685d6e63b0823ee76e652566e6a5041fb1dcd635..62a6303fd45b76df681e7a62f7d279d5ac48f59f 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -591,6 +591,12 @@
"Tashqi qurilma"
"Ulangan qurilma"
"Shu telefon"
+
+
+
+
+
+
"Bu qurilmada ijro etilmaydi"
"Oʻtish uchun hisobingizni yangilang"
"Yuklab olingan fayllar ijro etilmaydi"
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index 7e98afddbe105d40f233d6c6b18477acd5e5fc79..1b90818fbaf9175290d592e60a20caeb053270a2 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -591,6 +591,12 @@
"Thiết bị bên ngoài"
"Thiết bị đã kết nối"
"Điện thoại này"
+
+
+
+
+
+
"Không phát được trên thiết bị này"
"Nâng cấp tài khoản để chuyển đổi"
"Không thể phát các tệp đã tải xuống tại đây"
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index 0f3373e1142f8e57fe6c0ac0fa003ff301013575..94915650223fb2ac1f64b15b6a7685b071588a6a 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -591,6 +591,12 @@
"外部设备"
"连接的设备"
"这部手机"
+
+
+
+
+
+
"无法在此设备上播放"
"升级账号后才能切换"
"无法在此设备上播放下载的内容"
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index c8666ff88a25623e54e1ea0523b932916ef26803..aa3ac06298c5da576fb4a8bc8065da81498eb0c6 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -591,6 +591,12 @@
"外部裝置"
"已連接的裝置"
"這部手機"
+
+
+
+
+
+
"無法在此裝置上播放"
"請升級要切換的帳戶"
"無法在此播放下載內容"
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index 08bf732652b94f7808a54a6f27e708657f95419a..b5eb87da6de3acefa1a7551eaf0c3bb96c731537 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -591,6 +591,12 @@
"外部裝置"
"已連結的裝置"
"這支手機"
+
+
+
+
+
+
"無法在這部裝置上播放"
"請升級要切換的帳戶"
"這裡無法播放下載內容"
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index ad4f04555d05509c65aa0044d5e0c8d9aba64374..57e0b8d8afeb25076fe4d1d23b0016f28f777c47 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -591,6 +591,12 @@
"Idivayisi Yangaphandle"
"Idivayisi exhunyiwe"
"Le foni"
+
+
+
+
+
+
"Ayikwazi ukudlala kule divayisi"
"Thuthukisa i-akhawunti ukuze ushintshe"
"Awukwazi ukudlala okudawunilodiwe lapha"
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index bc144d60d238df4d4465b14650f10155ee8650d0..f03014ca95e286be867b365fd2960bfb17b62d6a 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -821,8 +821,10 @@
Linux development environment
-
- Run Linux terminal on Android
+
+ (Experimental) Run Linux terminal on Android
+
+ If you disable, Linux terminal data will be cleared
HDCP checking
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
index a87b8153b85827c6b55db38d0a2fd3d425d33c54..216574a5fff951d53e6c77d4c88895ee7af24b87 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
@@ -1,6 +1,7 @@
package com.android.settingslib.bluetooth;
import static com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast.UNKNOWN_VALUE_PLACEHOLDER;
+import static com.android.settingslib.flags.Flags.audioSharingHysteresisModeFix;
import static com.android.settingslib.widget.AdaptiveOutlineDrawable.ICON_TYPE_ADVANCED;
import android.annotation.SuppressLint;
@@ -651,6 +652,13 @@ public class BluetoothUtils {
context.getContentResolver()));
}
+ /** Returns if the le audio sharing hysteresis mode fix is available. */
+ @WorkerThread
+ public static boolean isAudioSharingHysteresisModeFixAvailable(@Nullable Context context) {
+ return (audioSharingHysteresisModeFix() && Flags.enableLeAudioSharing())
+ || (context != null && isAudioSharingPreviewEnabled(context.getContentResolver()));
+ }
+
/** Returns if the le audio sharing is enabled. */
public static boolean isAudioSharingEnabled() {
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
@@ -733,13 +741,15 @@ public class BluetoothUtils {
@WorkerThread
public static boolean hasConnectedBroadcastSourceForBtDevice(
@Nullable BluetoothDevice device, @Nullable LocalBluetoothManager localBtManager) {
- if (Flags.audioSharingHysteresisModeFix()) {
+ if (localBtManager == null) {
+ Log.d(TAG, "Skip check hasConnectedBroadcastSourceForBtDevice due to arg is null");
+ return false;
+ }
+ if (isAudioSharingHysteresisModeFixAvailable(localBtManager.getContext())) {
return hasActiveLocalBroadcastSourceForBtDevice(device, localBtManager);
}
LocalBluetoothLeBroadcastAssistant assistant =
- localBtManager == null
- ? null
- : localBtManager.getProfileManager().getLeAudioBroadcastAssistantProfile();
+ localBtManager.getProfileManager().getLeAudioBroadcastAssistantProfile();
if (device == null || assistant == null) {
Log.d(TAG, "Skip check hasConnectedBroadcastSourceForBtDevice due to arg is null");
return false;
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcast.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcast.java
index 6a9d5687370e11b3ff135e4f4cc1318e5c613ed0..dc52b4dafd9bd430941dc071d1a3639c19b90941 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcast.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcast.java
@@ -18,6 +18,8 @@ package com.android.settingslib.bluetooth;
import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
+import static com.android.settingslib.Utils.isAudioModeOngoingCall;
+
import static java.util.stream.Collectors.toList;
import android.annotation.CallbackExecutor;
@@ -54,7 +56,6 @@ import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import com.android.settingslib.R;
-import com.android.settingslib.flags.Flags;
import com.google.common.collect.ImmutableList;
@@ -303,6 +304,7 @@ public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile {
+ ", sourceId = "
+ sourceId);
}
+ updateFallbackActiveDeviceIfNeeded();
}
@Override
@@ -390,9 +392,6 @@ public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile {
+ ", state = "
+ state);
}
- if (BluetoothUtils.isConnected(state)) {
- updateFallbackActiveDeviceIfNeeded();
- }
}
};
@@ -1130,18 +1129,8 @@ public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile {
Log.d(TAG, "Skip updateFallbackActiveDeviceIfNeeded for work profile.");
return;
}
- if (mServiceBroadcast == null) {
- Log.d(TAG, "Skip updateFallbackActiveDeviceIfNeeded due to broadcast profile is null");
- return;
- }
- List sources = mServiceBroadcast.getAllBroadcastMetadata();
- if (sources.stream()
- .noneMatch(source -> mServiceBroadcast.isPlaying(source.getBroadcastId()))) {
- Log.d(TAG, "Skip updateFallbackActiveDeviceIfNeeded due to no broadcast ongoing");
- return;
- }
- if (mServiceBroadcastAssistant == null) {
- Log.d(TAG, "Skip updateFallbackActiveDeviceIfNeeded due to assistant profile is null");
+ if (isAudioModeOngoingCall(mContext)) {
+ Log.d(TAG, "Skip updateFallbackActiveDeviceIfNeeded due to ongoing call");
return;
}
Map> deviceGroupsInBroadcast = getDeviceGroupsInBroadcast();
@@ -1152,7 +1141,7 @@ public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile {
int targetGroupId = BluetoothCsipSetCoordinator.GROUP_ID_INVALID;
int fallbackActiveGroupId = BluetoothUtils.getPrimaryGroupIdForBroadcast(
mContext.getContentResolver());
- if (Flags.audioSharingHysteresisModeFix()) {
+ if (BluetoothUtils.isAudioSharingHysteresisModeFixAvailable(mContext)) {
int userPreferredPrimaryGroupId = getUserPreferredPrimaryGroupId();
if (userPreferredPrimaryGroupId != BluetoothCsipSetCoordinator.GROUP_ID_INVALID
&& deviceGroupsInBroadcast.containsKey(userPreferredPrimaryGroupId)) {
@@ -1193,7 +1182,8 @@ public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile {
@NonNull
private Map> getDeviceGroupsInBroadcast() {
- boolean hysteresisModeFixEnabled = Flags.audioSharingHysteresisModeFix();
+ boolean hysteresisModeFixEnabled =
+ BluetoothUtils.isAudioSharingHysteresisModeFixAvailable(mContext);
List connectedDevices = mServiceBroadcastAssistant.getConnectedDevices();
return connectedDevices.stream()
.filter(
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcastAssistantCallbackExt.kt b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcastAssistantCallbackExt.kt
index 91a99aed6db5dbe384b741a09a3998eb5f2fd22d..a0a6d2698d8c69cdd6eca49b85cb4d935aa7af14 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcastAssistantCallbackExt.kt
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcastAssistantCallbackExt.kt
@@ -35,11 +35,7 @@ val LocalBluetoothLeBroadcastAssistant.onSourceConnectedOrRemoved: Flow
sink: BluetoothDevice,
sourceId: Int,
state: BluetoothLeBroadcastReceiveState
- ) {
- if (BluetoothUtils.isConnected(state)) {
- launch { send(Unit) }
- }
- }
+ ) {}
override fun onSourceRemoved(sink: BluetoothDevice, sourceId: Int, reason: Int) {
launch { send(Unit) }
@@ -55,7 +51,9 @@ val LocalBluetoothLeBroadcastAssistant.onSourceConnectedOrRemoved: Flow
override fun onSourceFound(source: BluetoothLeBroadcastMetadata) {}
- override fun onSourceAdded(sink: BluetoothDevice, sourceId: Int, reason: Int) {}
+ override fun onSourceAdded(sink: BluetoothDevice, sourceId: Int, reason: Int) {
+ launch { send(Unit) }
+ }
override fun onSourceAddFailed(
sink: BluetoothDevice,
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/data/repository/DeviceSettingServiceConnection.kt b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/data/repository/DeviceSettingServiceConnection.kt
index edd49c5a8fb793308098289a9382688f8bc778b4..0209eb8c3fbf8cd8588a269ee5b77f2c04ef38b2 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/data/repository/DeviceSettingServiceConnection.kt
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/data/repository/DeviceSettingServiceConnection.kt
@@ -21,6 +21,7 @@ import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
+import android.os.DeadObjectException
import android.os.IBinder
import android.os.IInterface
import android.os.RemoteException
@@ -52,6 +53,7 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.callbackFlow
+import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.emitAll
import kotlinx.coroutines.flow.filterIsInstance
@@ -304,6 +306,14 @@ class DeviceSettingServiceConnection(
service.registerDeviceSettingsListener(deviceInfo, listener)
awaitClose { service.unregisterDeviceSettingsListener(deviceInfo, listener) }
}
+ .catch { e ->
+ if (e is DeadObjectException) {
+ Log.e(TAG, "DeadObjectException happens when registering listener.", e)
+ emit(listOf())
+ } else {
+ throw e
+ }
+ }
.stateIn(coroutineScope, SharingStarted.WhileSubscribed(), emptyList())
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/InputMediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/InputMediaDevice.java
index 83ee9751329fe941646938351a5f60d698d8f974..80e5e59819125a996ec8fe66f027d71f10735881 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/InputMediaDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/InputMediaDevice.java
@@ -15,6 +15,7 @@
*/
package com.android.settingslib.media;
+import static android.media.AudioDeviceInfo.TYPE_BLE_HEADSET;
import static android.media.AudioDeviceInfo.TYPE_BLUETOOTH_SCO;
import static android.media.AudioDeviceInfo.TYPE_BUILTIN_MIC;
import static android.media.AudioDeviceInfo.TYPE_USB_ACCESSORY;
@@ -103,7 +104,8 @@ public class InputMediaDevice extends MediaDevice {
TYPE_USB_DEVICE,
TYPE_USB_HEADSET,
TYPE_USB_ACCESSORY,
- TYPE_BLUETOOTH_SCO ->
+ TYPE_BLUETOOTH_SCO,
+ TYPE_BLE_HEADSET ->
true;
default -> false;
};
@@ -124,7 +126,7 @@ public class InputMediaDevice extends MediaDevice {
mProductName != null
? mProductName
: mContext.getString(R.string.media_transfer_usb_device_mic_name);
- case TYPE_BLUETOOTH_SCO ->
+ case TYPE_BLUETOOTH_SCO, TYPE_BLE_HEADSET ->
mProductName != null
? mProductName
: mContext.getString(R.string.media_transfer_bt_device_mic_name);
diff --git a/packages/SettingsLib/src/com/android/settingslib/notification/data/repository/ZenModeRepository.kt b/packages/SettingsLib/src/com/android/settingslib/notification/data/repository/ZenModeRepository.kt
index 7fdbcdae2276e9583505d23e5665fc27ae2b3237..f446bb8e32d1dca0cb07eb5e1d6e3fe1f449f3ee 100644
--- a/packages/SettingsLib/src/com/android/settingslib/notification/data/repository/ZenModeRepository.kt
+++ b/packages/SettingsLib/src/com/android/settingslib/notification/data/repository/ZenModeRepository.kt
@@ -93,33 +93,23 @@ class ZenModeRepositoryImpl(
IntentFilter().apply {
addAction(NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED)
addAction(NotificationManager.ACTION_NOTIFICATION_POLICY_CHANGED)
- if (Flags.volumePanelBroadcastFix() && android.app.Flags.modesApi())
+ if (android.app.Flags.modesApi())
addAction(
- NotificationManager.ACTION_CONSOLIDATED_NOTIFICATION_POLICY_CHANGED)
+ NotificationManager.ACTION_CONSOLIDATED_NOTIFICATION_POLICY_CHANGED
+ )
},
/* broadcastPermission = */ null,
- /* scheduler = */ if (Flags.volumePanelBroadcastFix()) {
- backgroundHandler
- } else {
- null
- },
+ /* scheduler = */ backgroundHandler,
)
awaitClose { context.unregisterReceiver(receiver) }
}
- .let {
- if (Flags.volumePanelBroadcastFix()) {
- // Share the flow to avoid having multiple broadcasts.
- it.flowOn(backgroundCoroutineContext)
- .shareIn(started = SharingStarted.WhileSubscribed(), scope = scope)
- } else {
- it.shareIn(started = SharingStarted.WhileSubscribed(), scope = scope)
- }
- }
+ .flowOn(backgroundCoroutineContext)
+ .shareIn(started = SharingStarted.WhileSubscribed(), scope = scope)
}
override val consolidatedNotificationPolicy: StateFlow by lazy {
- if (Flags.volumePanelBroadcastFix() && android.app.Flags.modesApi())
+ if (android.app.Flags.modesApi())
flowFromBroadcast(NotificationManager.ACTION_CONSOLIDATED_NOTIFICATION_POLICY_CHANGED) {
// If available, get the value from extras to avoid a potential binder call.
it?.extras?.getParcelable(EXTRA_NOTIFICATION_POLICY)
@@ -161,11 +151,13 @@ class ZenModeRepositoryImpl(
contentResolver.registerContentObserver(
Settings.Global.getUriFor(Settings.Global.ZEN_MODE),
/* notifyForDescendants= */ false,
- observer)
+ observer,
+ )
contentResolver.registerContentObserver(
Settings.Global.getUriFor(Settings.Global.ZEN_MODE_CONFIG_ETAG),
/* notifyForDescendants= */ false,
- observer)
+ observer,
+ )
awaitClose { contentResolver.unregisterContentObserver(observer) }
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/notification/modes/TestModeBuilder.java b/packages/SettingsLib/src/com/android/settingslib/notification/modes/TestModeBuilder.java
index 5eeb49a0b398bdd2f2fdc9c5659169bbf3e3834a..6842d0a949af858ecaf2c49a4bd2054677106867 100644
--- a/packages/SettingsLib/src/com/android/settingslib/notification/modes/TestModeBuilder.java
+++ b/packages/SettingsLib/src/com/android/settingslib/notification/modes/TestModeBuilder.java
@@ -204,6 +204,13 @@ public class TestModeBuilder {
return this;
}
+ public TestModeBuilder implicitForPackage(String pkg) {
+ setPackage(pkg);
+ setId(ZenModeConfig.implicitRuleId(pkg));
+ setName("Do Not Disturb (" + pkg + ")");
+ return this;
+ }
+
public TestModeBuilder setActive(boolean active) {
if (active) {
mConfigZenRule.enabled = true;
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 3cc111f6e0998222253be26ff13eb77488256788..d5cfe55813eeed4ecfcce14aed6ea8776e23306d 100644
--- a/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenMode.java
+++ b/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenMode.java
@@ -24,7 +24,6 @@ import static android.app.NotificationManager.INTERRUPTION_FILTER_NONE;
import static android.app.NotificationManager.INTERRUPTION_FILTER_PRIORITY;
import static android.service.notification.SystemZenRules.getTriggerDescriptionForScheduleEvent;
import static android.service.notification.SystemZenRules.getTriggerDescriptionForScheduleTime;
-import static android.service.notification.ZenModeConfig.tryParseCountdownConditionId;
import static android.service.notification.ZenModeConfig.tryParseEventConditionId;
import static android.service.notification.ZenModeConfig.tryParseScheduleConditionId;
@@ -208,6 +207,11 @@ public class ZenMode implements Parcelable {
return Strings.nullToEmpty(mRule.getName());
}
+ @NonNull
+ public Kind getKind() {
+ return mKind;
+ }
+
@NonNull
public Status getStatus() {
return mStatus;
@@ -224,27 +228,6 @@ public class ZenMode implements Parcelable {
return mRule.getTriggerDescription();
}
- /**
- * Returns a "dynamic" trigger description. For some modes (such as manual Do Not Disturb)
- * when activated, we know when (and if) the mode is expected to end on its own; this dynamic
- * description reflects that. In other cases, returns {@link #getTriggerDescription}.
- */
- @Nullable
- public String getDynamicDescription(Context context) {
- if (isManualDnd() && isActive()) {
- long countdownEndTime = tryParseCountdownConditionId(mRule.getConditionId());
- if (countdownEndTime > 0) {
- CharSequence formattedTime = ZenModeConfig.getFormattedTime(context,
- countdownEndTime, ZenModeConfig.isToday(countdownEndTime),
- context.getUserId());
- return context.getString(com.android.internal.R.string.zen_mode_until,
- formattedTime);
- }
- }
-
- return getTriggerDescription();
- }
-
/**
* Returns the {@link ZenIcon.Key} corresponding to the icon resource for this mode. This can be
* either app-provided (via {@link AutomaticZenRule#setIconResId}, user-chosen (via the icon
diff --git a/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenModeDescriptions.java b/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenModeDescriptions.java
new file mode 100644
index 0000000000000000000000000000000000000000..f5776989917e22a61b468a60d5c89c9f834ced3a
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenModeDescriptions.java
@@ -0,0 +1,86 @@
+/*
+ * 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.settingslib.notification.modes;
+
+import static android.app.AutomaticZenRule.TYPE_SCHEDULE_TIME;
+import static android.service.notification.ZenModeConfig.tryParseCountdownConditionId;
+
+import android.content.Context;
+import android.service.notification.SystemZenRules;
+import android.service.notification.ZenModeConfig;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.google.common.base.Strings;
+
+public final class ZenModeDescriptions {
+
+ private final Context mContext;
+
+ public ZenModeDescriptions(@NonNull Context context) {
+ mContext = context;
+ }
+
+ /**
+ * Returns a version of the mode's trigger description that might be "dynamic".
+ *
+ * For some modes (such as manual Do Not Disturb) when activated, we know when (and if) the
+ * mode is expected to end on its own; this description reflects that. In other cases,
+ * returns {@link ZenMode#getTriggerDescription}.
+ */
+ @Nullable
+ public String getTriggerDescription(@NonNull ZenMode mode) {
+ if (mode.isManualDnd() && mode.isActive()) {
+ long countdownEndTime = tryParseCountdownConditionId(mode.getRule().getConditionId());
+ if (countdownEndTime > 0) {
+ CharSequence formattedTime = ZenModeConfig.getFormattedTime(mContext,
+ countdownEndTime, ZenModeConfig.isToday(countdownEndTime),
+ mContext.getUserId());
+ return mContext.getString(com.android.internal.R.string.zen_mode_until,
+ formattedTime);
+ }
+ }
+
+ return Strings.emptyToNull(mode.getTriggerDescription());
+ }
+
+ /**
+ * Returns a version of the {@link ZenMode} trigger description that is suitable for
+ * accessibility (for example, where abbreviations are expanded to full words).
+ *
+ *
Returns {@code null} If the standard trigger description (returned by
+ * {@link #getTriggerDescription}) is sufficient.
+ */
+ @Nullable
+ public String getTriggerDescriptionForAccessibility(@NonNull ZenMode mode) {
+ // Only one special case: time-based schedules, where we want to use full day names.
+ if (mode.isSystemOwned() && mode.getType() == TYPE_SCHEDULE_TIME) {
+ ZenModeConfig.ScheduleInfo schedule = ZenModeConfig.tryParseScheduleConditionId(
+ mode.getRule().getConditionId());
+ if (schedule != null) {
+ String fullDaysSummary = SystemZenRules.getDaysOfWeekFull(mContext, schedule);
+ if (fullDaysSummary != null) {
+ return fullDaysSummary + ", " + SystemZenRules.getTimeSummary(mContext,
+ schedule);
+ }
+ }
+ }
+
+ return null;
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/volume/data/repository/AudioSharingRepository.kt b/packages/SettingsLib/src/com/android/settingslib/volume/data/repository/AudioSharingRepository.kt
index b41e9703d427c6eea3ad21ed356dfd3853d2e907..4c4ce2a61851ed3dbadf3f289fd355f0f8854823 100644
--- a/packages/SettingsLib/src/com/android/settingslib/volume/data/repository/AudioSharingRepository.kt
+++ b/packages/SettingsLib/src/com/android/settingslib/volume/data/repository/AudioSharingRepository.kt
@@ -221,6 +221,7 @@ class AudioSharingRepositoryImpl(
override suspend fun audioSharingAvailable(): Boolean {
return withContext(backgroundCoroutineContext) {
BluetoothUtils.isAudioSharingEnabled()
+ || BluetoothUtils.isAudioSharingPreviewEnabled(contentResolver)
}
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/volume/shared/AudioSharingLogger.kt b/packages/SettingsLib/src/com/android/settingslib/volume/shared/AudioSharingLogger.kt
index 18a4c6d1748dbb025e7b5555224ff5b872c6bd95..791d86611b069ff8752cd354e2e3983f76a41bea 100644
--- a/packages/SettingsLib/src/com/android/settingslib/volume/shared/AudioSharingLogger.kt
+++ b/packages/SettingsLib/src/com/android/settingslib/volume/shared/AudioSharingLogger.kt
@@ -26,4 +26,6 @@ interface AudioSharingLogger {
fun onVolumeMapChanged(map: Map)
fun onSetDeviceVolumeRequested(volume: Int)
+
+ fun onAudioSharingAvailabilityRequestedError(requestFrom: String, e: String)
}
\ No newline at end of file
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/volume/data/repository/FakeAudioSharingRepositoryLogger.kt b/packages/SettingsLib/tests/integ/src/com/android/settingslib/volume/data/repository/FakeAudioSharingRepositoryLogger.kt
index cc4cc8d4ab96803e55adf502f4da4b2e166515cf..731b3a136cd7e40c1351addc72d98eef1994a891 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/volume/data/repository/FakeAudioSharingRepositoryLogger.kt
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/volume/data/repository/FakeAudioSharingRepositoryLogger.kt
@@ -43,4 +43,8 @@ class FakeAudioSharingRepositoryLogger : AudioSharingLogger {
override fun onSetDeviceVolumeRequested(volume: Int) {
mutableLogs.add("onSetVolumeRequested volume=$volume")
}
+
+ override fun onAudioSharingAvailabilityRequestedError(requestFrom: String, e: String) {
+ mutableLogs.add("onAudioSharingAvailabilityRequestedError, requestFrom=$requestFrom")
+ }
}
\ No newline at end of file
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothUtilsTest.java
index 6d481dbe64e9c9ae2bcece203aca95848aa1857a..fa5d54283a17f5f162528e9d116d1f63e3e81922 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothUtilsTest.java
@@ -1256,4 +1256,40 @@ public class BluetoothUtilsTest {
assertThat(BluetoothUtils.isAudioSharingUIAvailable(mContext)).isTrue();
}
+
+ @Test
+ public void isAudioSharingHysteresisModeFixAvailable_mainAndPreviewFlagOff_returnsFalse() {
+ mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
+ mSetFlagsRule.enableFlags(Flags.FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX);
+ mSetFlagsRule.disableFlags(Flags.FLAG_AUDIO_SHARING_DEVELOPER_OPTION);
+
+ assertThat(BluetoothUtils.isAudioSharingHysteresisModeFixAvailable(mContext)).isFalse();
+ }
+
+ @Test
+ public void isAudioSharingHysteresisModeFixAvailable_hysteresisFixFlagOff_returnsFalse() {
+ mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
+ mSetFlagsRule.disableFlags(Flags.FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX);
+ mSetFlagsRule.disableFlags(Flags.FLAG_AUDIO_SHARING_DEVELOPER_OPTION);
+
+ assertThat(BluetoothUtils.isAudioSharingHysteresisModeFixAvailable(mContext)).isFalse();
+ }
+
+ @Test
+ public void isAudioSharingHysteresisModeFixAvailable_previewFlagOn_returnsTrue() {
+ mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
+ mSetFlagsRule.disableFlags(Flags.FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX);
+ mSetFlagsRule.enableFlags(Flags.FLAG_AUDIO_SHARING_DEVELOPER_OPTION);
+
+ assertThat(BluetoothUtils.isAudioSharingHysteresisModeFixAvailable(mContext)).isTrue();
+ }
+
+ @Test
+ public void isAudioSharingHysteresisModeFixAvailable_mainAndPreviewFlagOn_returnsTrue() {
+ mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
+ mSetFlagsRule.enableFlags(Flags.FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX);
+ mSetFlagsRule.disableFlags(Flags.FLAG_AUDIO_SHARING_DEVELOPER_OPTION);
+
+ assertThat(BluetoothUtils.isAudioSharingHysteresisModeFixAvailable(mContext)).isTrue();
+ }
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InputMediaDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InputMediaDeviceTest.java
index 7775b912e51d4ee9d7dac4830f99f976d742cdda..8624c4df833bd67e6219e45b407ba1e8e0a51d25 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InputMediaDeviceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InputMediaDeviceTest.java
@@ -38,6 +38,7 @@ public class InputMediaDeviceTest {
private final int WIRED_HEADSET_ID = 2;
private final int USB_HEADSET_ID = 3;
private final int BT_HEADSET_ID = 4;
+ private final int BLE_HEADSET_ID = 5;
private final int MAX_VOLUME = 1;
private final int CURRENT_VOLUME = 0;
private final boolean IS_VOLUME_FIXED = true;
@@ -45,6 +46,7 @@ public class InputMediaDeviceTest {
private static final String PRODUCT_NAME_WIRED_HEADSET = "My Wired Headset";
private static final String PRODUCT_NAME_USB_HEADSET = "My USB Headset";
private static final String PRODUCT_NAME_BT_HEADSET = "My Bluetooth Headset";
+ private static final String PRODUCT_NAME_BLE_HEADSET = "My BLE Headset";
@Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
@@ -163,4 +165,35 @@ public class InputMediaDeviceTest {
assertThat(btMediaDevice.getName())
.isEqualTo(mContext.getString(R.string.media_transfer_bt_device_mic_name));
}
+
+ @Test
+ public void getName_returnCorrectName_bleHeadset() {
+ InputMediaDevice bleMediaDevice =
+ InputMediaDevice.create(
+ mContext,
+ String.valueOf(BLE_HEADSET_ID),
+ AudioDeviceInfo.TYPE_BLE_HEADSET,
+ MAX_VOLUME,
+ CURRENT_VOLUME,
+ IS_VOLUME_FIXED,
+ PRODUCT_NAME_BLE_HEADSET);
+ assertThat(bleMediaDevice).isNotNull();
+ assertThat(bleMediaDevice.getName()).isEqualTo(PRODUCT_NAME_BLE_HEADSET);
+ }
+
+ @Test
+ public void getName_returnCorrectName_bleHeadset_nullProductName() {
+ InputMediaDevice bleMediaDevice =
+ InputMediaDevice.create(
+ mContext,
+ String.valueOf(BLE_HEADSET_ID),
+ AudioDeviceInfo.TYPE_BLE_HEADSET,
+ MAX_VOLUME,
+ CURRENT_VOLUME,
+ IS_VOLUME_FIXED,
+ null);
+ assertThat(bleMediaDevice).isNotNull();
+ assertThat(bleMediaDevice.getName())
+ .isEqualTo(mContext.getString(R.string.media_transfer_bt_device_mic_name));
+ }
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/data/repository/ZenModeRepositoryTest.kt b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/data/repository/ZenModeRepositoryTest.kt
index c136644e095973782579a3ab22146505ca70b2dc..388af61c627392776af23378f92677f71bb1e6bf 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/data/repository/ZenModeRepositoryTest.kt
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/data/repository/ZenModeRepositoryTest.kt
@@ -23,12 +23,10 @@ import android.content.Context
import android.content.Intent
import android.database.ContentObserver
import android.os.Parcelable
-import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
import android.platform.test.flag.junit.SetFlagsRule
import android.provider.Settings.Global
import androidx.test.filters.SmallTest
-import com.android.settingslib.flags.Flags
import com.android.settingslib.notification.modes.TestModeBuilder
import com.android.settingslib.notification.modes.ZenMode
import com.android.settingslib.notification.modes.ZenModesBackend
@@ -93,26 +91,7 @@ class ZenModeRepositoryTest {
)
}
- @DisableFlags(Flags.FLAG_VOLUME_PANEL_BROADCAST_FIX)
- @Test
- fun consolidatedPolicyChanges_repositoryEmits_flagsOff() {
- testScope.runTest {
- val values = mutableListOf()
- `when`(notificationManager.consolidatedNotificationPolicy).thenReturn(testPolicy1)
- underTest.consolidatedNotificationPolicy
- .onEach { values.add(it) }
- .launchIn(backgroundScope)
- runCurrent()
-
- `when`(notificationManager.consolidatedNotificationPolicy).thenReturn(testPolicy2)
- triggerIntent(NotificationManager.ACTION_NOTIFICATION_POLICY_CHANGED)
- runCurrent()
-
- assertThat(values).containsExactly(null, testPolicy1, testPolicy2).inOrder()
- }
- }
-
- @EnableFlags(android.app.Flags.FLAG_MODES_API, Flags.FLAG_VOLUME_PANEL_BROADCAST_FIX)
+ @EnableFlags(android.app.Flags.FLAG_MODES_API)
@Test
fun consolidatedPolicyChanges_repositoryEmits_flagsOn() {
testScope.runTest {
@@ -131,7 +110,7 @@ class ZenModeRepositoryTest {
}
}
- @EnableFlags(android.app.Flags.FLAG_MODES_API, Flags.FLAG_VOLUME_PANEL_BROADCAST_FIX)
+ @EnableFlags(android.app.Flags.FLAG_MODES_API)
@Test
fun consolidatedPolicyChanges_repositoryEmitsFromExtras() {
testScope.runTest {
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModeDescriptionsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModeDescriptionsTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..2b3accdbb906a1606e563a082aca500f3af752d7
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModeDescriptionsTest.java
@@ -0,0 +1,60 @@
+/*
+ * 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.settingslib.notification.modes;
+
+import static android.app.AutomaticZenRule.TYPE_SCHEDULE_TIME;
+import static android.service.notification.SystemZenRules.PACKAGE_ANDROID;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.service.notification.ZenModeConfig;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+import java.util.Calendar;
+
+@RunWith(RobolectricTestRunner.class)
+public class ZenModeDescriptionsTest {
+
+ private final ZenModeDescriptions mDescriptions = new ZenModeDescriptions(
+ RuntimeEnvironment.getApplication());
+
+ @Test
+ public void getTriggerDescriptionForAccessibility_scheduleTime_usesFullDays() {
+ ZenModeConfig.ScheduleInfo scheduleInfo = new ZenModeConfig.ScheduleInfo();
+ scheduleInfo.days = new int[] { Calendar.MONDAY };
+ scheduleInfo.startHour = 11;
+ scheduleInfo.endHour = 15;
+ ZenMode mode = new TestModeBuilder()
+ .setPackage(PACKAGE_ANDROID)
+ .setType(TYPE_SCHEDULE_TIME)
+ .setConditionId(ZenModeConfig.toScheduleConditionId(scheduleInfo))
+ .build();
+
+ assertThat(mDescriptions.getTriggerDescriptionForAccessibility(mode))
+ .isEqualTo("Monday, 11:00 AM - 3:00 PM");
+ }
+
+ @Test
+ public void getTriggerDescriptionForAccessibility_otherMode_isNull() {
+ ZenMode mode = new TestModeBuilder().setTriggerDescription("When December ends").build();
+ assertThat(mDescriptions.getTriggerDescriptionForAccessibility(mode)).isNull();
+ }
+}
diff --git a/packages/SettingsProvider/res/xml/bookmarks.xml b/packages/SettingsProvider/res/xml/bookmarks.xml
index 22d02262c3882142cb14f34e31643aef2a73c104..645b275e2af508f3c0ac135085566ddf4aaf698e 100644
--- a/packages/SettingsProvider/res/xml/bookmarks.xml
+++ b/packages/SettingsProvider/res/xml/bookmarks.xml
@@ -32,6 +32,9 @@
'y': YouTube
-->
+
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
index 8f58e8cd19733b8acd98410e4d392282f3d5531f..c90ba8249d54e41444d00714f84ca90a72b1eb24 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
@@ -462,5 +462,7 @@ public class GlobalSettingsValidators {
Global.Wearable.PHONE_SWITCHING_REQUEST_SOURCE_NONE,
Global.Wearable.PHONE_SWITCHING_REQUEST_SOURCE_COMPANION
));
+ VALIDATORS.put(Global.HEARING_DEVICE_LOCAL_AMBIENT_VOLUME, ANY_STRING_VALIDATOR);
+ VALIDATORS.put(Global.HEARING_DEVICE_LOCAL_NOTIFICATION, ANY_STRING_VALIDATOR);
}
}
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java
index 558ccaf7a7072f748665d75b3eaffd12773583eb..509b88b257fef50d26b8cf0d1e1bf2ca8cbe5b8a 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java
@@ -263,6 +263,5 @@ public class SystemSettingsValidators {
VALIDATORS.put(System.NOTIFICATION_COOLDOWN_ENABLED, BOOLEAN_VALIDATOR);
VALIDATORS.put(System.NOTIFICATION_COOLDOWN_ALL, BOOLEAN_VALIDATOR);
VALIDATORS.put(System.NOTIFICATION_COOLDOWN_VIBRATE_UNLOCKED, BOOLEAN_VALIDATOR);
- VALIDATORS.put(System.HEARING_DEVICE_LOCAL_AMBIENT_VOLUME, ANY_STRING_VALIDATOR);
}
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java b/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java
index fbce6ca07b3ecb4b15fa76ea574d1ff13b31a146..aca2c4ef2a4973a878ea59bda0a155eda59417a3 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java
@@ -16,6 +16,7 @@
package com.android.providers.settings;
+import static android.provider.DeviceConfig.DUMP_ARG_NAMESPACE;
import static android.provider.Settings.Config.SYNC_DISABLED_MODE_NONE;
import static android.provider.Settings.Config.SYNC_DISABLED_MODE_PERSISTENT;
import static android.provider.Settings.Config.SYNC_DISABLED_MODE_UNTIL_REBOOT;
@@ -42,6 +43,7 @@ import android.provider.DeviceConfigShellCommandHandler;
import android.provider.Settings;
import android.provider.Settings.Config.SyncDisabledMode;
import android.provider.UpdatableDeviceConfigServiceReadiness;
+import android.util.Log;
import android.util.Slog;
import com.android.internal.util.FastPrintWriter;
@@ -55,11 +57,13 @@ import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.regex.Pattern;
/**
* Receives shell commands from the command line related to device config flags, and dispatches them
@@ -80,6 +84,7 @@ public final class DeviceConfigService extends Binder {
final SettingsProvider mProvider;
private static final String TAG = "DeviceConfigService";
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
public DeviceConfigService(SettingsProvider provider) {
mProvider = provider;
@@ -97,14 +102,35 @@ public final class DeviceConfigService extends Binder {
}
}
+ // TODO(b/364399200): add unit test
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ String filter = null;
if (android.provider.flags.Flags.dumpImprovements()) {
- pw.print("SyncDisabledForTests: ");
- MyShellCommand.getSyncDisabledForTests(pw, pw);
+ if (args.length > 0) {
+ switch (args[0]) {
+ case DUMP_ARG_NAMESPACE:
+ if (args.length < 2) {
+ throw new IllegalArgumentException("argument " + DUMP_ARG_NAMESPACE
+ + " requires an extra argument");
+ }
+ filter = args[1];
+ if (DEBUG) {
+ Slog.d(TAG, "dump(): setting filter as " + filter);
+ }
+ break;
+ default:
+ Slog.w(TAG, "dump(): ignoring invalid arguments: " + Arrays.toString(args));
+ break;
+ }
+ }
+ if (filter == null) {
+ pw.print("SyncDisabledForTests: ");
+ MyShellCommand.getSyncDisabledForTests(pw, pw);
- pw.print("UpdatableDeviceConfigServiceReadiness.shouldStartUpdatableService(): ");
- pw.println(UpdatableDeviceConfigServiceReadiness.shouldStartUpdatableService());
+ pw.print("UpdatableDeviceConfigServiceReadiness.shouldStartUpdatableService(): ");
+ pw.println(UpdatableDeviceConfigServiceReadiness.shouldStartUpdatableService());
+ }
pw.println("DeviceConfig provider: ");
try (ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(fd)) {
@@ -117,8 +143,16 @@ public final class DeviceConfigService extends Binder {
IContentProvider iprovider = mProvider.getIContentProvider();
pw.println("DeviceConfig flags:");
+ Pattern lineFilter = filter == null ? null : Pattern.compile("^.*" + filter + ".*\\/.*$");
for (String line : MyShellCommand.listAll(iprovider)) {
- pw.println(line);
+ if (lineFilter == null || lineFilter.matcher(line).matches()) {
+ pw.println(line);
+ }
+ }
+
+ if (filter != null) {
+ // TODO(b/364399200): use filter to skip instead?
+ return;
}
ArrayList missingFiles = new ArrayList();
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index c2beaa8048f66cd97b57e10b02d457a30280ff59..9de7faf04df60cebe706b8f0b961162afa3f171d 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -564,6 +564,8 @@ public class SettingsBackupTest {
Settings.Global.MANAGED_PROVISIONING_DEFER_PROVISIONING_TO_ROLE_HOLDER,
Settings.Global.REVIEW_PERMISSIONS_NOTIFICATION_STATE,
Settings.Global.ENABLE_BACK_ANIMATION, // Temporary for T, dev option only
+ Settings.Global.HEARING_DEVICE_LOCAL_AMBIENT_VOLUME, // cache per hearing device
+ Settings.Global.HEARING_DEVICE_LOCAL_NOTIFICATION, // cache per hearing device
Settings.Global.Wearable.COMBINED_LOCATION_ENABLE,
Settings.Global.Wearable.HAS_PAY_TOKENS,
Settings.Global.Wearable.GMS_CHECKIN_TIMEOUT_MIN,
@@ -944,8 +946,7 @@ public class SettingsBackupTest {
Settings.System.WEAR_ACCESSIBILITY_GESTURE_ENABLED_DURING_OOBE,
Settings.System.WEAR_TTS_PREWARM_ENABLED,
Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ,
- Settings.System.MULTI_AUDIO_FOCUS_ENABLED, // form-factor/OEM specific
- Settings.System.HEARING_DEVICE_LOCAL_AMBIENT_VOLUME // internal cache
+ Settings.System.MULTI_AUDIO_FOCUS_ENABLED // form-factor/OEM specific
);
if (!Flags.backUpSmoothDisplayAndForcePeakRefreshRate()) {
settings.add(Settings.System.MIN_REFRESH_RATE);
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 7b6321d1cc7df7892c1914c8f0454dc05673dbcd..526320debb1a3530b5d4b695d1b3cbeca0e5aab1 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -369,6 +369,9 @@
+
+
+
@@ -953,6 +956,13 @@
+
+
+
+
+
diff --git a/packages/Shell/OWNERS b/packages/Shell/OWNERS
index 8feefa5d892fbc8e3fef9d9020eacc40642144e8..d4b5b86223eadf74f6b2c86696e7af4ca923e966 100644
--- a/packages/Shell/OWNERS
+++ b/packages/Shell/OWNERS
@@ -12,3 +12,4 @@ patb@google.com
cbrubaker@google.com
omakoto@google.com
michaelwr@google.com
+ronish@google.com
diff --git a/packages/Shell/aconfig/Android.bp b/packages/Shell/aconfig/Android.bp
new file mode 100644
index 0000000000000000000000000000000000000000..1d797b29c1a47eeb8fe5e61ad941d36e14d82f7e
--- /dev/null
+++ b/packages/Shell/aconfig/Android.bp
@@ -0,0 +1,13 @@
+aconfig_declarations {
+ name: "wear_aconfig_declarations",
+ package: "com.android.shell.flags",
+ container: "system",
+ srcs: [
+ "wear.aconfig",
+ ],
+}
+
+java_aconfig_library {
+ name: "wear_aconfig_declarations_flags_java_lib",
+ aconfig_declarations: "wear_aconfig_declarations",
+}
diff --git a/packages/Shell/aconfig/wear.aconfig b/packages/Shell/aconfig/wear.aconfig
new file mode 100644
index 0000000000000000000000000000000000000000..e07bd963a4aa6908754a189f6bde45fbe243027a
--- /dev/null
+++ b/packages/Shell/aconfig/wear.aconfig
@@ -0,0 +1,9 @@
+package: "com.android.shell.flags"
+container: "system"
+
+flag {
+ name: "handle_bugreports_for_wear"
+ namespace: "wear_services"
+ description: "This flag enables Shell to propagate bugreport results to WearServices."
+ bug: "378060870"
+}
\ No newline at end of file
diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java
index 7c478ac78a298778de4c1ffd15767d5a00eb3c10..7f25b51e35cae19dffe80bf7c99021c919460aeb 100644
--- a/packages/Shell/src/com/android/shell/BugreportProgressService.java
+++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java
@@ -153,6 +153,10 @@ public class BugreportProgressService extends Service {
static final String INTENT_BUGREPORT_FINISHED =
"com.android.internal.intent.action.BUGREPORT_FINISHED";
+ // Intent sent to notify external apps that bugreport aborted due to error.
+ static final String INTENT_BUGREPORT_ABORTED =
+ "com.android.internal.intent.action.BUGREPORT_ABORTED";
+
// Internal intents used on notification actions.
static final String INTENT_BUGREPORT_CANCEL = "android.intent.action.BUGREPORT_CANCEL";
static final String INTENT_BUGREPORT_SHARE = "android.intent.action.BUGREPORT_SHARE";
@@ -174,6 +178,8 @@ public class BugreportProgressService extends Service {
static final String EXTRA_INFO = "android.intent.extra.INFO";
static final String EXTRA_EXTRA_ATTACHMENT_URIS =
"android.intent.extra.EXTRA_ATTACHMENT_URIS";
+ static final String EXTRA_ABORTED_ERROR_CODE =
+ "android.intent.extra.EXTRA_ABORTED_ERROR_CODE";
private static final ThreadFactory sBugreportManagerCallbackThreadFactory =
new ThreadFactory() {
@@ -404,6 +410,7 @@ public class BugreportProgressService extends Service {
@Override
public void onError(@BugreportErrorCode int errorCode) {
synchronized (mLock) {
+ sendBugreportAbortedBroadcastLocked(errorCode);
stopProgressLocked(mInfo.id);
mInfo.deleteEmptyFiles();
}
@@ -460,6 +467,13 @@ public class BugreportProgressService extends Service {
onBugreportFinished(mInfo);
}
}
+
+ @GuardedBy("mLock")
+ private void sendBugreportAbortedBroadcastLocked(@BugreportErrorCode int errorCode) {
+ final Intent intent = new Intent(INTENT_BUGREPORT_ABORTED);
+ intent.putExtra(EXTRA_ABORTED_ERROR_CODE, errorCode);
+ mContext.sendBroadcast(intent, android.Manifest.permission.DUMP);
+ }
}
private void sendRemoteBugreportFinishedBroadcast(Context context,
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
index bffda8bcae6560efdec5c8c178f33bc98353a4e8..d1a22e8612d38254763faef754bfec482b5e4c39 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -90,8 +90,6 @@ filegroup {
"tests/src/**/systemui/globalactions/GlobalActionsDialogLiteTest.java",
"tests/src/**/systemui/globalactions/GlobalActionsImeTest.java",
"tests/src/**/systemui/keyguard/data/repository/KeyguardTransitionRepositoryTest.kt",
- "tests/src/**/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImplTest.kt",
- "tests/src/**/systemui/media/controls/domain/pipeline/MediaDataProcessorTest.kt",
"tests/src/**/systemui/media/dialog/MediaOutputAdapterTest.java",
"tests/src/**/systemui/media/dialog/MediaOutputBaseDialogTest.java",
"tests/src/**/systemui/media/dialog/MediaOutputBroadcastDialogTest.java",
@@ -134,7 +132,6 @@ filegroup {
"tests/src/**/systemui/accessibility/floatingmenu/MenuViewLayerTest.java",
"tests/src/**/systemui/accessibility/floatingmenu/MenuViewTest.java",
"tests/src/**/systemui/classifier/PointerCountClassifierTest.java",
- "tests/src/**/systemui/qs/tileimpl/QSIconViewImplTest_311121830.kt",
"tests/src/**/systemui/accessibility/floatingmenu/RadiiAnimatorTest.java",
"tests/src/**/systemui/screenrecord/RecordingControllerTest.java",
"tests/src/**/systemui/screenshot/RequestProcessorTest.kt",
@@ -211,13 +208,13 @@ filegroup {
"tests/src/**/systemui/qs/tiles/DreamTileTest.java",
"tests/src/**/systemui/qs/FgsManagerControllerTest.java",
"tests/src/**/systemui/qs/QSPanelTest.kt",
+ "tests/src/**/systemui/reardisplay/RearDisplayCoreStartableTest.kt",
"tests/src/**/systemui/reardisplay/RearDisplayDialogControllerTest.java",
+ "tests/src/**/systemui/reardisplay/RearDisplayInnerDialogDelegateTest.kt",
"tests/src/**/systemui/statusbar/KeyboardShortcutListSearchTest.java",
"tests/src/**/systemui/statusbar/KeyboardShortcutsTest.java",
"tests/src/**/systemui/statusbar/KeyguardIndicationControllerWithCoroutinesTest.kt",
"tests/src/**/systemui/statusbar/notification/AssistantFeedbackControllerTest.java",
- "tests/src/**/systemui/statusbar/notification/PropertyAnimatorTest.java",
- "tests/src/**/systemui/statusbar/notification/collection/NotifCollectionTest.java",
"tests/src/**/systemui/statusbar/notification/collection/NotificationEntryTest.java",
"tests/src/**/systemui/statusbar/notification/collection/render/GroupExpansionManagerTest.kt",
"tests/src/**/systemui/statusbar/notification/collection/ShadeListBuilderTest.java",
@@ -233,9 +230,7 @@ filegroup {
"tests/src/**/systemui/statusbar/notification/row/NotificationConversationInfoTest.java",
"tests/src/**/systemui/statusbar/notification/row/NotificationGutsManagerTest.java",
"tests/src/**/systemui/statusbar/notification/row/NotificationGutsManagerWithScenesTest.kt",
- "tests/src/**/systemui/statusbar/notification/row/NotifLayoutInflaterFactoryTest.kt",
"tests/src/**/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapperTest.kt",
- "tests/src/**/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java",
"tests/src/**/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java",
"tests/src/**/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt",
"tests/src/**/systemui/statusbar/phone/AutoTileManagerTest.java",
@@ -250,7 +245,6 @@ filegroup {
"tests/src/**/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModelImplTest.kt",
"tests/src/**/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt",
"tests/src/**/systemui/statusbar/pipeline/mobile/ui/view/ModernStatusBarMobileViewTest.kt",
- "tests/src/**/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt",
"tests/src/**/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiViewTest.kt",
"tests/src/**/systemui/statusbar/policy/CallbackControllerTest.java",
"tests/src/**/systemui/statusbar/policy/DeviceStateRotationLockSettingControllerTest.java",
@@ -263,11 +257,9 @@ filegroup {
"tests/src/**/systemui/theme/ThemeOverlayApplierTest.java",
"tests/src/**/systemui/touch/TouchInsetManagerTest.java",
"tests/src/**/systemui/util/LifecycleFragmentTest.java",
- "tests/src/**/systemui/util/TestableAlertDialogTest.kt",
"tests/src/**/systemui/util/kotlin/PairwiseFlowTest",
"tests/src/**/systemui/util/sensors/AsyncManagerTest.java",
"tests/src/**/systemui/util/sensors/ThresholdSensorImplTest.java",
- "tests/src/**/systemui/util/wakelock/KeepAwakeAnimationListenerTest.java",
"tests/src/**/systemui/volume/VolumeDialogImplTest.java",
"tests/src/**/systemui/wallet/controller/QuickAccessWalletControllerTest.java",
"tests/src/**/systemui/wallet/ui/WalletScreenControllerTest.java",
@@ -288,9 +280,6 @@ filegroup {
"tests/src/**/systemui/qs/QSImplTest.java",
"tests/src/**/systemui/qs/panels/ui/compose/DragAndDropTest.kt",
"tests/src/**/systemui/qs/panels/ui/compose/ResizingTest.kt",
- "tests/src/**/systemui/screenshot/ActionExecutorTest.kt",
- "tests/src/**/systemui/screenshot/ScreenshotDetectionControllerTest.kt",
- "tests/src/**/systemui/screenshot/TakeScreenshotServiceTest.kt",
"tests/src/**/systemui/accessibility/floatingmenu/MenuAnimationControllerTest.java",
"tests/src/**/systemui/accessibility/floatingmenu/PositionTest.java",
"tests/src/**/systemui/animation/TransitionAnimatorTest.kt",
@@ -303,10 +292,45 @@ filegroup {
"tests/src/**/systemui/statusbar/notification/row/BigPictureIconManagerTest.kt",
"tests/src/**/systemui/statusbar/policy/RotationLockControllerImplTest.java",
"tests/src/**/systemui/statusbar/phone/ScrimControllerTest.java",
- "tests/src/**/systemui/stylus/StylusUsiPowerStartableTest.kt",
"tests/src/**/systemui/toast/ToastUITest.java",
"tests/src/**/systemui/statusbar/policy/FlashlightControllerImplTest.kt",
"tests/src/**/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImplTest.kt",
+ "tests/src/**/systemui/stylus/StylusUsiPowerUiTest.kt",
+ ],
+}
+
+// Files which use ExtendedMockito on the device.
+filegroup {
+ name: "SystemUI-tests-broken-robofiles-mockito-extended",
+ srcs: [
+ "tests/src/**/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceConfigTest.kt",
+ "tests/src/**/systemui/notetask/shortcut/LaunchNoteTaskActivityTest.kt",
+ "tests/src/**/systemui/notetask/LaunchNotesRoleSettingsTrampolineActivityTest.kt",
+ "tests/src/**/systemui/bluetooth/qsdialog/AudioSharingDeviceItemActionInteractorTest.kt",
+ "tests/src/**/systemui/bluetooth/qsdialog/AudioSharingButtonViewModelTest.kt",
+ "tests/src/**/systemui/bluetooth/qsdialog/DeviceItemFactoryTest.kt",
+ "tests/src/**/systemui/stylus/StylusManagerTest.kt",
+ "tests/src/**/systemui/recents/OverviewProxyServiceTest.kt",
+ "tests/src/**/systemui/DisplayCutoutBaseViewTest.kt",
+ "tests/src/**/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepositoryTest.kt",
+ "tests/src/**/systemui/statusbar/policy/BatteryControllerTest.java",
+ "tests/src/**/systemui/statusbar/policy/SensitiveNotificationProtectionControllerTest.kt",
+ "tests/src/**/systemui/statusbar/KeyboardShortcutsReceiverTest.java",
+ "tests/src/**/systemui/media/controls/domain/pipeline/MediaDataProcessorTest.kt",
+ "tests/src/**/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImplTest.kt",
+ "tests/src/**/systemui/temporarydisplay/chipbar/SwipeChipbarAwayGestureHandlerTest.kt",
+ "tests/src/**/systemui/qs/tiles/HotspotTileTest.java",
+ "tests/src/**/systemui/qs/tiles/dialog/InternetDialogDelegateTest.java",
+ "tests/src/**/systemui/navigationbar/NavigationBarControllerImplTest.java",
+ "tests/src/**/systemui/wmshell/BubblesTest.java",
+ "tests/src/**/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java",
+ "tests/src/**/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java",
+ "tests/src/**/systemui/shared/system/RemoteTransitionTest.java",
+ "tests/src/**/systemui/qs/tiles/dialog/InternetDialogDelegateControllerTest.java",
+ "tests/src/**/systemui/qs/external/TileLifecycleManagerTest.java",
+ "tests/src/**/systemui/ScreenDecorationsTest.java",
+ "tests/src/**/keyguard/CarrierTextManagerTest.java",
+ "tests/src/**/keyguard/KeyguardUpdateMonitorTest.java",
],
}
@@ -314,29 +338,23 @@ filegroup {
filegroup {
name: "SystemUI-tests-broken-robofiles-compile",
srcs: [
- "tests/src/**/keyguard/KeyguardUpdateMonitorTest.java",
"tests/src/**/systemui/statusbar/notification/icon/IconManagerTest.kt",
"tests/src/**/systemui/statusbar/KeyguardIndicationControllerTest.java",
"tests/src/**/systemui/doze/DozeScreenStateTest.java",
- "tests/src/**/keyguard/CarrierTextManagerTest.java",
"tests/src/**/systemui/notetask/NoteTaskInitializerTest.kt",
"tests/src/**/systemui/media/controls/ui/controller/MediaHierarchyManagerTest.kt",
"tests/src/**/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt",
"tests/src/**/systemui/controls/management/ControlsFavoritingActivityTest.kt",
"tests/src/**/systemui/controls/management/ControlsProviderSelectorActivityTest.kt",
"tests/src/**/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelTest.kt",
- "tests/src/**/systemui/media/controls/domain/pipeline/MediaTimeoutListenerTest.kt",
"tests/src/**/systemui/media/taptotransfer/receiver/FakeMediaTttChipControllerReceiver.kt",
"tests/src/**/systemui/qs/tileimpl/QSTileViewImplTest.kt",
- "tests/src/**/systemui/statusbar/policy/BatteryStateNotifierTest.kt",
"tests/src/**/systemui/temporarydisplay/TemporaryViewDisplayControllerTest.kt",
"tests/src/**/keyguard/ClockEventControllerTest.kt",
"tests/src/**/systemui/bluetooth/qsdialog/BluetoothAutoOnRepositoryTest.kt",
- "tests/src/**/systemui/bluetooth/qsdialog/BluetoothStateInteractorTest.kt",
"tests/src/**/systemui/bluetooth/qsdialog/BluetoothTileDialogDelegateTest.kt",
"tests/src/**/systemui/bluetooth/qsdialog/BluetoothTileDialogRepositoryTest.kt",
"tests/src/**/systemui/bluetooth/qsdialog/BluetoothTileDialogViewModelTest.kt",
- "tests/src/**/systemui/bluetooth/qsdialog/DeviceItemFactoryTest.kt",
"tests/src/**/systemui/bluetooth/qsdialog/DeviceItemInteractorTest.kt",
"tests/src/**/systemui/broadcast/UserBroadcastDispatcherTest.kt",
"tests/src/**/systemui/charging/WiredChargingRippleControllerTest.kt",
@@ -351,7 +369,6 @@ filegroup {
"tests/src/**/systemui/controls/ui/SelectionItemTest.kt",
"tests/src/**/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySectionTest.kt",
"tests/src/**/systemui/media/controls/domain/pipeline/LegacyMediaDataFilterImplTest.kt",
- "tests/src/**/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImplTest.kt",
"tests/src/**/systemui/media/controls/domain/pipeline/MediaDataFilterImplTest.kt",
"tests/src/**/systemui/media/controls/ui/animation/AnimationBindHandlerTest.kt",
"tests/src/**/systemui/media/controls/ui/animation/ColorSchemeTransitionTest.kt",
@@ -417,40 +434,9 @@ filegroup {
"tests/src/**/systemui/statusbar/policy/VariableDateViewControllerTest.kt",
"tests/src/**/systemui/statusbar/policy/WalletControllerImplTest.kt",
"tests/src/**/systemui/statusbar/SplitShadeLockScreenOverScrollerTest.kt",
- "tests/src/**/systemui/stylus/StylusUsiPowerUiTest.kt",
"tests/src/**/systemui/temporarydisplay/chipbar/ChipbarCoordinatorTest.kt",
- "tests/src/**/systemui/ScreenDecorationsTest.java",
- "tests/src/**/systemui/temporarydisplay/chipbar/SwipeChipbarAwayGestureHandlerTest.kt",
- "tests/src/**/systemui/media/controls/domain/pipeline/MediaDataProcessorTest.kt",
- "tests/src/**/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImplTest.kt",
- "tests/src/**/systemui/shared/system/RemoteTransitionTest.java",
- "tests/src/**/systemui/navigationbar/NavigationBarControllerImplTest.java",
- "tests/src/**/systemui/bluetooth/qsdialog/AudioSharingButtonViewModelTest.kt",
- "tests/src/**/systemui/bluetooth/qsdialog/AudioSharingDeviceItemActionInteractorTest.kt",
- "tests/src/**/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceConfigTest.kt",
- "tests/src/**/systemui/notetask/LaunchNotesRoleSettingsTrampolineActivityTest.kt",
- "tests/src/**/systemui/notetask/shortcut/LaunchNoteTaskActivityTest.kt",
- "tests/src/**/systemui/DisplayCutoutBaseViewTest.kt",
- "tests/src/**/systemui/qs/tiles/dialog/InternetDialogDelegateTest.java",
- "tests/src/**/systemui/qs/tiles/dialog/InternetDialogDelegateControllerTest.java",
- "tests/src/**/systemui/qs/tiles/HotspotTileTest.java",
- "tests/src/**/systemui/qs/external/TileLifecycleManagerTest.java",
- "tests/src/**/systemui/recents/OverviewProxyServiceTest.kt",
- "tests/src/**/systemui/stylus/StylusManagerTest.kt",
- "tests/src/**/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java",
- "tests/src/**/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java",
"tests/src/**/systemui/statusbar/policy/BatteryControllerStartableTest.java",
- "tests/src/**/systemui/statusbar/policy/BatteryControllerTest.java",
- "tests/src/**/systemui/statusbar/policy/SensitiveNotificationProtectionControllerTest.kt",
- "tests/src/**/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepositoryTest.kt",
- "tests/src/**/systemui/statusbar/KeyboardShortcutsReceiverTest.java",
- "tests/src/**/systemui/wmshell/BubblesTest.java",
- "tests/src/**/systemui/power/PowerUITest.java",
- "tests/src/**/systemui/qs/QSSecurityFooterTest.java",
- "tests/src/**/systemui/qs/tileimpl/QSTileImplTest.java",
"tests/src/**/systemui/shared/plugins/PluginActionManagerTest.java",
- "tests/src/**/systemui/statusbar/CommandQueueTest.java",
- "tests/src/**/systemui/statusbar/connectivity/CallbackHandlerTest.java",
"tests/src/**/systemui/statusbar/policy/SecurityControllerTest.java",
"tests/src/**/systemui/shared/clocks/view/SimpleDigitalClockTextViewTest.kt",
],
@@ -497,6 +483,9 @@ android_library {
resource_dirs: [],
static_libs: [
"//frameworks/libs/systemui:compilelib",
+ "//frameworks/base/packages/SystemUI/pods/com/android/systemui/dagger:api",
+ "//frameworks/base/packages/SystemUI/pods/com/android/systemui/util/settings:api",
+ "//frameworks/base/packages/SystemUI/pods/com/android/systemui/retail:impl",
"SystemUI-res",
"WifiTrackerLib",
"WindowManager-Shell",
@@ -770,6 +759,9 @@ android_library {
],
static_libs: [
"//frameworks/libs/systemui:compilelib",
+ "//frameworks/base/packages/SystemUI/pods/com/android/systemui/dagger:api",
+ "//frameworks/base/packages/SystemUI/pods/com/android/systemui/util/settings:api",
+ "//frameworks/base/packages/SystemUI/pods/com/android/systemui/retail:impl",
"SystemUI-tests-base",
"androidx.test.uiautomator_uiautomator",
"androidx.core_core-animation-testing",
@@ -910,6 +902,7 @@ android_robolectric_test {
":SystemUI-tests-robofiles",
],
exclude_srcs: [
+ ":SystemUI-tests-broken-robofiles-mockito-extended",
":SystemUI-tests-broken-robofiles-compile",
":SystemUI-tests-broken-robofiles-run",
":SystemUI-tests-broken-robofiles-sysui-run",
diff --git a/packages/SystemUI/TEST_MAPPING b/packages/SystemUI/TEST_MAPPING
index 380344a23c998867739913f63bb0a158f68a408c..e47704ebdf868e4f7dffcf3812af1f631b516b4f 100644
--- a/packages/SystemUI/TEST_MAPPING
+++ b/packages/SystemUI/TEST_MAPPING
@@ -153,5 +153,11 @@
{
"path": "cts/tests/tests/multiuser"
}
+ ],
+
+ "sysui-e2e-presubmit": [
+ {
+ "name": "PlatformScenarioTests_SysUI_Presubmit"
+ }
]
}
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig
index 207ed71c955d5b6e538304d10ec3a524bf811c96..67666c3db81f33a28ea7ee17f499038ef4586fe0 100644
--- a/packages/SystemUI/aconfig/systemui.aconfig
+++ b/packages/SystemUI/aconfig/systemui.aconfig
@@ -267,7 +267,7 @@ flag {
flag {
name: "dual_shade"
namespace: "systemui"
- description: "Enables the BC25 Dual Shade (go/bc25-dual-shade-design)."
+ description: "Enables Dual Shade (go/dual-shade-design-doc)."
bug: "337259436"
}
@@ -557,6 +557,13 @@ flag {
bug: "343495953"
}
+flag {
+ name: "lockscreen_custom_clocks"
+ namespace: "systemui"
+ description: "Enable lockscreen custom clocks"
+ bug: "378486437"
+}
+
flag {
name: "faster_unlock_transition"
namespace: "systemui"
@@ -625,9 +632,9 @@ flag {
flag {
name: "status_bar_connected_displays"
- namespace: "systemui"
+ namespace: "lse_desktop_experience"
description: "Shows the status bar on connected displays"
- bug: "362720336"
+ bug: "379264862"
}
flag {
@@ -1359,16 +1366,6 @@ flag {
}
}
-flag {
- name: "notification_pulsing_fix"
- namespace: "systemui"
- description: "Allow showing new pulsing notifications when the device is already pulsing."
- bug: "335560575"
- metadata {
- purpose: PURPOSE_BUGFIX
- }
-}
-
flag {
name: "media_lockscreen_launch_animation"
namespace : "systemui"
@@ -1750,6 +1747,13 @@ flag {
bug: "376491880"
}
+flag {
+ name: "notification_shade_blur"
+ namespace: "systemui"
+ description: "Enables the new blur effect on the Notification Shade."
+ bug: "370555223"
+}
+
flag {
name: "ensure_enr_views_visibility"
namespace: "systemui"
@@ -1784,3 +1788,13 @@ flag {
purpose: PURPOSE_BUGFIX
}
}
+
+flag {
+ name: "keyguard_transition_force_finish_on_screen_off"
+ namespace: "systemui"
+ description: "Forces KTF transitions to finish if the screen turns all the way off."
+ bug: "331636736"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityTransitionAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityTransitionAnimator.kt
index 18f40c98fe040a63b9c1f8ccab9cfe54d64806f0..eee0cafd34fe4b091c2355b7460ee608e675626a 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityTransitionAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityTransitionAnimator.kt
@@ -24,18 +24,22 @@ import android.app.WindowConfiguration
import android.content.ComponentName
import android.graphics.Color
import android.graphics.Matrix
+import android.graphics.PointF
import android.graphics.Rect
import android.graphics.RectF
import android.os.Binder
import android.os.Build
import android.os.Handler
+import android.os.IBinder
import android.os.Looper
import android.os.RemoteException
+import android.util.ArrayMap
import android.util.Log
import android.view.IRemoteAnimationFinishedCallback
import android.view.IRemoteAnimationRunner
import android.view.RemoteAnimationAdapter
import android.view.RemoteAnimationTarget
+import android.view.SurfaceControl
import android.view.SyncRtSurfaceTransactionApplier
import android.view.View
import android.view.ViewGroup
@@ -45,8 +49,12 @@ import android.view.WindowManager.TRANSIT_OPEN
import android.view.WindowManager.TRANSIT_TO_BACK
import android.view.WindowManager.TRANSIT_TO_FRONT
import android.view.animation.PathInterpolator
+import android.window.IRemoteTransition
+import android.window.IRemoteTransitionFinishedCallback
import android.window.RemoteTransition
import android.window.TransitionFilter
+import android.window.TransitionInfo
+import android.window.WindowAnimationState
import androidx.annotation.AnyThread
import androidx.annotation.BinderThread
import androidx.annotation.UiThread
@@ -55,11 +63,14 @@ import com.android.internal.annotations.VisibleForTesting
import com.android.internal.policy.ScreenDecorationsUtils
import com.android.systemui.Flags.activityTransitionUseLargestWindow
import com.android.systemui.Flags.translucentOccludingActivityFix
+import com.android.systemui.animation.TransitionAnimator.Companion.assertLongLivedReturnAnimations
+import com.android.systemui.animation.TransitionAnimator.Companion.assertReturnAnimations
+import com.android.systemui.animation.TransitionAnimator.Companion.longLivedReturnAnimationsEnabled
+import com.android.systemui.animation.TransitionAnimator.Companion.returnAnimationsEnabled
import com.android.systemui.animation.TransitionAnimator.Companion.toTransitionState
-import com.android.systemui.shared.Flags.returnAnimationFrameworkLibrary
-import com.android.systemui.shared.Flags.returnAnimationFrameworkLongLived
import com.android.wm.shell.shared.IShellTransitions
import com.android.wm.shell.shared.ShellTransitions
+import com.android.wm.shell.shared.TransitionUtil
import java.util.concurrent.Executor
import kotlin.math.roundToInt
@@ -194,7 +205,13 @@ constructor(
private const val LONG_TRANSITION_TIMEOUT = 5_000L
private fun defaultTransitionAnimator(mainExecutor: Executor): TransitionAnimator {
- return TransitionAnimator(mainExecutor, TIMINGS, INTERPOLATORS)
+ return TransitionAnimator(
+ mainExecutor,
+ TIMINGS,
+ INTERPOLATORS,
+ SPRING_TIMINGS,
+ SPRING_INTERPOLATORS,
+ )
}
private fun defaultDialogToAppAnimator(mainExecutor: Executor): TransitionAnimator {
@@ -275,7 +292,7 @@ constructor(
"ActivityTransitionAnimator.callback must be set before using this animator"
)
val runner = createRunner(controller)
- val runnerDelegate = runner.delegate!!
+ val runnerDelegate = runner.delegate
val hideKeyguardWithAnimation = callback.isOnKeyguard() && !showOverLockscreen
// Pass the RemoteAnimationAdapter to the intent starter only if we are not hiding the
@@ -330,7 +347,11 @@ constructor(
// If we expect an animation, post a timeout to cancel it in case the remote animation is
// never started.
if (willAnimate) {
- runnerDelegate.postTimeouts()
+ if (longLivedReturnAnimationsEnabled()) {
+ runner.postTimeouts()
+ } else {
+ runnerDelegate!!.postTimeouts()
+ }
// Hide the keyguard using the launch animation instead of the default unlock animation.
if (hideKeyguardWithAnimation) {
@@ -390,7 +411,7 @@ constructor(
launchController: Controller,
transitionRegister: TransitionRegister?,
) {
- if (!returnAnimationFrameworkLibrary()) return
+ if (!returnAnimationsEnabled()) return
var cleanUpRunnable: Runnable? = null
val returnRunner =
@@ -413,7 +434,8 @@ constructor(
private fun cleanUp() {
cleanUpRunnable?.run()
}
- }
+ },
+ initializeLazily = longLivedReturnAnimationsEnabled(),
)
// mTypeSet and mModes match back signals only, and not home. This is on purpose, because
@@ -435,7 +457,11 @@ constructor(
"${launchController.transitionCookie}_returnTransition",
)
- transitionRegister?.register(filter, transition)
+ transitionRegister?.register(
+ filter,
+ transition,
+ includeTakeover = longLivedReturnAnimationsEnabled(),
+ )
cleanUpRunnable = Runnable { transitionRegister?.unregister(transition) }
}
@@ -451,7 +477,10 @@ constructor(
/** Create a new animation [Runner] controlled by [controller]. */
@VisibleForTesting
- fun createRunner(controller: Controller): Runner {
+ @JvmOverloads
+ fun createRunner(controller: Controller, initializeLazily: Boolean = false): Runner {
+ if (initializeLazily) assertLongLivedReturnAnimations()
+
// Make sure we use the modified timings when animating a dialog into an app.
val transitionAnimator =
if (controller.isDialogLaunch) {
@@ -460,7 +489,13 @@ constructor(
transitionAnimator
}
- return Runner(controller, callback!!, transitionAnimator, lifecycleListener)
+ return Runner(
+ controller,
+ callback!!,
+ transitionAnimator,
+ lifecycleListener,
+ initializeLazily,
+ )
}
interface PendingIntentStarter {
@@ -628,10 +663,7 @@ constructor(
* this registration.
*/
fun register(controller: Controller) {
- check(returnAnimationFrameworkLongLived()) {
- "Long-lived registrations cannot be used when the returnAnimationFrameworkLongLived " +
- "flag is disabled"
- }
+ assertLongLivedReturnAnimations()
if (transitionRegister == null) {
throw IllegalStateException(
@@ -667,10 +699,10 @@ constructor(
}
val launchRemoteTransition =
RemoteTransition(
- RemoteAnimationRunnerCompat.wrap(createRunner(controller)),
+ OriginTransition(createRunner(controller, initializeLazily = true)),
"${cookie}_launchTransition",
)
- transitionRegister.register(launchFilter, launchRemoteTransition)
+ transitionRegister.register(launchFilter, launchRemoteTransition, includeTakeover = true)
val returnController =
object : Controller by controller {
@@ -689,10 +721,10 @@ constructor(
}
val returnRemoteTransition =
RemoteTransition(
- RemoteAnimationRunnerCompat.wrap(createRunner(returnController)),
+ OriginTransition(createRunner(returnController, initializeLazily = true)),
"${cookie}_returnTransition",
)
- transitionRegister.register(returnFilter, returnRemoteTransition)
+ transitionRegister.register(returnFilter, returnRemoteTransition, includeTakeover = true)
longLivedTransitions[cookie] = Pair(launchRemoteTransition, returnRemoteTransition)
}
@@ -738,14 +770,154 @@ constructor(
}
}
+ /** [Runner] wrapper that supports animation takeovers. */
+ private inner class OriginTransition(private val runner: Runner) : IRemoteTransition {
+ private val delegate = RemoteAnimationRunnerCompat.wrap(runner)
+
+ init {
+ assertLongLivedReturnAnimations()
+ }
+
+ override fun startAnimation(
+ token: IBinder?,
+ info: TransitionInfo?,
+ t: SurfaceControl.Transaction?,
+ finishCallback: IRemoteTransitionFinishedCallback?,
+ ) {
+ delegate.startAnimation(token, info, t, finishCallback)
+ }
+
+ override fun mergeAnimation(
+ transition: IBinder?,
+ info: TransitionInfo?,
+ t: SurfaceControl.Transaction?,
+ mergeTarget: IBinder?,
+ finishCallback: IRemoteTransitionFinishedCallback?,
+ ) {
+ delegate.mergeAnimation(transition, info, t, mergeTarget, finishCallback)
+ }
+
+ override fun onTransitionConsumed(transition: IBinder?, aborted: Boolean) {
+ delegate.onTransitionConsumed(transition, aborted)
+ }
+
+ override fun takeOverAnimation(
+ token: IBinder?,
+ info: TransitionInfo?,
+ t: SurfaceControl.Transaction?,
+ finishCallback: IRemoteTransitionFinishedCallback?,
+ states: Array,
+ ) {
+ if (info == null || t == null) {
+ Log.e(
+ TAG,
+ "Skipping the animation takeover because the required data is missing: " +
+ "info=$info, transaction=$t",
+ )
+ return
+ }
+
+ // The following code converts the contents of the given TransitionInfo into
+ // RemoteAnimationTargets. This is necessary because we must currently support both the
+ // new (Shell, remote transitions) and old (remote animations) framework to maintain
+ // functionality for all users of the library.
+ val apps = ArrayList()
+ val filteredStates = ArrayList()
+ val leashMap = ArrayMap()
+ val leafTaskFilter = TransitionUtil.LeafTaskFilter()
+
+ // About layering: we divide up the "layer space" into 2 regions (each the size of the
+ // change count). This lets us categorize things into above and below while
+ // maintaining their relative ordering.
+ val belowLayers = info.changes.size
+ val aboveLayers = info.changes.size * 2
+ for (i in info.changes.indices) {
+ val change = info.changes[i]
+ if (change == null || change.taskInfo == null) {
+ continue
+ }
+
+ val taskInfo = change.taskInfo
+
+ if (TransitionUtil.isWallpaper(change)) {
+ val target =
+ TransitionUtil.newTarget(
+ change,
+ belowLayers - i, // wallpapers go into the "below" layer space
+ info,
+ t,
+ leashMap,
+ )
+
+ // Make all the wallpapers opaque.
+ t.setAlpha(target.leash, 1f)
+ } else if (leafTaskFilter.test(change)) {
+ // Start by putting everything into the "below" layer space.
+ val target =
+ TransitionUtil.newTarget(change, belowLayers - i, info, t, leashMap)
+ apps.add(target)
+ filteredStates.add(states[i])
+
+ // Make all the apps opaque.
+ t.setAlpha(target.leash, 1f)
+
+ if (
+ TransitionUtil.isClosingType(change.mode) &&
+ taskInfo?.topActivityType != WindowConfiguration.ACTIVITY_TYPE_HOME
+ ) {
+ // Raise closing task to "above" layer so it isn't covered.
+ t.setLayer(target.leash, aboveLayers - i)
+ }
+ } else if (TransitionInfo.isIndependent(change, info)) {
+ // Root tasks
+ if (TransitionUtil.isClosingType(change.mode)) {
+ // Raise closing task to "above" layer so it isn't covered.
+ t.setLayer(change.leash, aboveLayers - i)
+ } else if (TransitionUtil.isOpeningType(change.mode)) {
+ // Put into the "below" layer space.
+ t.setLayer(change.leash, belowLayers - i)
+ }
+ } else if (TransitionUtil.isDividerBar(change)) {
+ val target =
+ TransitionUtil.newTarget(change, belowLayers - i, info, t, leashMap)
+ apps.add(target)
+ filteredStates.add(states[i])
+ }
+ }
+
+ val wrappedCallback: IRemoteAnimationFinishedCallback =
+ object : IRemoteAnimationFinishedCallback.Stub() {
+ override fun onAnimationFinished() {
+ leashMap.clear()
+ val finishTransaction = SurfaceControl.Transaction()
+ finishCallback?.onTransitionFinished(null, finishTransaction)
+ finishTransaction.close()
+ }
+ }
+
+ runner.takeOverAnimation(
+ apps.toTypedArray(),
+ filteredStates.toTypedArray(),
+ t,
+ wrappedCallback,
+ )
+ }
+
+ override fun asBinder(): IBinder {
+ return delegate.asBinder()
+ }
+ }
+
@VisibleForTesting
inner class Runner(
- controller: Controller,
- callback: Callback,
+ private val controller: Controller,
+ private val callback: Callback,
/** The animator to use to animate the window transition. */
- transitionAnimator: TransitionAnimator,
+ private val transitionAnimator: TransitionAnimator,
/** Listener for animation lifecycle events. */
- listener: Listener? = null,
+ private val listener: Listener? = null,
+ /** Whether the internal [delegate] should be initialized lazily. */
+ private val initializeLazily: Boolean = false,
) : IRemoteAnimationRunner.Stub() {
// This is being passed across IPC boundaries and cycles (through PendingIntentRecords,
// etc.) are possible. So we need to make sure we drop any references that might
@@ -753,15 +925,14 @@ constructor(
@VisibleForTesting var delegate: AnimationDelegate?
init {
- delegate =
- AnimationDelegate(
- mainExecutor,
- controller,
- callback,
- DelegatingAnimationCompletionListener(listener, this::dispose),
- transitionAnimator,
- disableWmTimeout,
- )
+ delegate = null
+ if (!initializeLazily) {
+ // Ephemeral launches bundle the runner with the launch request (instead of being
+ // registered ahead of time for later use). This means that there could be a timeout
+ // between creation and invocation, so the delegate needs to exist from the
+ // beginning in order to handle such timeout.
+ createDelegate()
+ }
}
@BinderThread
@@ -772,6 +943,36 @@ constructor(
nonApps: Array?,
finishedCallback: IRemoteAnimationFinishedCallback?,
) {
+ initAndRun(finishedCallback) { delegate ->
+ delegate.onAnimationStart(transit, apps, wallpapers, nonApps, finishedCallback)
+ }
+ }
+
+ @VisibleForTesting
+ @BinderThread
+ fun takeOverAnimation(
+ apps: Array?,
+ windowAnimationStates: Array,
+ startTransaction: SurfaceControl.Transaction,
+ finishedCallback: IRemoteAnimationFinishedCallback?,
+ ) {
+ assertLongLivedReturnAnimations()
+ initAndRun(finishedCallback) { delegate ->
+ delegate.takeOverAnimation(
+ apps,
+ windowAnimationStates,
+ startTransaction,
+ finishedCallback,
+ )
+ }
+ }
+
+ @BinderThread
+ private fun initAndRun(
+ finishedCallback: IRemoteAnimationFinishedCallback?,
+ performAnimation: (AnimationDelegate) -> Unit,
+ ) {
+ maybeSetUp()
val delegate = delegate
mainExecutor.execute {
if (delegate == null) {
@@ -780,7 +981,7 @@ constructor(
// signal back that we're done with it.
finishedCallback?.onAnimationFinished()
} else {
- delegate.onAnimationStart(transit, apps, wallpapers, nonApps, finishedCallback)
+ performAnimation(delegate)
}
}
}
@@ -794,6 +995,32 @@ constructor(
}
}
+ @VisibleForTesting
+ @UiThread
+ fun postTimeouts() {
+ maybeSetUp()
+ delegate?.postTimeouts()
+ }
+
+ @AnyThread
+ private fun maybeSetUp() {
+ if (!initializeLazily || delegate != null) return
+ createDelegate()
+ }
+
+ @AnyThread
+ private fun createDelegate() {
+ delegate =
+ AnimationDelegate(
+ mainExecutor,
+ controller,
+ callback,
+ DelegatingAnimationCompletionListener(listener, this::dispose),
+ transitionAnimator,
+ disableWmTimeout,
+ )
+ }
+
@AnyThread
fun dispose() {
// Drop references to animation controller once we're done with the animation
@@ -867,7 +1094,7 @@ constructor(
init {
// We do this check here to cover all entry points, including Launcher which doesn't
// call startIntentWithAnimation()
- if (!controller.isLaunching) TransitionAnimator.checkReturnAnimationFrameworkFlag()
+ if (!controller.isLaunching) assertReturnAnimations()
}
@UiThread
@@ -893,19 +1120,73 @@ constructor(
nonApps: Array?,
callback: IRemoteAnimationFinishedCallback?,
) {
+ val window = setUpAnimation(apps, callback) ?: return
+
+ if (controller.windowAnimatorState == null || !longLivedReturnAnimationsEnabled()) {
+ val navigationBar =
+ nonApps?.firstOrNull {
+ it.windowType == WindowManager.LayoutParams.TYPE_NAVIGATION_BAR
+ }
+
+ startAnimation(window, navigationBar, iCallback = callback)
+ } else {
+ // If a [controller.windowAnimatorState] exists, treat this like a takeover.
+ takeOverAnimationInternal(
+ window,
+ startWindowStates = null,
+ startTransaction = null,
+ callback,
+ )
+ }
+ }
+
+ @UiThread
+ internal fun takeOverAnimation(
+ apps: Array?,
+ startWindowStates: Array,
+ startTransaction: SurfaceControl.Transaction,
+ callback: IRemoteAnimationFinishedCallback?,
+ ) {
+ val window = setUpAnimation(apps, callback) ?: return
+ takeOverAnimationInternal(window, startWindowStates, startTransaction, callback)
+ }
+
+ private fun takeOverAnimationInternal(
+ window: RemoteAnimationTarget,
+ startWindowStates: Array?,
+ startTransaction: SurfaceControl.Transaction?,
+ callback: IRemoteAnimationFinishedCallback?,
+ ) {
+ val useSpring =
+ !controller.isLaunching && startWindowStates != null && startTransaction != null
+ startAnimation(
+ window,
+ navigationBar = null,
+ useSpring,
+ startWindowStates,
+ startTransaction,
+ callback,
+ )
+ }
+
+ @UiThread
+ private fun setUpAnimation(
+ apps: Array?,
+ callback: IRemoteAnimationFinishedCallback?,
+ ): RemoteAnimationTarget? {
removeTimeouts()
// The animation was started too late and we already notified the controller that it
// timed out.
if (timedOut) {
callback?.invoke()
- return
+ return null
}
// This should not happen, but let's make sure we don't start the animation if it was
// cancelled before and we already notified the controller.
if (cancelled) {
- return
+ return null
}
val window = findTargetWindowIfPossible(apps)
@@ -921,15 +1202,10 @@ constructor(
}
controller.onTransitionAnimationCancelled()
listener?.onTransitionAnimationCancelled()
- return
+ return null
}
- val navigationBar =
- nonApps?.firstOrNull {
- it.windowType == WindowManager.LayoutParams.TYPE_NAVIGATION_BAR
- }
-
- startAnimation(window, navigationBar, callback)
+ return window
}
private fun findTargetWindowIfPossible(
@@ -950,7 +1226,7 @@ constructor(
for (it in apps) {
if (it.mode == targetMode) {
if (activityTransitionUseLargestWindow()) {
- if (returnAnimationFrameworkLibrary()) {
+ if (returnAnimationsEnabled()) {
// If the controller contains a cookie, _only_ match if either the
// candidate contains the matching cookie, or a component is also
// defined and is a match.
@@ -995,8 +1271,11 @@ constructor(
private fun startAnimation(
window: RemoteAnimationTarget,
- navigationBar: RemoteAnimationTarget?,
- iCallback: IRemoteAnimationFinishedCallback?,
+ navigationBar: RemoteAnimationTarget? = null,
+ useSpring: Boolean = false,
+ startingWindowStates: Array? = null,
+ startTransaction: SurfaceControl.Transaction? = null,
+ iCallback: IRemoteAnimationFinishedCallback? = null,
) {
if (TransitionAnimator.DEBUG) {
Log.d(TAG, "Remote animation started")
@@ -1046,18 +1325,66 @@ constructor(
val controller =
object : Controller by delegate {
override fun createAnimatorState(): TransitionAnimator.State {
- if (isLaunching) return delegate.createAnimatorState()
- return delegate.windowAnimatorState?.toTransitionState()
- ?: getWindowRadius(isExpandingFullyAbove).let {
- TransitionAnimator.State(
- top = windowBounds.top,
- bottom = windowBounds.bottom,
- left = windowBounds.left,
- right = windowBounds.right,
- topCornerRadius = it,
- bottomCornerRadius = it,
- )
+ if (isLaunching) {
+ return delegate.createAnimatorState()
+ } else if (!longLivedReturnAnimationsEnabled()) {
+ return delegate.windowAnimatorState?.toTransitionState()
+ ?: getWindowRadius(isExpandingFullyAbove).let {
+ TransitionAnimator.State(
+ top = windowBounds.top,
+ bottom = windowBounds.bottom,
+ left = windowBounds.left,
+ right = windowBounds.right,
+ topCornerRadius = it,
+ bottomCornerRadius = it,
+ )
+ }
+ }
+
+ // The states are sorted matching the changes inside the transition info.
+ // Using this info, the RemoteAnimationTargets are created, with their
+ // prefixOrderIndex fields in reverse order to that of changes. To extract
+ // the right state, we need to invert again.
+ val windowState =
+ if (startingWindowStates != null) {
+ startingWindowStates[
+ startingWindowStates.size - window.prefixOrderIndex]
+ } else {
+ controller.windowAnimatorState
}
+
+ // TODO(b/323863002): use the timestamp and velocity to update the initial
+ // position.
+ val bounds = windowState?.bounds
+ val left: Int = bounds?.left?.toInt() ?: windowBounds.left
+ val top: Int = bounds?.top?.toInt() ?: windowBounds.top
+ val right: Int = bounds?.right?.toInt() ?: windowBounds.right
+ val bottom: Int = bounds?.bottom?.toInt() ?: windowBounds.bottom
+
+ val width = windowBounds.right - windowBounds.left
+ val height = windowBounds.bottom - windowBounds.top
+ // Scale the window. We use the max of (widthRatio, heightRatio) so that
+ // there is no blank space on any side.
+ val widthRatio = (right - left).toFloat() / width
+ val heightRatio = (bottom - top).toFloat() / height
+ val startScale = maxOf(widthRatio, heightRatio)
+
+ val maybeRadius = windowState?.topLeftRadius
+ val windowRadius =
+ if (maybeRadius != null) {
+ maybeRadius * startScale
+ } else {
+ getWindowRadius(isExpandingFullyAbove)
+ }
+
+ return TransitionAnimator.State(
+ top = top,
+ bottom = bottom,
+ left = left,
+ right = right,
+ topCornerRadius = windowRadius,
+ bottomCornerRadius = windowRadius,
+ )
}
override fun onTransitionAnimationStart(isExpandingFullyAbove: Boolean) {
@@ -1071,6 +1398,19 @@ constructor(
"[controller=$delegate]",
)
}
+
+ if (startTransaction != null) {
+ // Calling applyStateToWindow() here avoids skipping a frame when taking
+ // over an animation.
+ applyStateToWindow(
+ window,
+ createAnimatorState(),
+ linearProgress = 0f,
+ useSpring,
+ startTransaction,
+ )
+ }
+
delegate.onTransitionAnimationStart(isExpandingFullyAbove)
}
@@ -1094,14 +1434,29 @@ constructor(
progress: Float,
linearProgress: Float,
) {
- applyStateToWindow(window, state, linearProgress)
+ applyStateToWindow(window, state, linearProgress, useSpring)
navigationBar?.let { applyStateToNavigationBar(it, state, linearProgress) }
listener?.onTransitionAnimationProgress(linearProgress)
delegate.onTransitionAnimationProgress(state, progress, linearProgress)
}
}
-
+ val windowState =
+ if (startingWindowStates != null) {
+ startingWindowStates[startingWindowStates.size - window.prefixOrderIndex]
+ } else {
+ controller.windowAnimatorState
+ }
+ val velocityPxPerS =
+ if (longLivedReturnAnimationsEnabled() && windowState?.velocityPxPerMs != null) {
+ val xVelocityPxPerS = windowState.velocityPxPerMs.x * 1000
+ val yVelocityPxPerS = windowState.velocityPxPerMs.y * 1000
+ PointF(xVelocityPxPerS, yVelocityPxPerS)
+ } else if (useSpring) {
+ PointF(0f, 0f)
+ } else {
+ null
+ }
animation =
transitionAnimator.startAnimation(
controller,
@@ -1109,6 +1464,7 @@ constructor(
windowBackgroundColor,
fadeWindowBackgroundLayer = !controller.isBelowAnimatingWindow,
drawHole = !controller.isBelowAnimatingWindow,
+ startVelocity = velocityPxPerS,
)
}
@@ -1128,6 +1484,8 @@ constructor(
window: RemoteAnimationTarget,
state: TransitionAnimator.State,
linearProgress: Float,
+ useSpring: Boolean,
+ transaction: SurfaceControl.Transaction? = null,
) {
if (transactionApplierView.viewRootImpl == null || !window.leash.isValid) {
// Don't apply any transaction if the view root we synchronize with was detached or
@@ -1171,25 +1529,47 @@ constructor(
windowCropF.bottom.roundToInt(),
)
- val windowAnimationDelay =
+ val interpolators: TransitionAnimator.Interpolators
+ val windowProgress: Float
+
+ if (useSpring) {
+ val windowAnimationDelay: Float
+ val windowAnimationDuration: Float
if (controller.isLaunching) {
- TIMINGS.contentAfterFadeInDelay
+ windowAnimationDelay = SPRING_TIMINGS.contentAfterFadeInDelay
+ windowAnimationDuration = SPRING_TIMINGS.contentAfterFadeInDuration
} else {
- TIMINGS.contentBeforeFadeOutDelay
+ windowAnimationDelay = SPRING_TIMINGS.contentBeforeFadeOutDelay
+ windowAnimationDuration = SPRING_TIMINGS.contentBeforeFadeOutDuration
}
- val windowAnimationDuration =
+
+ interpolators = SPRING_INTERPOLATORS
+ windowProgress =
+ TransitionAnimator.getProgress(
+ linearProgress,
+ windowAnimationDelay,
+ windowAnimationDuration,
+ )
+ } else {
+ val windowAnimationDelay: Long
+ val windowAnimationDuration: Long
if (controller.isLaunching) {
- TIMINGS.contentAfterFadeInDuration
+ windowAnimationDelay = TIMINGS.contentAfterFadeInDelay
+ windowAnimationDuration = TIMINGS.contentAfterFadeInDuration
} else {
- TIMINGS.contentBeforeFadeOutDuration
+ windowAnimationDelay = TIMINGS.contentBeforeFadeOutDelay
+ windowAnimationDuration = TIMINGS.contentBeforeFadeOutDuration
}
- val windowProgress =
- TransitionAnimator.getProgress(
- TIMINGS,
- linearProgress,
- windowAnimationDelay,
- windowAnimationDuration,
- )
+
+ interpolators = INTERPOLATORS
+ windowProgress =
+ TransitionAnimator.getProgress(
+ TIMINGS,
+ linearProgress,
+ windowAnimationDelay,
+ windowAnimationDuration,
+ )
+ }
// The alpha of the opening window. If it opens above the expandable, then it should
// fade in progressively. Otherwise, it should be fully opaque and will be progressively
@@ -1197,12 +1577,12 @@ constructor(
val alpha =
if (controller.isBelowAnimatingWindow) {
if (controller.isLaunching) {
- INTERPOLATORS.contentAfterFadeInInterpolator.getInterpolation(
+ interpolators.contentAfterFadeInInterpolator.getInterpolation(
windowProgress
)
} else {
1 -
- INTERPOLATORS.contentBeforeFadeOutInterpolator.getInterpolation(
+ interpolators.contentBeforeFadeOutInterpolator.getInterpolation(
windowProgress
)
}
@@ -1216,6 +1596,7 @@ constructor(
// especially important for lock screen animations, where the window is not clipped by
// the shade.
val cornerRadius = maxOf(state.topCornerRadius, state.bottomCornerRadius) / scale
+
val params =
SyncRtSurfaceTransactionApplier.SurfaceParams.Builder(window.leash)
.withAlpha(alpha)
@@ -1223,11 +1604,15 @@ constructor(
.withWindowCrop(windowCrop)
.withCornerRadius(cornerRadius)
.withVisibility(true)
- .build()
+ if (transaction != null) params.withMergeTransaction(transaction)
- transactionApplier.scheduleApply(params)
+ transactionApplier.scheduleApply(params.build())
}
+ // TODO(b/377643129): remote transitions have no way of identifying the navbar when
+ // converting to RemoteAnimationTargets (and in my testing it was never included in the
+ // transition at all). So this method is not used anymore. Remove or adapt once we fully
+ // convert to remote transitions.
private fun applyStateToNavigationBar(
navigationBar: RemoteAnimationTarget,
state: TransitionAnimator.State,
@@ -1362,9 +1747,17 @@ constructor(
}
/** Register [remoteTransition] with WM Shell using the given [filter]. */
- internal fun register(filter: TransitionFilter, remoteTransition: RemoteTransition) {
+ internal fun register(
+ filter: TransitionFilter,
+ remoteTransition: RemoteTransition,
+ includeTakeover: Boolean,
+ ) {
shellTransitions?.registerRemote(filter, remoteTransition)
iShellTransitions?.registerRemote(filter, remoteTransition)
+ if (includeTakeover) {
+ shellTransitions?.registerRemoteForTakeover(filter, remoteTransition)
+ iShellTransitions?.registerRemoteForTakeover(filter, remoteTransition)
+ }
}
/** Unregister [remoteTransition] from WM Shell. */
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/TransitionAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/TransitionAnimator.kt
index fdb4871423c34632c297b9451731e9fef297db16..de4bdbc284c410180a66c2cccbdf22fc03db54a5 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/TransitionAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/TransitionAnimator.kt
@@ -38,6 +38,7 @@ import com.android.internal.annotations.VisibleForTesting
import com.android.internal.dynamicanimation.animation.SpringAnimation
import com.android.internal.dynamicanimation.animation.SpringForce
import com.android.systemui.shared.Flags.returnAnimationFrameworkLibrary
+import com.android.systemui.shared.Flags.returnAnimationFrameworkLongLived
import java.util.concurrent.Executor
import kotlin.math.abs
import kotlin.math.max
@@ -113,13 +114,26 @@ class TransitionAnimator(
)
}
- internal fun checkReturnAnimationFrameworkFlag() {
- check(returnAnimationFrameworkLibrary()) {
- "isLaunching cannot be false when the returnAnimationFrameworkLibrary flag is " +
- "disabled"
+ internal fun assertReturnAnimations() {
+ check(returnAnimationsEnabled()) {
+ "isLaunching cannot be false when the returnAnimationFrameworkLibrary flag " +
+ "is disabled"
}
}
+ internal fun returnAnimationsEnabled() = returnAnimationFrameworkLibrary()
+
+ internal fun assertLongLivedReturnAnimations() {
+ check(longLivedReturnAnimationsEnabled()) {
+ "Long-lived registrations cannot be used when the " +
+ "returnAnimationFrameworkLibrary or the " +
+ "returnAnimationFrameworkLongLived flag are disabled"
+ }
+ }
+
+ internal fun longLivedReturnAnimationsEnabled() =
+ returnAnimationFrameworkLibrary() && returnAnimationFrameworkLongLived()
+
internal fun WindowAnimationState.toTransitionState() =
State().also {
bounds?.let { b ->
@@ -467,7 +481,8 @@ class TransitionAnimator(
drawHole: Boolean = false,
startVelocity: PointF? = null,
): Animation {
- if (!controller.isLaunching || startVelocity != null) checkReturnAnimationFrameworkFlag()
+ if (!controller.isLaunching) assertReturnAnimations()
+ if (startVelocity != null) assertLongLivedReturnAnimations()
// We add an extra layer with the same color as the dialog/app splash screen background
// color, which is usually the same color of the app background. We first fade in this layer
diff --git a/packages/SystemUI/common/Android.bp b/packages/SystemUI/common/Android.bp
index 91dc3e338c59e3453b5d229c4573de333c7535f2..9f1598364dbc4d2e0c4c850bc561c196bec6de74 100644
--- a/packages/SystemUI/common/Android.bp
+++ b/packages/SystemUI/common/Android.bp
@@ -30,5 +30,9 @@ java_library {
"src/**/*.kt",
],
+ static_libs: ["SystemUI-shared-utils"],
+
+ libs: ["//frameworks/libs/systemui:tracinglib-platform"],
+
kotlincflags: ["-Xjvm-default=all"],
}
diff --git a/packages/SystemUI/src/com/android/systemui/common/coroutine/ConflatedCallbackFlow.kt b/packages/SystemUI/common/src/com/android/systemui/common/coroutine/ConflatedCallbackFlow.kt
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/common/coroutine/ConflatedCallbackFlow.kt
rename to packages/SystemUI/common/src/com/android/systemui/common/coroutine/ConflatedCallbackFlow.kt
diff --git a/packages/SystemUI/src/com/android/systemui/coroutines/Tracing.kt b/packages/SystemUI/common/src/com/android/systemui/coroutines/Tracing.kt
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/coroutines/Tracing.kt
rename to packages/SystemUI/common/src/com/android/systemui/coroutines/Tracing.kt
diff --git a/packages/SystemUI/compose/core/src/com/android/compose/theme/PlatformTheme.kt b/packages/SystemUI/compose/core/src/com/android/compose/theme/PlatformTheme.kt
index d31d7aa5948985c337013f430c50e573cf5af8cd..71ec63c1666c3d41b7d1e10ed3e9134f803d4754 100644
--- a/packages/SystemUI/compose/core/src/com/android/compose/theme/PlatformTheme.kt
+++ b/packages/SystemUI/compose/core/src/com/android/compose/theme/PlatformTheme.kt
@@ -63,6 +63,9 @@ private fun platformColorScheme(isDarkTheme: Boolean, context: Context): ColorSc
return if (isDarkTheme) {
dynamicDarkColorScheme(context)
.copy(
+ inverseSurface = color(context, R.color.system_inverse_surface_dark),
+ inverseOnSurface = color(context, R.color.system_inverse_on_surface_dark),
+ inversePrimary = color(context, R.color.system_inverse_primary_dark),
error = color(context, R.color.system_error_dark),
onError = color(context, R.color.system_on_error_dark),
errorContainer = color(context, R.color.system_error_container_dark),
@@ -71,6 +74,9 @@ private fun platformColorScheme(isDarkTheme: Boolean, context: Context): ColorSc
} else {
dynamicLightColorScheme(context)
.copy(
+ inverseSurface = color(context, R.color.system_inverse_surface_light),
+ inverseOnSurface = color(context, R.color.system_inverse_on_surface_light),
+ inversePrimary = color(context, R.color.system_inverse_primary_light),
error = color(context, R.color.system_error_light),
onError = color(context, R.color.system_on_error_light),
errorContainer = color(context, R.color.system_error_container_light),
diff --git a/packages/SystemUI/compose/core/tests/src/com/android/compose/theme/PlatformThemeTest.kt b/packages/SystemUI/compose/core/tests/src/com/android/compose/theme/PlatformThemeTest.kt
index de021a0677cf5915c953acd40b625124640ad292..737853b88f7a237b0a8d8564f1d883fb14bf58d7 100644
--- a/packages/SystemUI/compose/core/tests/src/com/android/compose/theme/PlatformThemeTest.kt
+++ b/packages/SystemUI/compose/core/tests/src/com/android/compose/theme/PlatformThemeTest.kt
@@ -89,7 +89,7 @@ class PlatformThemeTest {
addValue(
"inversePrimary",
colorScheme.inversePrimary,
- R.attr.materialColorPrimaryInverse,
+ R.attr.materialColorInversePrimary,
)
addValue("secondary", colorScheme.secondary, R.attr.materialColorSecondary)
addValue("onSecondary", colorScheme.onSecondary, R.attr.materialColorOnSecondary)
@@ -131,12 +131,12 @@ class PlatformThemeTest {
addValue(
"inverseSurface",
colorScheme.inverseSurface,
- R.attr.materialColorSurfaceInverse,
+ R.attr.materialColorInverseSurface,
)
addValue(
"inverseOnSurface",
colorScheme.inverseOnSurface,
- R.attr.materialColorOnSurfaceInverse,
+ R.attr.materialColorInverseOnSurface,
)
addValue("error", colorScheme.error, R.attr.materialColorError)
addValue("onError", colorScheme.onError, R.attr.materialColorOnError)
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContent.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContent.kt
index 9392b1afffa37b0dc44b05c1bbb8124b678c8769..778d7e7f99b361429089e093d3c6397d6b1f37a9 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContent.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContent.kt
@@ -66,13 +66,14 @@ constructor(
interactionHandler = interactionHandler,
dialogFactory = dialogFactory,
widgetSection = widgetSection,
- modifier = Modifier.element(Communal.Elements.Grid)
+ modifier = Modifier.element(Communal.Elements.Grid),
+ sceneScope = this@Content,
)
}
with(lockSection) {
LockIcon(
overrideColor = MaterialTheme.colorScheme.onPrimaryContainer,
- modifier = Modifier.element(Communal.Elements.LockIcon)
+ modifier = Modifier.element(Communal.Elements.LockIcon),
)
}
with(bottomAreaSection) {
@@ -80,17 +81,13 @@ constructor(
Modifier.element(Communal.Elements.IndicationArea).fillMaxWidth()
)
}
- }
+ },
) { measurables, constraints ->
val communalGridMeasurable = measurables[0]
val lockIconMeasurable = measurables[1]
val bottomAreaMeasurable = measurables[2]
- val noMinConstraints =
- constraints.copy(
- minWidth = 0,
- minHeight = 0,
- )
+ val noMinConstraints = constraints.copy(minWidth = 0, minHeight = 0)
val lockIconPlaceable = lockIconMeasurable.measure(noMinConstraints)
val lockIconBounds =
@@ -109,14 +106,8 @@ constructor(
)
layout(constraints.maxWidth, constraints.maxHeight) {
- communalGridPlaceable.place(
- x = 0,
- y = 0,
- )
- lockIconPlaceable.place(
- x = lockIconBounds.left,
- y = lockIconBounds.top,
- )
+ communalGridPlaceable.place(x = 0, y = 0)
+ lockIconPlaceable.place(x = lockIconBounds.left, y = lockIconBounds.top)
bottomAreaPlaceable.place(
x = 0,
y = constraints.maxHeight - bottomAreaPlaceable.height,
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 5e1ac1f3035412ccd06f118562ae3217c810a538..5b1203fa17c9d2c36e055b43aff762cc65de2798 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
@@ -163,6 +163,7 @@ import androidx.compose.ui.zIndex
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.window.layout.WindowMetricsCalculator
import com.android.compose.animation.Easings.Emphasized
+import com.android.compose.animation.scene.SceneScope
import com.android.compose.modifiers.thenIf
import com.android.compose.ui.graphics.painter.rememberDrawablePainter
import com.android.internal.R.dimen.system_app_widget_background_radius
@@ -186,7 +187,9 @@ import com.android.systemui.communal.util.DensityUtils.Companion.adjustedDp
import com.android.systemui.communal.widgets.SmartspaceAppWidgetHostView
import com.android.systemui.communal.widgets.WidgetConfigurator
import com.android.systemui.lifecycle.rememberViewModel
+import com.android.systemui.media.controls.ui.composable.MediaCarousel
import com.android.systemui.res.R
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
import com.android.systemui.statusbar.phone.SystemUIDialogFactory
import kotlin.math.max
import kotlin.math.min
@@ -205,6 +208,7 @@ fun CommunalHub(
widgetConfigurator: WidgetConfigurator? = null,
onOpenWidgetPicker: (() -> Unit)? = null,
onEditDone: (() -> Unit)? = null,
+ sceneScope: SceneScope? = null,
) {
val communalContent by
viewModel.communalContent.collectAsStateWithLifecycle(initialValue = emptyList())
@@ -414,6 +418,7 @@ fun CommunalHub(
widgetConfigurator = widgetConfigurator,
interactionHandler = interactionHandler,
widgetSection = widgetSection,
+ sceneScope = sceneScope,
)
}
}
@@ -735,6 +740,7 @@ private fun BoxScope.CommunalHubLazyGrid(
widgetConfigurator: WidgetConfigurator?,
interactionHandler: RemoteViews.InteractionHandler?,
widgetSection: CommunalAppWidgetSection,
+ sceneScope: SceneScope?,
) {
var gridModifier =
Modifier.align(Alignment.TopStart).onGloballyPositioned { setGridCoordinates(it) }
@@ -807,7 +813,6 @@ private fun BoxScope.CommunalHubLazyGrid(
) {
ResizeableItemFrameViewModel()
}
-
if (viewModel.isEditMode && dragDropState != null) {
val isItemDragging = dragDropState.draggingItemKey == item.key
val outlineAlpha by
@@ -872,6 +877,7 @@ private fun BoxScope.CommunalHubLazyGrid(
interactionHandler = interactionHandler,
widgetSection = widgetSection,
resizeableItemFrameViewModel = resizeableItemFrameViewModel,
+ sceneScope = sceneScope,
)
}
}
@@ -1096,6 +1102,7 @@ private fun CommunalContent(
interactionHandler: RemoteViews.InteractionHandler?,
widgetSection: CommunalAppWidgetSection,
resizeableItemFrameViewModel: ResizeableItemFrameViewModel,
+ sceneScope: SceneScope? = null,
) {
when (model) {
is CommunalContentModel.WidgetContent.Widget ->
@@ -1119,7 +1126,7 @@ private fun CommunalContent(
is CommunalContentModel.CtaTileInViewMode -> CtaTileInViewModeContent(viewModel, modifier)
is CommunalContentModel.Smartspace -> SmartspaceContent(interactionHandler, model, modifier)
is CommunalContentModel.Tutorial -> TutorialContent(modifier)
- is CommunalContentModel.Umo -> Umo(viewModel, modifier)
+ is CommunalContentModel.Umo -> Umo(viewModel, sceneScope, modifier)
}
}
@@ -1530,7 +1537,25 @@ private fun TutorialContent(modifier: Modifier = Modifier) {
}
@Composable
-private fun Umo(viewModel: BaseCommunalViewModel, modifier: Modifier = Modifier) {
+private fun Umo(
+ viewModel: BaseCommunalViewModel,
+ sceneScope: SceneScope?,
+ modifier: Modifier = Modifier,
+) {
+ if (SceneContainerFlag.isEnabled && sceneScope != null) {
+ sceneScope.MediaCarousel(
+ modifier = modifier.fillMaxSize(),
+ isVisible = true,
+ mediaHost = viewModel.mediaHost,
+ carouselController = viewModel.mediaCarouselController,
+ )
+ } else {
+ UmoLegacy(viewModel, modifier)
+ }
+}
+
+@Composable
+private fun UmoLegacy(viewModel: BaseCommunalViewModel, modifier: Modifier = Modifier) {
AndroidView(
modifier =
modifier.pointerInput(Unit) {
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/ContentListState.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/ContentListState.kt
index 6e30575a684d0806e496b86733d11bf7a4f8e2f0..16002bc709fd97a1288a73a889936db998c16d82 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/ContentListState.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/ContentListState.kt
@@ -59,7 +59,14 @@ internal constructor(
private val onAddWidget: (componentName: ComponentName, user: UserHandle, rank: Int) -> Unit,
private val onDeleteWidget: (id: Int, componentName: ComponentName, rank: Int) -> Unit,
private val onReorderWidgets: (widgetIdToRankMap: Map) -> Unit,
- private val onResizeWidget: (id: Int, spanY: Int, widgetIdToRankMap: Map) -> Unit,
+ private val onResizeWidget:
+ (
+ id: Int,
+ spanY: Int,
+ widgetIdToRankMap: Map,
+ componentName: ComponentName,
+ rank: Int,
+ ) -> Unit,
) {
var list = communalContent.toMutableStateList()
private set
@@ -105,7 +112,9 @@ internal constructor(
} else {
emptyMap()
}
- onResizeWidget(item.appWidgetId, newSpan, widgetIdToRankMap)
+ val componentName = item.componentName
+ val rank = item.rank
+ onResizeWidget(item.appWidgetId, newSpan, widgetIdToRankMap, componentName, rank)
}
/**
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/GridDragDropState.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/GridDragDropState.kt
index 1551ca97a2e3a0e81bd4d40249ed98b1aec151b5..ef5e90bd7aad4b4ba8f56bb3844ba93d0c4cf094 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/GridDragDropState.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/GridDragDropState.kt
@@ -179,11 +179,18 @@ internal constructor(
val targetItem =
if (communalWidgetResizing()) {
state.layoutInfo.visibleItemsInfo.findLast { item ->
+ val lastVisibleItemIndex = state.layoutInfo.visibleItemsInfo.last().index
val itemBoundingBox = IntRect(item.offset, item.size)
draggingItemKey != item.key &&
contentListState.isItemEditable(item.index) &&
(draggingBoundingBox.contains(itemBoundingBox.center) ||
- itemBoundingBox.contains(draggingBoundingBox.center))
+ itemBoundingBox.contains(draggingBoundingBox.center)) &&
+ // If we swap with the last visible item, and that item doesn't fit
+ // in the gap created by moving the current item, then the current item
+ // will get placed after the last visible item. In this case, it gets
+ // placed outside of the viewport. We avoid this here, so the user
+ // has to scroll first before the swap can happen.
+ (item.index != lastVisibleItemIndex || item.span <= draggingItem.span)
}
} else {
state.layoutInfo.visibleItemsInfo
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/qs/footer/ui/compose/FooterActions.kt b/packages/SystemUI/compose/features/src/com/android/systemui/qs/footer/ui/compose/FooterActions.kt
index 20c8c6a3f4bfd5a1c4195e1bed465a079cc4a0dd..2d32fd768eaac409d1a317c6353d70c1c72408fb 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/qs/footer/ui/compose/FooterActions.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/qs/footer/ui/compose/FooterActions.kt
@@ -36,6 +36,7 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
+import androidx.compose.foundation.shape.CornerSize
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Icon
import androidx.compose.material3.LocalContentColor
@@ -84,6 +85,7 @@ import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsSecurityButtonVi
import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel
import com.android.systemui.qs.ui.composable.QuickSettings
import com.android.systemui.qs.ui.composable.QuickSettingsTheme
+import com.android.systemui.qs.ui.compose.borderOnFocus
import com.android.systemui.res.R
import kotlinx.coroutines.launch
@@ -264,7 +266,11 @@ private fun IconButton(model: FooterActionsButtonViewModel, modifier: Modifier =
color = colorAttr(model.backgroundColor),
shape = CircleShape,
onClick = model.onClick,
- modifier = modifier,
+ modifier =
+ modifier.borderOnFocus(
+ color = MaterialTheme.colorScheme.secondary,
+ CornerSize(percent = 50),
+ ),
) {
val tint = model.iconTint?.let { Color(it) } ?: Color.Unspecified
Icon(model.icon, tint = tint, modifier = Modifier.size(20.dp))
@@ -291,7 +297,11 @@ private fun NumberButton(
shape = CircleShape,
onClick = onClick,
interactionSource = interactionSource,
- modifier = modifier,
+ modifier =
+ modifier.borderOnFocus(
+ color = MaterialTheme.colorScheme.secondary,
+ CornerSize(percent = 50),
+ ),
) {
Box(Modifier.size(40.dp)) {
Box(
@@ -342,7 +352,10 @@ private fun TextButton(
color = colorAttr(R.attr.underSurface),
contentColor = MaterialTheme.colorScheme.onSurfaceVariant,
borderStroke = BorderStroke(1.dp, colorAttr(R.attr.shadeInactive)),
- modifier = modifier.padding(horizontal = 4.dp),
+ modifier =
+ modifier
+ .padding(horizontal = 4.dp)
+ .borderOnFocus(color = MaterialTheme.colorScheme.secondary, CornerSize(50)),
onClick = onClick,
) {
Row(
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainerTransitions.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainerTransitions.kt
index 2cde6787f730ca84543fa816d14acfa2e4d52cc6..9de7a5d659ae9c98221d123ff74a732f3ce13666 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainerTransitions.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainerTransitions.kt
@@ -15,7 +15,10 @@ import com.android.systemui.scene.ui.composable.transitions.bouncerToGoneTransit
import com.android.systemui.scene.ui.composable.transitions.bouncerToLockscreenPreview
import com.android.systemui.scene.ui.composable.transitions.communalToBouncerTransition
import com.android.systemui.scene.ui.composable.transitions.communalToShadeTransition
+import com.android.systemui.scene.ui.composable.transitions.dreamToBouncerTransition
+import com.android.systemui.scene.ui.composable.transitions.dreamToCommunalTransition
import com.android.systemui.scene.ui.composable.transitions.dreamToGoneTransition
+import com.android.systemui.scene.ui.composable.transitions.dreamToShadeTransition
import com.android.systemui.scene.ui.composable.transitions.goneToQuickSettingsTransition
import com.android.systemui.scene.ui.composable.transitions.goneToShadeTransition
import com.android.systemui.scene.ui.composable.transitions.goneToSplitShadeTransition
@@ -55,7 +58,10 @@ val SceneContainerTransitions = transitions {
// Scene transitions
from(Scenes.Bouncer, to = Scenes.Gone) { bouncerToGoneTransition() }
+ from(Scenes.Dream, to = Scenes.Bouncer) { dreamToBouncerTransition() }
+ from(Scenes.Dream, to = Scenes.Communal) { dreamToCommunalTransition() }
from(Scenes.Dream, to = Scenes.Gone) { dreamToGoneTransition() }
+ from(Scenes.Dream, to = Scenes.Shade) { dreamToShadeTransition() }
from(Scenes.Gone, to = Scenes.Shade) { goneToShadeTransition() }
from(Scenes.Gone, to = Scenes.Shade, key = ToSplitShade) { goneToSplitShadeTransition() }
from(Scenes.Gone, to = Scenes.Shade, key = SlightlyFasterShadeCollapse) {
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromDreamToBouncerTransition.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromDreamToBouncerTransition.kt
new file mode 100644
index 0000000000000000000000000000000000000000..8cb89f91a831f2504cced335e85546465c194e3e
--- /dev/null
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromDreamToBouncerTransition.kt
@@ -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 com.android.systemui.scene.ui.composable.transitions
+
+import com.android.compose.animation.scene.TransitionBuilder
+
+fun TransitionBuilder.dreamToBouncerTransition() {
+ toBouncerTransition()
+}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromDreamToCommunalTransition.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromDreamToCommunalTransition.kt
new file mode 100644
index 0000000000000000000000000000000000000000..93c10b6224abfc508ca864681c3c252f0a37b321
--- /dev/null
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromDreamToCommunalTransition.kt
@@ -0,0 +1,33 @@
+/*
+ * 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.scene.ui.composable.transitions
+
+import androidx.compose.animation.core.tween
+import com.android.compose.animation.scene.Edge
+import com.android.compose.animation.scene.TransitionBuilder
+import com.android.systemui.communal.ui.compose.AllElements
+import com.android.systemui.communal.ui.compose.Communal
+
+fun TransitionBuilder.dreamToCommunalTransition() {
+ spec = tween(durationMillis = 1000)
+
+ // Translate communal hub grid from the end direction.
+ translate(Communal.Elements.Grid, Edge.End)
+
+ // Fade all communal hub elements.
+ timestampRange(startMillis = 167, endMillis = 334) { fade(AllElements) }
+}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromDreamToShadeTransition.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromDreamToShadeTransition.kt
new file mode 100644
index 0000000000000000000000000000000000000000..e35aaae19e297f6e9024a77a2a895483710a17da
--- /dev/null
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromDreamToShadeTransition.kt
@@ -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 com.android.systemui.scene.ui.composable.transitions
+
+import com.android.compose.animation.scene.TransitionBuilder
+
+fun TransitionBuilder.dreamToShadeTransition(durationScale: Double = 1.0) {
+ toShadeTransition(durationScale = durationScale)
+}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromGoneToSplitShadeTransition.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromGoneToSplitShadeTransition.kt
index 71fa6c9e567a493068a98f7fb4f6703de77a4081..ce7a85b19fb4f48ee5e4e9eeb84b1810fb21bb06 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromGoneToSplitShadeTransition.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromGoneToSplitShadeTransition.kt
@@ -19,11 +19,8 @@ package com.android.systemui.scene.ui.composable.transitions
import androidx.compose.animation.core.Spring
import androidx.compose.animation.core.spring
import androidx.compose.animation.core.tween
-import androidx.compose.foundation.gestures.Orientation
-import androidx.compose.ui.unit.IntSize
import com.android.compose.animation.scene.TransitionBuilder
import com.android.compose.animation.scene.UserActionDistance
-import com.android.compose.animation.scene.UserActionDistanceScope
import com.android.systemui.media.controls.ui.composable.MediaCarousel
import com.android.systemui.notifications.ui.composable.Notifications
import com.android.systemui.qs.ui.composable.QuickSettings
@@ -31,24 +28,17 @@ import com.android.systemui.shade.ui.composable.Shade
import com.android.systemui.shade.ui.composable.ShadeHeader
import kotlin.time.Duration.Companion.milliseconds
-fun TransitionBuilder.goneToSplitShadeTransition(
- durationScale: Double = 1.0,
-) {
+fun TransitionBuilder.goneToSplitShadeTransition(durationScale: Double = 1.0) {
spec = tween(durationMillis = (DefaultDuration * durationScale).inWholeMilliseconds.toInt())
swipeSpec =
spring(
stiffness = Spring.StiffnessMediumLow,
visibilityThreshold = Shade.Dimensions.ScrimVisibilityThreshold,
)
- distance =
- object : UserActionDistance {
- override fun UserActionDistanceScope.absoluteDistance(
- fromSceneSize: IntSize,
- orientation: Orientation,
- ): Float {
- return fromSceneSize.height.toFloat() * 2 / 3f
- }
- }
+ distance = UserActionDistance { fromContent, _, _ ->
+ val fromContentSize = checkNotNull(fromContent.targetSize())
+ fromContentSize.height.toFloat() * 2 / 3f
+ }
fractionRange(end = .33f) { fade(Shade.Elements.BackgroundScrim) }
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToSplitShadeTransition.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToSplitShadeTransition.kt
index 1486ea7d53b5b5c8555da0070e29e45bb3593e6e..1f7a7380bbc68c3f9d9d56a15f6740fb439e60fe 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToSplitShadeTransition.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToSplitShadeTransition.kt
@@ -19,35 +19,25 @@ package com.android.systemui.scene.ui.composable.transitions
import androidx.compose.animation.core.Spring
import androidx.compose.animation.core.spring
import androidx.compose.animation.core.tween
-import androidx.compose.foundation.gestures.Orientation
-import androidx.compose.ui.unit.IntSize
import com.android.compose.animation.scene.TransitionBuilder
import com.android.compose.animation.scene.UserActionDistance
-import com.android.compose.animation.scene.UserActionDistanceScope
import com.android.systemui.notifications.ui.composable.Notifications
import com.android.systemui.qs.ui.composable.QuickSettings
import com.android.systemui.shade.ui.composable.Shade
import com.android.systemui.shade.ui.composable.ShadeHeader
import kotlin.time.Duration.Companion.milliseconds
-fun TransitionBuilder.lockscreenToSplitShadeTransition(
- durationScale: Double = 1.0,
-) {
+fun TransitionBuilder.lockscreenToSplitShadeTransition(durationScale: Double = 1.0) {
spec = tween(durationMillis = (DefaultDuration * durationScale).inWholeMilliseconds.toInt())
swipeSpec =
spring(
stiffness = Spring.StiffnessMediumLow,
visibilityThreshold = Shade.Dimensions.ScrimVisibilityThreshold,
)
- distance =
- object : UserActionDistance {
- override fun UserActionDistanceScope.absoluteDistance(
- fromSceneSize: IntSize,
- orientation: Orientation,
- ): Float {
- return fromSceneSize.height.toFloat() * 2 / 3f
- }
- }
+ distance = UserActionDistance { fromContent, _, _ ->
+ val fromContentSize = checkNotNull(fromContent.targetSize())
+ fromContentSize.height.toFloat() * 2 / 3f
+ }
fractionRange(end = .33f) { fade(Shade.Elements.BackgroundScrim) }
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromShadeToQuickSettingsTransition.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromShadeToQuickSettingsTransition.kt
index 8cd357ef92a5565650027c04fecbce719b33f2e1..ba1972fbcc5a49f2c1789c616a6396509d2c9f66 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromShadeToQuickSettingsTransition.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromShadeToQuickSettingsTransition.kt
@@ -1,46 +1,36 @@
package com.android.systemui.scene.ui.composable.transitions
import androidx.compose.animation.core.tween
-import androidx.compose.foundation.gestures.Orientation
-import androidx.compose.ui.unit.IntSize
import com.android.compose.animation.scene.Edge
import com.android.compose.animation.scene.TransitionBuilder
import com.android.compose.animation.scene.UserActionDistance
-import com.android.compose.animation.scene.UserActionDistanceScope
import com.android.systemui.notifications.ui.composable.Notifications
import com.android.systemui.qs.ui.composable.QuickSettings
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.shade.ui.composable.ShadeHeader
import kotlin.time.Duration.Companion.milliseconds
-fun TransitionBuilder.shadeToQuickSettingsTransition(
- durationScale: Double = 1.0,
-) {
+fun TransitionBuilder.shadeToQuickSettingsTransition(durationScale: Double = 1.0) {
spec = tween(durationMillis = (DefaultDuration * durationScale).inWholeMilliseconds.toInt())
- distance =
- object : UserActionDistance {
- override fun UserActionDistanceScope.absoluteDistance(
- fromSceneSize: IntSize,
- orientation: Orientation,
- ): Float {
- val distance =
- Notifications.Elements.NotificationScrim.targetOffset(Scenes.Shade)?.y
- ?: return 0f
- return fromSceneSize.height - distance
- }
- }
+ distance = UserActionDistance { fromContent, _, _ ->
+ val distance =
+ Notifications.Elements.NotificationScrim.targetOffset(Scenes.Shade)?.y
+ ?: return@UserActionDistance 0f
+ val fromContentSize = checkNotNull(fromContent.targetSize())
+ fromContentSize.height - distance
+ }
translate(Notifications.Elements.NotificationScrim, Edge.Bottom)
timestampRange(endMillis = 83) { fade(QuickSettings.Elements.FooterActions) }
translate(
ShadeHeader.Elements.CollapsedContentStart,
- y = ShadeHeader.Dimensions.CollapsedHeight
+ y = ShadeHeader.Dimensions.CollapsedHeight,
)
translate(ShadeHeader.Elements.CollapsedContentEnd, y = ShadeHeader.Dimensions.CollapsedHeight)
translate(
ShadeHeader.Elements.ExpandedContent,
- y = -(ShadeHeader.Dimensions.ExpandedHeight - ShadeHeader.Dimensions.CollapsedHeight)
+ y = -(ShadeHeader.Dimensions.ExpandedHeight - ShadeHeader.Dimensions.CollapsedHeight),
)
translate(ShadeHeader.Elements.ShadeCarrierGroup, y = -ShadeHeader.Dimensions.CollapsedHeight)
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/ToBouncerTransition.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/ToBouncerTransition.kt
index de76f708c1c75ab145ceb699a7756859c1585dc1..d35537a74c8535412fcf4ce7d720d423d2f665ed 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/ToBouncerTransition.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/ToBouncerTransition.kt
@@ -28,8 +28,9 @@ private const val TO_BOUNCER_SWIPE_DISTANCE_FRACTION = 0.5f
fun TransitionBuilder.toBouncerTransition() {
spec = tween(durationMillis = 500)
- distance = UserActionDistance { fromSceneSize, _ ->
- fromSceneSize.height * TO_BOUNCER_SWIPE_DISTANCE_FRACTION
+ distance = UserActionDistance { fromContent, _, _ ->
+ val fromContentSize = checkNotNull(fromContent.targetSize())
+ fromContentSize.height * TO_BOUNCER_SWIPE_DISTANCE_FRACTION
}
translate(Bouncer.Elements.Content, y = 300.dp)
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/ToQuickSettingsShadeTransition.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/ToQuickSettingsShadeTransition.kt
index 55fa6ad94ed3916d05bc3c1767e8f799c00f0aba..e78bc6afcc4fa68755428e706ad03884e66957e4 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/ToQuickSettingsShadeTransition.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/ToQuickSettingsShadeTransition.kt
@@ -33,7 +33,10 @@ fun TransitionBuilder.toQuickSettingsShadeTransition(durationScale: Double = 1.0
stiffness = Spring.StiffnessMediumLow,
visibilityThreshold = Shade.Dimensions.ScrimVisibilityThreshold,
)
- distance = UserActionDistance { fromSceneSize, _ -> fromSceneSize.height.toFloat() * 2 / 3f }
+ distance = UserActionDistance { fromContent, _, _ ->
+ val fromContentSize = checkNotNull(fromContent.targetSize())
+ fromContentSize.height.toFloat() * 2 / 3f
+ }
translate(OverlayShade.Elements.Panel, Edge.Top)
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/ToShadeTransition.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/ToShadeTransition.kt
index b677dff2dcf98ca5713fe56fb998088b6d4e576d..bfae4897dc688e6f10c22a6427399737c2e2d058 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/ToShadeTransition.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/ToShadeTransition.kt
@@ -19,12 +19,9 @@ package com.android.systemui.scene.ui.composable.transitions
import androidx.compose.animation.core.Spring
import androidx.compose.animation.core.spring
import androidx.compose.animation.core.tween
-import androidx.compose.foundation.gestures.Orientation
-import androidx.compose.ui.unit.IntSize
import com.android.compose.animation.scene.Edge
import com.android.compose.animation.scene.TransitionBuilder
import com.android.compose.animation.scene.UserActionDistance
-import com.android.compose.animation.scene.UserActionDistanceScope
import com.android.systemui.media.controls.ui.composable.MediaCarousel
import com.android.systemui.notifications.ui.composable.Notifications
import com.android.systemui.qs.ui.composable.QuickSettings
@@ -33,24 +30,16 @@ import com.android.systemui.shade.ui.composable.Shade
import com.android.systemui.shade.ui.composable.ShadeHeader
import kotlin.time.Duration.Companion.milliseconds
-fun TransitionBuilder.toShadeTransition(
- durationScale: Double = 1.0,
-) {
+fun TransitionBuilder.toShadeTransition(durationScale: Double = 1.0) {
spec = tween(durationMillis = (DefaultDuration * durationScale).inWholeMilliseconds.toInt())
swipeSpec =
spring(
stiffness = Spring.StiffnessMediumLow,
visibilityThreshold = Shade.Dimensions.ScrimVisibilityThreshold,
)
- distance =
- object : UserActionDistance {
- override fun UserActionDistanceScope.absoluteDistance(
- fromSceneSize: IntSize,
- orientation: Orientation,
- ): Float {
- return Notifications.Elements.NotificationScrim.targetOffset(Scenes.Shade)?.y ?: 0f
- }
- }
+ distance = UserActionDistance { _, _, _ ->
+ Notifications.Elements.NotificationScrim.targetOffset(Scenes.Shade)?.y ?: 0f
+ }
fractionRange(start = .58f) {
fade(ShadeHeader.Elements.Clock)
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/SingleShadeMeasurePolicy.kt b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/SingleShadeMeasurePolicy.kt
index 352d29e2198776abb1ccb1c960f791bb555b791f..74896482be88710388f2951219e264503f83d34d 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/SingleShadeMeasurePolicy.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/SingleShadeMeasurePolicy.kt
@@ -25,7 +25,6 @@ import androidx.compose.ui.layout.Placeable
import androidx.compose.ui.layout.layoutId
import androidx.compose.ui.unit.Constraints
import androidx.compose.ui.unit.offset
-import androidx.compose.ui.util.fastFirst
import androidx.compose.ui.util.fastFirstOrNull
import com.android.systemui.shade.ui.composable.SingleShadeMeasurePolicy.LayoutId
import kotlin.math.max
@@ -60,18 +59,20 @@ class SingleShadeMeasurePolicy(
val shadeHeaderPlaceable =
measurables
- .fastFirst { it.layoutId == LayoutId.ShadeHeader }
- .measure(constraintsWithCutout)
+ .fastFirstOrNull { it.layoutId == LayoutId.ShadeHeader }
+ ?.measure(constraintsWithCutout)
val mediaPlaceable =
measurables
.fastFirstOrNull { it.layoutId == LayoutId.Media }
?.measure(applyMediaConstraints(constraintsWithCutout, isMediaInRow))
val quickSettingsPlaceable =
measurables
- .fastFirst { it.layoutId == LayoutId.QuickSettings }
- .measure(constraintsWithCutout)
+ .fastFirstOrNull { it.layoutId == LayoutId.QuickSettings }
+ ?.measure(constraintsWithCutout)
val notificationsPlaceable =
- measurables.fastFirst { it.layoutId == LayoutId.Notifications }.measure(constraints)
+ measurables
+ .fastFirstOrNull { it.layoutId == LayoutId.Notifications }
+ ?.measure(constraints)
val notificationsTop =
calculateNotificationsTop(
@@ -84,23 +85,25 @@ class SingleShadeMeasurePolicy(
onNotificationsTopChanged(notificationsTop)
return layout(constraints.maxWidth, constraints.maxHeight) {
- shadeHeaderPlaceable.placeRelative(x = insetsLeft, y = insetsTop)
- quickSettingsPlaceable.placeRelative(
+ shadeHeaderPlaceable?.placeRelative(x = insetsLeft, y = insetsTop)
+ val statusBarHeaderHeight = shadeHeaderPlaceable?.height ?: 0
+ quickSettingsPlaceable?.placeRelative(
x = insetsLeft,
- y = insetsTop + shadeHeaderPlaceable.height,
+ y = insetsTop + statusBarHeaderHeight,
)
- if (mediaPlaceable != null)
+ if (mediaPlaceable != null) {
+ val quickSettingsHeight = quickSettingsPlaceable?.height ?: 0
+
if (isMediaInRow) {
// mediaPlaceable height ranges from 0 to qsHeight. We want it to be centered
// vertically when it's smaller than the QS
- val mediaCenteringOffset =
- (quickSettingsPlaceable.height - mediaPlaceable.height) / 2
+ val mediaCenteringOffset = (quickSettingsHeight - mediaPlaceable.height) / 2
mediaPlaceable.placeRelative(
x = insetsLeft + constraintsWithCutout.maxWidth / 2,
y =
insetsTop +
- shadeHeaderPlaceable.height +
+ statusBarHeaderHeight +
mediaCenteringOffset +
mediaOffset(),
zIndex = mediaZIndex(),
@@ -108,30 +111,34 @@ class SingleShadeMeasurePolicy(
} else {
mediaPlaceable.placeRelative(
x = insetsLeft,
- y = insetsTop + shadeHeaderPlaceable.height + quickSettingsPlaceable.height,
+ y = insetsTop + statusBarHeaderHeight + quickSettingsHeight,
zIndex = mediaZIndex(),
)
}
+ }
// Notifications don't need to accommodate for horizontal insets
- notificationsPlaceable.placeRelative(x = 0, y = notificationsTop)
+ notificationsPlaceable?.placeRelative(x = 0, y = notificationsTop)
}
}
private fun calculateNotificationsTop(
- statusBarHeaderPlaceable: Placeable,
- quickSettingsPlaceable: Placeable,
+ statusBarHeaderPlaceable: Placeable?,
+ quickSettingsPlaceable: Placeable?,
mediaPlaceable: Placeable?,
insetsTop: Int,
isMediaInRow: Boolean,
): Int {
val mediaHeight = mediaPlaceable?.height ?: 0
+ val statusBarHeaderHeight = statusBarHeaderPlaceable?.height ?: 0
+ val quickSettingsHeight = quickSettingsPlaceable?.height ?: 0
+
return insetsTop +
- statusBarHeaderPlaceable.height +
+ statusBarHeaderHeight +
if (isMediaInRow) {
- max(quickSettingsPlaceable.height, mediaHeight)
+ max(quickSettingsHeight, mediaHeight)
} else {
- quickSettingsPlaceable.height + mediaHeight
+ quickSettingsHeight + mediaHeight
}
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/statusbar/phone/SystemUIDialogFactoryExt.kt b/packages/SystemUI/compose/features/src/com/android/systemui/statusbar/phone/SystemUIDialogFactoryExt.kt
index 163f4b36f4722721609af45c161b3765e4e47d20..78e605601b76df62da30302c1b74a2fb25d25b19 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/statusbar/phone/SystemUIDialogFactoryExt.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/statusbar/phone/SystemUIDialogFactoryExt.kt
@@ -307,6 +307,6 @@ private fun draggableTopPadding(): Dp {
private object DraggableBottomSheet {
val DefaultTopPadding = 64.dp
- val LargeScreenTopPadding = 72.dp
+ val LargeScreenTopPadding = 56.dp
val MaxWidth = 640.dp
}
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt
index 041cd15bdeea6752b27314a0b4190f2658ca0599..04c527176ccec821a8a08c6ce7e55645e230c864 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt
@@ -25,7 +25,6 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.round
import androidx.compose.ui.util.fastCoerceIn
import com.android.compose.animation.scene.content.Content
-import com.android.compose.animation.scene.content.state.TransitionState
import com.android.compose.animation.scene.content.state.TransitionState.HasOverscrollProperties.Companion.DistanceUnspecified
import com.android.compose.nestedscroll.OnStopScope
import com.android.compose.nestedscroll.PriorityNestedScrollConnection
@@ -36,11 +35,11 @@ internal typealias SuspendedValue = suspend () -> T
internal interface DraggableHandler {
/**
- * Start a drag with the given [pointersInfo] and [overSlop].
+ * Start a drag with the given [pointersDown] and [overSlop].
*
* The returned [DragController] should be used to continue or stop the drag.
*/
- fun onDragStarted(pointersInfo: PointersInfo?, overSlop: Float): DragController
+ fun onDragStarted(pointersDown: PointersInfo.PointersDown?, overSlop: Float): DragController
}
/**
@@ -95,7 +94,7 @@ internal class DraggableHandlerImpl(
* Note: if this returns true, then [onDragStarted] will be called with overSlop equal to 0f,
* indicating that the transition should be intercepted.
*/
- internal fun shouldImmediatelyIntercept(pointersInfo: PointersInfo?): Boolean {
+ internal fun shouldImmediatelyIntercept(pointersDown: PointersInfo.PointersDown?): Boolean {
// We don't intercept the touch if we are not currently driving the transition.
val dragController = dragController
if (dragController?.isDrivingTransition != true) {
@@ -106,7 +105,7 @@ internal class DraggableHandlerImpl(
// Only intercept the current transition if one of the 2 swipes results is also a transition
// between the same pair of contents.
- val swipes = computeSwipes(pointersInfo)
+ val swipes = computeSwipes(pointersDown)
val fromContent = layoutImpl.content(swipeAnimation.currentContent)
val (upOrLeft, downOrRight) = swipes.computeSwipesResults(fromContent)
val currentScene = layoutImpl.state.currentScene
@@ -123,7 +122,10 @@ internal class DraggableHandlerImpl(
))
}
- override fun onDragStarted(pointersInfo: PointersInfo?, overSlop: Float): DragController {
+ override fun onDragStarted(
+ pointersDown: PointersInfo.PointersDown?,
+ overSlop: Float,
+ ): DragController {
if (overSlop == 0f) {
val oldDragController = dragController
check(oldDragController != null && oldDragController.isDrivingTransition) {
@@ -148,7 +150,7 @@ internal class DraggableHandlerImpl(
return updateDragController(swipes, swipeAnimation)
}
- val swipes = computeSwipes(pointersInfo)
+ val swipes = computeSwipes(pointersDown)
val fromContent = layoutImpl.contentForUserActions()
swipes.updateSwipesResults(fromContent)
@@ -194,11 +196,11 @@ internal class DraggableHandlerImpl(
)
}
- private fun computeSwipes(pointersInfo: PointersInfo?): Swipes {
- val fromSource = pointersInfo?.let { resolveSwipeSource(it.startedPosition) }
+ private fun computeSwipes(pointersDown: PointersInfo.PointersDown?): Swipes {
+ val fromSource = pointersDown?.let { resolveSwipeSource(it.startedPosition) }
return Swipes(
- upOrLeft = resolveSwipe(orientation, isUpOrLeft = true, pointersInfo, fromSource),
- downOrRight = resolveSwipe(orientation, isUpOrLeft = false, pointersInfo, fromSource),
+ upOrLeft = resolveSwipe(orientation, isUpOrLeft = true, pointersDown, fromSource),
+ downOrRight = resolveSwipe(orientation, isUpOrLeft = false, pointersDown, fromSource),
)
}
}
@@ -206,7 +208,7 @@ internal class DraggableHandlerImpl(
private fun resolveSwipe(
orientation: Orientation,
isUpOrLeft: Boolean,
- pointersInfo: PointersInfo?,
+ pointersDown: PointersInfo.PointersDown?,
fromSource: SwipeSource.Resolved?,
): Swipe.Resolved {
return Swipe.Resolved(
@@ -227,9 +229,9 @@ private fun resolveSwipe(
}
},
// If the number of pointers is not specified, 1 is assumed.
- pointerCount = pointersInfo?.pointersDown ?: 1,
+ pointerCount = pointersDown?.count ?: 1,
// Resolves the pointer type only if all pointers are of the same type.
- pointersType = pointersInfo?.pointersDownByType?.keys?.singleOrNull(),
+ pointersType = pointersDown?.countByType?.keys?.singleOrNull(),
fromSource = fromSource,
)
}
@@ -528,82 +530,62 @@ internal class Swipes(val upOrLeft: Swipe.Resolved, val downOrRight: Swipe.Resol
}
internal class NestedScrollHandlerImpl(
- private val layoutImpl: SceneTransitionLayoutImpl,
- private val orientation: Orientation,
+ private val draggableHandler: DraggableHandlerImpl,
internal var topOrLeftBehavior: NestedScrollBehavior,
internal var bottomOrRightBehavior: NestedScrollBehavior,
internal var isExternalOverscrollGesture: () -> Boolean,
private val pointersInfoOwner: PointersInfoOwner,
) {
- private val layoutState = layoutImpl.state
- private val draggableHandler = layoutImpl.draggableHandler(orientation)
-
val connection: PriorityNestedScrollConnection = nestedScrollConnection()
- private fun resolveSwipe(isUpOrLeft: Boolean, pointersInfo: PointersInfo?): Swipe.Resolved {
- return resolveSwipe(
- orientation = draggableHandler.orientation,
- isUpOrLeft = isUpOrLeft,
- pointersInfo = pointersInfo,
- fromSource =
- pointersInfo?.let { draggableHandler.resolveSwipeSource(it.startedPosition) },
- )
- }
-
private fun nestedScrollConnection(): PriorityNestedScrollConnection {
// If we performed a long gesture before entering priority mode, we would have to avoid
// moving on to the next scene.
var canChangeScene = false
- var lastPointersInfo: PointersInfo? = null
-
- fun hasNextScene(amount: Float): Boolean {
- val transitionState = layoutState.transitionState
- val scene = transitionState.currentScene
- val fromScene = layoutImpl.scene(scene)
- val resolvedSwipe =
- when {
- amount < 0f -> resolveSwipe(isUpOrLeft = true, lastPointersInfo)
- amount > 0f -> resolveSwipe(isUpOrLeft = false, lastPointersInfo)
- else -> null
- }
- val nextScene = resolvedSwipe?.let { fromScene.findActionResultBestMatch(it) }
- if (nextScene != null) return true
+ var lastPointersDown: PointersInfo.PointersDown? = null
- if (transitionState !is TransitionState.Idle) return false
-
- val overscrollSpec = layoutImpl.state.transitions.overscrollSpec(scene, orientation)
- return overscrollSpec != null
+ fun shouldEnableSwipes(): Boolean {
+ return draggableHandler.layoutImpl
+ .contentForUserActions()
+ .shouldEnableSwipes(draggableHandler.orientation)
}
var isIntercepting = false
return PriorityNestedScrollConnection(
- orientation = orientation,
+ orientation = draggableHandler.orientation,
canStartPreScroll = { offsetAvailable, offsetBeforeStart, _ ->
- val pointersInfo = pointersInfoOwner.pointersInfo()
+ val pointersDown: PointersInfo.PointersDown? =
+ when (val info = pointersInfoOwner.pointersInfo()) {
+ PointersInfo.MouseWheel -> {
+ // Do not support mouse wheel interactions
+ return@PriorityNestedScrollConnection false
+ }
+
+ is PointersInfo.PointersDown -> info
+ null -> null
+ }
+
canChangeScene =
if (isExternalOverscrollGesture()) false else offsetBeforeStart == 0f
val canInterceptSwipeTransition =
canChangeScene &&
offsetAvailable != 0f &&
- draggableHandler.shouldImmediatelyIntercept(pointersInfo)
+ draggableHandler.shouldImmediatelyIntercept(pointersDown)
if (!canInterceptSwipeTransition) return@PriorityNestedScrollConnection false
+ val layoutImpl = draggableHandler.layoutImpl
val threshold = layoutImpl.transitionInterceptionThreshold
- val hasSnappedToIdle = layoutState.snapToIdleIfClose(threshold)
+ val hasSnappedToIdle = layoutImpl.state.snapToIdleIfClose(threshold)
if (hasSnappedToIdle) {
// If the current swipe transition is closed to 0f or 1f, then we want to
// interrupt the transition (snapping it to Idle) and scroll the list.
return@PriorityNestedScrollConnection false
}
- if (pointersInfo?.isMouseWheel == true) {
- // Do not support mouse wheel interactions
- return@PriorityNestedScrollConnection false
- }
- lastPointersInfo = pointersInfo
+ lastPointersDown = pointersDown
// If the current swipe transition is *not* closed to 0f or 1f, then we want the
// scroll events to intercept the current transition to continue the scene
@@ -622,28 +604,33 @@ internal class NestedScrollHandlerImpl(
val isZeroOffset =
if (isExternalOverscrollGesture()) false else offsetBeforeStart == 0f
- val pointersInfo = pointersInfoOwner.pointersInfo()
- if (pointersInfo?.isMouseWheel == true) {
- // Do not support mouse wheel interactions
- return@PriorityNestedScrollConnection false
- }
- lastPointersInfo = pointersInfo
+ val pointersDown: PointersInfo.PointersDown? =
+ when (val info = pointersInfoOwner.pointersInfo()) {
+ PointersInfo.MouseWheel -> {
+ // Do not support mouse wheel interactions
+ return@PriorityNestedScrollConnection false
+ }
+
+ is PointersInfo.PointersDown -> info
+ null -> null
+ }
+ lastPointersDown = pointersDown
val canStart =
when (behavior) {
NestedScrollBehavior.EdgeNoPreview -> {
canChangeScene = isZeroOffset
- isZeroOffset && hasNextScene(offsetAvailable)
+ isZeroOffset && shouldEnableSwipes()
}
NestedScrollBehavior.EdgeWithPreview -> {
canChangeScene = isZeroOffset
- hasNextScene(offsetAvailable)
+ shouldEnableSwipes()
}
NestedScrollBehavior.EdgeAlways -> {
canChangeScene = true
- hasNextScene(offsetAvailable)
+ shouldEnableSwipes()
}
}
@@ -664,14 +651,19 @@ internal class NestedScrollHandlerImpl(
// We could start an overscroll animation
canChangeScene = false
- val pointersInfo = pointersInfoOwner.pointersInfo()
- if (pointersInfo?.isMouseWheel == true) {
- // Do not support mouse wheel interactions
- return@PriorityNestedScrollConnection false
- }
- lastPointersInfo = pointersInfo
+ val pointersDown: PointersInfo.PointersDown? =
+ when (val info = pointersInfoOwner.pointersInfo()) {
+ PointersInfo.MouseWheel -> {
+ // Do not support mouse wheel interactions
+ return@PriorityNestedScrollConnection false
+ }
+
+ is PointersInfo.PointersDown -> info
+ null -> null
+ }
+ lastPointersDown = pointersDown
- val canStart = behavior.canStartOnPostFling && hasNextScene(velocityAvailable)
+ val canStart = behavior.canStartOnPostFling && shouldEnableSwipes()
if (canStart) {
isIntercepting = false
}
@@ -679,11 +671,10 @@ internal class NestedScrollHandlerImpl(
canStart
},
onStart = { firstScroll ->
- val pointersInfo = lastPointersInfo
scrollController(
dragController =
draggableHandler.onDragStarted(
- pointersInfo = pointersInfo,
+ pointersDown = lastPointersDown,
overSlop = if (isIntercepting) 0f else firstScroll,
),
canChangeScene = canChangeScene,
@@ -701,8 +692,7 @@ private fun scrollController(
): ScrollController {
return object : ScrollController {
override fun onScroll(deltaScroll: Float, source: NestedScrollSource): Float {
- val pointersInfo = pointersInfoOwner.pointersInfo()
- if (pointersInfo?.isMouseWheel == true) {
+ if (pointersInfoOwner.pointersInfo() == PointersInfo.MouseWheel) {
// Do not support mouse wheel interactions
return 0f
}
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Element.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Element.kt
index d976e8e62f3cc88231546e0c1bc831d7d274cf16..eb2a01632095ce4ef5ac0c0fd91678fd07c185e6 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Element.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Element.kt
@@ -50,6 +50,8 @@ import androidx.compose.ui.util.fastForEachReversed
import androidx.compose.ui.util.lerp
import com.android.compose.animation.scene.content.Content
import com.android.compose.animation.scene.content.state.TransitionState
+import com.android.compose.animation.scene.transformation.CustomPropertyTransformation
+import com.android.compose.animation.scene.transformation.InterpolatedPropertyTransformation
import com.android.compose.animation.scene.transformation.PropertyTransformation
import com.android.compose.animation.scene.transformation.SharedElementTransformation
import com.android.compose.animation.scene.transformation.TransformationWithRange
@@ -348,8 +350,7 @@ internal class ElementNode(
val placeInThisContent =
elementContentWhenIdle(
layoutImpl,
- currentState.currentScene,
- currentState.currentOverlays,
+ currentState,
isInContent = { it in element.stateByContent },
) == content.key
@@ -637,20 +638,11 @@ internal inline fun elementState(
internal inline fun elementContentWhenIdle(
layoutImpl: SceneTransitionLayoutImpl,
- idle: TransitionState.Idle,
- isInContent: (ContentKey) -> Boolean,
-): ContentKey {
- val currentScene = idle.currentScene
- val overlays = idle.currentOverlays
- return elementContentWhenIdle(layoutImpl, currentScene, overlays, isInContent)
-}
-
-private inline fun elementContentWhenIdle(
- layoutImpl: SceneTransitionLayoutImpl,
- currentScene: SceneKey,
- overlays: Set,
+ currentState: TransitionState,
isInContent: (ContentKey) -> Boolean,
): ContentKey {
+ val currentScene = currentState.currentScene
+ val overlays = currentState.currentOverlays
if (overlays.isEmpty()) {
return currentScene
}
@@ -1308,7 +1300,14 @@ private inline fun computeValue(
checkNotNull(if (currentContent == toContent) toState else fromState)
val idleValue = contentValue(overscrollState)
val targetValue =
- with(propertySpec.transformation) {
+ with(
+ propertySpec.transformation.requireInterpolatedTransformation(
+ element,
+ transition,
+ ) {
+ "Custom transformations in overscroll specs should not be possible"
+ }
+ ) {
layoutImpl.propertyTransformationScope.transform(
currentContent,
element.key,
@@ -1390,7 +1389,7 @@ private inline fun computeValue(
// fromContent or toContent during interruptions.
val content = contentState.content
- val transformation =
+ val transformationWithRange =
transformation(transition.transformationSpec.transformations(element.key, content))
val previewTransformation =
@@ -1403,7 +1402,14 @@ private inline fun computeValue(
val idleValue = contentValue(contentState)
val isEntering = content == toContent
val previewTargetValue =
- with(previewTransformation.transformation) {
+ with(
+ previewTransformation.transformation.requireInterpolatedTransformation(
+ element,
+ transition,
+ ) {
+ "Custom transformations in preview specs should not be possible"
+ }
+ ) {
layoutImpl.propertyTransformationScope.transform(
content,
element.key,
@@ -1413,8 +1419,15 @@ private inline fun computeValue(
}
val targetValueOrNull =
- transformation?.let { transformation ->
- with(transformation.transformation) {
+ transformationWithRange?.let { transformation ->
+ with(
+ transformation.transformation.requireInterpolatedTransformation(
+ element,
+ transition,
+ ) {
+ "Custom transformations are not allowed for properties with a preview"
+ }
+ ) {
layoutImpl.propertyTransformationScope.transform(
content,
element.key,
@@ -1461,7 +1474,7 @@ private inline fun computeValue(
lerp(
lerp(previewTargetValue, targetValueOrNull ?: idleValue, previewRangeProgress),
idleValue,
- transformation?.range?.progress(transition.progress) ?: transition.progress,
+ transformationWithRange?.range?.progress(transition.progress) ?: transition.progress,
)
} else {
if (targetValueOrNull == null) {
@@ -1474,22 +1487,39 @@ private inline fun computeValue(
lerp(
lerp(idleValue, previewTargetValue, previewRangeProgress),
targetValueOrNull,
- transformation.range?.progress(transition.progress) ?: transition.progress,
+ transformationWithRange.range?.progress(transition.progress)
+ ?: transition.progress,
)
}
}
}
- if (transformation == null) {
+ if (transformationWithRange == null) {
// If there is no transformation explicitly associated to this element value, let's use
// the value given by the system (like the current position and size given by the layout
// pass).
return currentValue()
}
+ val transformation = transformationWithRange.transformation
+ when (transformation) {
+ is CustomPropertyTransformation ->
+ return with(transformation) {
+ layoutImpl.propertyTransformationScope.transform(
+ content,
+ element.key,
+ transition,
+ transition.coroutineScope,
+ )
+ }
+ is InterpolatedPropertyTransformation -> {
+ /* continue */
+ }
+ }
+
val idleValue = contentValue(contentState)
val targetValue =
- with(transformation.transformation) {
+ with(transformation) {
layoutImpl.propertyTransformationScope.transform(
content,
element.key,
@@ -1506,7 +1536,7 @@ private inline fun computeValue(
val progress = transition.progress
// TODO(b/290184746): Make sure that we don't overflow transformations associated to a range.
- val rangeProgress = transformation.range?.progress(progress) ?: progress
+ val rangeProgress = transformationWithRange.range?.progress(progress) ?: progress
// Interpolate between the value at rest and the value before entering/after leaving.
val isEntering =
@@ -1523,6 +1553,22 @@ private inline fun computeValue(
}
}
+private inline fun PropertyTransformation.requireInterpolatedTransformation(
+ element: Element,
+ transition: TransitionState.Transition,
+ errorMessage: () -> String,
+): InterpolatedPropertyTransformation {
+ return when (this) {
+ is InterpolatedPropertyTransformation -> this
+ is CustomPropertyTransformation -> {
+ val elem = element.key.debugName
+ val fromContent = transition.fromContent
+ val toContent = transition.toContent
+ error("${errorMessage()} (element=$elem fromContent=$fromContent toContent=$toContent)")
+ }
+ }
+}
+
private inline fun interpolateSharedElement(
transition: TransitionState.Transition,
contentValue: (Element.State) -> T,
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MovableElement.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MovableElement.kt
index c790ff03aef154ed47d723534334ff7642dc1270..509a16c5a7048fc0ea5f83985f7b8807caaaecf9 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MovableElement.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MovableElement.kt
@@ -188,7 +188,9 @@ private fun shouldComposeMovableElement(
return when (
val elementState = movableElementState(element, layoutImpl.state.transitionStates)
) {
- null -> false
+ null ->
+ movableElementContentWhenIdle(layoutImpl, element, layoutImpl.state.transitionState) ==
+ content
is TransitionState.Idle ->
movableElementContentWhenIdle(layoutImpl, element, elementState) == content
is TransitionState.Transition -> {
@@ -217,7 +219,7 @@ private fun movableElementState(
private fun movableElementContentWhenIdle(
layoutImpl: SceneTransitionLayoutImpl,
element: MovableElementKey,
- elementState: TransitionState.Idle,
+ elementState: TransitionState,
): ContentKey {
val contents = element.contentPicker.contents
return elementContentWhenIdle(layoutImpl, elementState, isInContent = { contents.contains(it) })
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MultiPointerDraggable.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MultiPointerDraggable.kt
index ab2324a87d8145690abdf598c2cc4a83fad238a5..160326792f81c21f9b6570bb444dbfc343479190 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MultiPointerDraggable.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MultiPointerDraggable.kt
@@ -80,8 +80,8 @@ import kotlinx.coroutines.launch
@Stable
internal fun Modifier.multiPointerDraggable(
orientation: Orientation,
- startDragImmediately: (pointersInfo: PointersInfo) -> Boolean,
- onDragStarted: (pointersInfo: PointersInfo, overSlop: Float) -> DragController,
+ startDragImmediately: (pointersDown: PointersInfo.PointersDown) -> Boolean,
+ onDragStarted: (pointersDown: PointersInfo.PointersDown, overSlop: Float) -> DragController,
onFirstPointerDown: () -> Unit = {},
swipeDetector: SwipeDetector = DefaultSwipeDetector,
dispatcher: NestedScrollDispatcher,
@@ -99,8 +99,9 @@ internal fun Modifier.multiPointerDraggable(
private data class MultiPointerDraggableElement(
private val orientation: Orientation,
- private val startDragImmediately: (pointersInfo: PointersInfo) -> Boolean,
- private val onDragStarted: (pointersInfo: PointersInfo, overSlop: Float) -> DragController,
+ private val startDragImmediately: (pointersDown: PointersInfo.PointersDown) -> Boolean,
+ private val onDragStarted:
+ (pointersDown: PointersInfo.PointersDown, overSlop: Float) -> DragController,
private val onFirstPointerDown: () -> Unit,
private val swipeDetector: SwipeDetector,
private val dispatcher: NestedScrollDispatcher,
@@ -126,8 +127,8 @@ private data class MultiPointerDraggableElement(
internal class MultiPointerDraggableNode(
orientation: Orientation,
- var startDragImmediately: (pointersInfo: PointersInfo) -> Boolean,
- var onDragStarted: (pointersInfo: PointersInfo, overSlop: Float) -> DragController,
+ var startDragImmediately: (pointersDown: PointersInfo.PointersDown) -> Boolean,
+ var onDragStarted: (pointersDown: PointersInfo.PointersDown, overSlop: Float) -> DragController,
var onFirstPointerDown: () -> Unit,
swipeDetector: SwipeDetector = DefaultSwipeDetector,
private val dispatcher: NestedScrollDispatcher,
@@ -185,20 +186,27 @@ internal class MultiPointerDraggableNode(
private var lastPointerEvent: PointerEvent? = null
private var startedPosition: Offset? = null
- private var pointersDown: Int = 0
+ private var countPointersDown: Int = 0
internal fun pointersInfo(): PointersInfo? {
- val startedPosition = startedPosition
- val lastPointerEvent = lastPointerEvent
- if (startedPosition == null || lastPointerEvent == null) {
- // This may be null, i.e. when the user uses TalkBack
- return null
- }
+ // This may be null, i.e. when the user uses TalkBack
+ val lastPointerEvent = lastPointerEvent ?: return null
+
+ if (lastPointerEvent.type == PointerEventType.Scroll) return PointersInfo.MouseWheel
- return PointersInfo(
+ val startedPosition = startedPosition ?: return null
+
+ return PointersInfo.PointersDown(
startedPosition = startedPosition,
- pointersDown = pointersDown,
- lastPointerEvent = lastPointerEvent,
+ count = countPointersDown,
+ countByType =
+ buildMap {
+ lastPointerEvent.changes.fastForEach { change ->
+ if (!change.pressed) return@fastForEach
+ val newValue = (get(change.type) ?: 0) + 1
+ put(change.type, newValue)
+ }
+ },
)
}
@@ -218,11 +226,11 @@ internal class MultiPointerDraggableNode(
val changes = pointerEvent.changes
lastPointerEvent = pointerEvent
- pointersDown = changes.countDown()
+ countPointersDown = changes.countDown()
when {
// There are no more pointers down.
- pointersDown == 0 -> {
+ countPointersDown == 0 -> {
startedPosition = null
// In case of multiple events with 0 pointers down (not pressed) we may have
@@ -290,8 +298,8 @@ internal class MultiPointerDraggableNode(
detectDragGestures(
orientation = orientation,
startDragImmediately = startDragImmediately,
- onDragStart = { pointersInfo, overSlop ->
- onDragStarted(pointersInfo, overSlop)
+ onDragStart = { pointersDown, overSlop ->
+ onDragStarted(pointersDown, overSlop)
},
onDrag = { controller, amount ->
dispatchScrollEvents(
@@ -440,8 +448,8 @@ internal class MultiPointerDraggableNode(
*/
private suspend fun AwaitPointerEventScope.detectDragGestures(
orientation: Orientation,
- startDragImmediately: (pointersInfo: PointersInfo) -> Boolean,
- onDragStart: (pointersInfo: PointersInfo, overSlop: Float) -> DragController,
+ startDragImmediately: (pointersDown: PointersInfo.PointersDown) -> Boolean,
+ onDragStart: (pointersDown: PointersInfo.PointersDown, overSlop: Float) -> DragController,
onDrag: (controller: DragController, dragAmount: Float) -> Unit,
onDragEnd: (controller: DragController) -> Unit,
onDragCancel: (controller: DragController) -> Unit,
@@ -466,13 +474,14 @@ internal class MultiPointerDraggableNode(
.first()
var overSlop = 0f
- var lastPointersInfo =
+ var lastPointersDown: PointersInfo.PointersDown =
checkNotNull(pointersInfo()) {
"We should have pointers down, last event: $currentEvent"
}
+ as PointersInfo.PointersDown
val drag =
- if (startDragImmediately(lastPointersInfo)) {
+ if (startDragImmediately(lastPointersDown)) {
consumablePointer.consume()
consumablePointer
} else {
@@ -499,10 +508,11 @@ internal class MultiPointerDraggableNode(
)
} ?: return
- lastPointersInfo =
+ lastPointersDown =
checkNotNull(pointersInfo()) {
"We should have pointers down, last event: $currentEvent"
}
+ as PointersInfo.PointersDown
// Make sure that overSlop is not 0f. This can happen when the user drags by exactly
// the touch slop. However, the overSlop we pass to onDragStarted() is used to
// compute the direction we are dragging in, so overSlop should never be 0f unless
@@ -516,7 +526,7 @@ internal class MultiPointerDraggableNode(
drag
}
- val controller = onDragStart(lastPointersInfo, overSlop)
+ val controller = onDragStart(lastPointersDown, overSlop)
val successful: Boolean
try {
@@ -666,48 +676,31 @@ internal fun interface PointersInfoOwner {
fun pointersInfo(): PointersInfo?
}
-/**
- * Holds information about pointer interactions within a composable.
- *
- * This class stores details such as the starting position of a gesture, the number of pointers
- * down, and whether the last pointer event was a mouse wheel scroll.
- *
- * @param startedPosition The starting position of the gesture. This is the position where the first
- * pointer touched the screen, not necessarily the point where dragging begins. This may be
- * different from the initial touch position if a child composable intercepts the gesture before
- * this one.
- * @param pointersDown The number of pointers currently down.
- * @param isMouseWheel Indicates whether the last pointer event was a mouse wheel scroll.
- * @param pointersDownByType Provide a map of pointer types to the count of pointers of that type
- * currently down/pressed.
- */
-internal data class PointersInfo(
- val startedPosition: Offset,
- val pointersDown: Int,
- val isMouseWheel: Boolean,
- val pointersDownByType: Map,
-) {
- init {
- check(pointersDown > 0) { "We should have at least 1 pointer down, $pointersDown instead" }
+internal sealed interface PointersInfo {
+ /**
+ * Holds information about pointer interactions within a composable.
+ *
+ * This class stores details such as the starting position of a gesture, the number of pointers
+ * down, and whether the last pointer event was a mouse wheel scroll.
+ *
+ * @param startedPosition The starting position of the gesture. This is the position where the
+ * first pointer touched the screen, not necessarily the point where dragging begins. This may
+ * be different from the initial touch position if a child composable intercepts the gesture
+ * before this one.
+ * @param count The number of pointers currently down.
+ * @param countByType Provide a map of pointer types to the count of pointers of that type
+ * currently down/pressed.
+ */
+ data class PointersDown(
+ val startedPosition: Offset,
+ val count: Int,
+ val countByType: Map,
+ ) : PointersInfo {
+ init {
+ check(count > 0) { "We should have at least 1 pointer down, $count instead" }
+ }
}
-}
-private fun PointersInfo(
- startedPosition: Offset,
- pointersDown: Int,
- lastPointerEvent: PointerEvent,
-): PointersInfo {
- return PointersInfo(
- startedPosition = startedPosition,
- pointersDown = pointersDown,
- isMouseWheel = lastPointerEvent.type == PointerEventType.Scroll,
- pointersDownByType =
- buildMap {
- lastPointerEvent.changes.fastForEach { change ->
- if (!change.pressed) return@fastForEach
- val newValue = (get(change.type) ?: 0) + 1
- put(change.type, newValue)
- }
- },
- )
+ /** Indicates whether the last pointer event was a mouse wheel scroll. */
+ data object MouseWheel : PointersInfo
}
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/NestedScrollToScene.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/NestedScrollToScene.kt
index fbd1cd542c0546ef2072d65fe8b1da6146247ded..955be603efafdadb1900eb9b0deb93996e1d926f 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/NestedScrollToScene.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/NestedScrollToScene.kt
@@ -16,7 +16,6 @@
package com.android.compose.animation.scene
-import androidx.compose.foundation.gestures.Orientation
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
@@ -69,32 +68,28 @@ enum class NestedScrollBehavior(val canStartOnPostFling: Boolean) {
}
internal fun Modifier.nestedScrollToScene(
- layoutImpl: SceneTransitionLayoutImpl,
- orientation: Orientation,
+ draggableHandler: DraggableHandlerImpl,
topOrLeftBehavior: NestedScrollBehavior,
bottomOrRightBehavior: NestedScrollBehavior,
isExternalOverscrollGesture: () -> Boolean,
) =
this then
NestedScrollToSceneElement(
- layoutImpl = layoutImpl,
- orientation = orientation,
+ draggableHandler = draggableHandler,
topOrLeftBehavior = topOrLeftBehavior,
bottomOrRightBehavior = bottomOrRightBehavior,
isExternalOverscrollGesture = isExternalOverscrollGesture,
)
private data class NestedScrollToSceneElement(
- private val layoutImpl: SceneTransitionLayoutImpl,
- private val orientation: Orientation,
+ private val draggableHandler: DraggableHandlerImpl,
private val topOrLeftBehavior: NestedScrollBehavior,
private val bottomOrRightBehavior: NestedScrollBehavior,
private val isExternalOverscrollGesture: () -> Boolean,
) : ModifierNodeElement() {
override fun create() =
NestedScrollToSceneNode(
- layoutImpl = layoutImpl,
- orientation = orientation,
+ draggableHandler = draggableHandler,
topOrLeftBehavior = topOrLeftBehavior,
bottomOrRightBehavior = bottomOrRightBehavior,
isExternalOverscrollGesture = isExternalOverscrollGesture,
@@ -102,8 +97,7 @@ private data class NestedScrollToSceneElement(
override fun update(node: NestedScrollToSceneNode) {
node.update(
- layoutImpl = layoutImpl,
- orientation = orientation,
+ draggableHandler = draggableHandler,
topOrLeftBehavior = topOrLeftBehavior,
bottomOrRightBehavior = bottomOrRightBehavior,
isExternalOverscrollGesture = isExternalOverscrollGesture,
@@ -112,16 +106,14 @@ private data class NestedScrollToSceneElement(
override fun InspectorInfo.inspectableProperties() {
name = "nestedScrollToScene"
- properties["layoutImpl"] = layoutImpl
- properties["orientation"] = orientation
+ properties["draggableHandler"] = draggableHandler
properties["topOrLeftBehavior"] = topOrLeftBehavior
properties["bottomOrRightBehavior"] = bottomOrRightBehavior
}
}
private class NestedScrollToSceneNode(
- private var layoutImpl: SceneTransitionLayoutImpl,
- private var orientation: Orientation,
+ private var draggableHandler: DraggableHandlerImpl,
private var topOrLeftBehavior: NestedScrollBehavior,
private var bottomOrRightBehavior: NestedScrollBehavior,
private var isExternalOverscrollGesture: () -> Boolean,
@@ -129,12 +121,8 @@ private class NestedScrollToSceneNode(
private var scrollBehaviorOwner: ScrollBehaviorOwner? = null
private fun findScrollBehaviorOwner(): ScrollBehaviorOwner? {
- var behaviorOwner = scrollBehaviorOwner
- if (behaviorOwner == null) {
- behaviorOwner = findScrollBehaviorOwner(layoutImpl.draggableHandler(orientation))
- scrollBehaviorOwner = behaviorOwner
- }
- return behaviorOwner
+ return scrollBehaviorOwner
+ ?: findScrollBehaviorOwner(draggableHandler).also { scrollBehaviorOwner = it }
}
private val updateScrollBehaviorsConnection =
@@ -177,14 +165,12 @@ private class NestedScrollToSceneNode(
}
fun update(
- layoutImpl: SceneTransitionLayoutImpl,
- orientation: Orientation,
+ draggableHandler: DraggableHandlerImpl,
topOrLeftBehavior: NestedScrollBehavior,
bottomOrRightBehavior: NestedScrollBehavior,
isExternalOverscrollGesture: () -> Boolean,
) {
- this.layoutImpl = layoutImpl
- this.orientation = orientation
+ this.draggableHandler = draggableHandler
this.topOrLeftBehavior = topOrLeftBehavior
this.bottomOrRightBehavior = bottomOrRightBehavior
this.isExternalOverscrollGesture = isExternalOverscrollGesture
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt
index dbf7d7b298342f3a34d19c60d4e8855e0e5e01fb..d3ddb5003469d60ec6ddeae92af4ddbaa182b3ae 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt
@@ -637,8 +637,8 @@ sealed class UserActionResult(
fun interface UserActionDistance {
/**
- * Return the **absolute** distance of the user action given the size of the scene we are
- * animating from and the [orientation].
+ * Return the **absolute** distance of the user action when going from [fromContent] to
+ * [toContent] in the given [orientation].
*
* Note: This function will be called for each drag event until it returns a value > 0f. This
* for instance allows you to return 0f or a negative value until the first layout pass of a
@@ -646,7 +646,8 @@ fun interface UserActionDistance {
* transitioning to when computing this absolute distance.
*/
fun UserActionDistanceScope.absoluteDistance(
- fromSceneSize: IntSize,
+ fromContent: ContentKey,
+ toContent: ContentKey,
orientation: Orientation,
): Float
}
@@ -656,7 +657,8 @@ interface UserActionDistanceScope : Density, ElementStateScope
/** The user action has a fixed [absoluteDistance]. */
class FixedDistance(private val distance: Dp) : UserActionDistance {
override fun UserActionDistanceScope.absoluteDistance(
- fromSceneSize: IntSize,
+ fromContent: ContentKey,
+ toContent: ContentKey,
orientation: Orientation,
): Float = distance.toPx()
}
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutImpl.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutImpl.kt
index e93cf8f714cd08fd327770565b7e8fd760760fe8..b916b0b45e41a7a388147737443e4ac43f596630 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutImpl.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutImpl.kt
@@ -125,8 +125,8 @@ internal class SceneTransitionLayoutImpl(
}
// TODO(b/317958526): Lazily allocate scene gesture handlers the first time they are needed.
- private val horizontalDraggableHandler: DraggableHandlerImpl
- private val verticalDraggableHandler: DraggableHandlerImpl
+ internal val horizontalDraggableHandler: DraggableHandlerImpl
+ internal val verticalDraggableHandler: DraggableHandlerImpl
internal val elementStateScope = ElementStateScopeImpl(this)
internal val propertyTransformationScope = PropertyTransformationScopeImpl(this)
@@ -163,12 +163,6 @@ internal class SceneTransitionLayoutImpl(
state.checkThread()
}
- internal fun draggableHandler(orientation: Orientation): DraggableHandlerImpl =
- when (orientation) {
- Orientation.Vertical -> verticalDraggableHandler
- Orientation.Horizontal -> horizontalDraggableHandler
- }
-
internal fun scene(key: SceneKey): Scene {
return scenes[key] ?: error("Scene $key is not configured")
}
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutState.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutState.kt
index 61332b61ed1b21fd09fafae9ffaa54ff898986cf..b3fd097946d081c8a34182b5e7d70b87c021d994 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutState.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutState.kt
@@ -25,17 +25,14 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.ui.util.fastAll
import androidx.compose.ui.util.fastAny
-import androidx.compose.ui.util.fastFilter
import androidx.compose.ui.util.fastForEach
import com.android.compose.animation.scene.content.state.TransitionState
import com.android.compose.animation.scene.transformation.SharedElementTransformation
-import com.android.compose.animation.scene.transition.link.LinkedTransition
-import com.android.compose.animation.scene.transition.link.StateLink
import kotlin.math.absoluteValue
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.Job
-import kotlinx.coroutines.coroutineScope
+import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch
/**
@@ -236,7 +233,6 @@ fun MutableSceneTransitionLayoutState(
canShowOverlay: (OverlayKey) -> Boolean = { true },
canHideOverlay: (OverlayKey) -> Boolean = { true },
canReplaceOverlay: (from: OverlayKey, to: OverlayKey) -> Boolean = { _, _ -> true },
- stateLinks: List = emptyList(),
): MutableSceneTransitionLayoutState {
return MutableSceneTransitionLayoutStateImpl(
initialScene,
@@ -246,7 +242,6 @@ fun MutableSceneTransitionLayoutState(
canShowOverlay,
canHideOverlay,
canReplaceOverlay,
- stateLinks,
)
}
@@ -258,10 +253,7 @@ internal class MutableSceneTransitionLayoutStateImpl(
internal val canChangeScene: (SceneKey) -> Boolean = { true },
internal val canShowOverlay: (OverlayKey) -> Boolean = { true },
internal val canHideOverlay: (OverlayKey) -> Boolean = { true },
- internal val canReplaceOverlay: (from: OverlayKey, to: OverlayKey) -> Boolean = { _, _ ->
- true
- },
- private val stateLinks: List = emptyList(),
+ internal val canReplaceOverlay: (from: OverlayKey, to: OverlayKey) -> Boolean = { _, _ -> true },
) : MutableSceneTransitionLayoutState {
private val creationThread: Thread = Thread.currentThread()
@@ -275,11 +267,12 @@ internal class MutableSceneTransitionLayoutStateImpl(
private set
/**
- * The flattened list of [SharedElementTransformation] within all the transitions in
+ * The flattened list of [SharedElementTransformation.Factory] within all the transitions in
* [transitionStates].
*/
- private val transformationsWithElevation: List by derivedStateOf {
- transformationsWithElevation(transitionStates)
+ private val transformationFactoriesWithElevation:
+ List by derivedStateOf {
+ transformationFactoriesWithElevation(transitionStates)
}
override val currentScene: SceneKey
@@ -361,29 +354,27 @@ internal class MutableSceneTransitionLayoutStateImpl(
}
override suspend fun startTransition(transition: TransitionState.Transition, chain: Boolean) {
+ Log.i(TAG, "startTransition(transition=$transition, chain=$chain)")
checkThread()
- try {
- // Keep a reference to the previous transition (if any).
- val previousTransition = currentTransition
+ // Prepare the transition before starting it. This is outside of the try/finally block on
+ // purpose because preparing a transition might throw an exception (e.g. if we find multiple
+ // specs matching this transition), in which case we want to throw that exception here
+ // before even starting the transition.
+ prepareTransitionBeforeStarting(transition)
+ try {
// Start the transition.
startTransitionInternal(transition, chain)
- // Handle transition links.
- previousTransition?.let { cancelActiveTransitionLinks(it) }
- if (stateLinks.isNotEmpty()) {
- coroutineScope { setupTransitionLinks(transition) }
- }
-
// Run the transition until it is finished.
- transition.run()
+ transition.runInternal()
} finally {
finishTransition(transition)
}
}
- private fun startTransitionInternal(transition: TransitionState.Transition, chain: Boolean) {
+ private fun prepareTransitionBeforeStarting(transition: TransitionState.Transition) {
// Set the current scene and overlays on the transition.
val currentState = transitionState
transition.currentSceneWhenTransitionStarted = currentState.currentScene
@@ -411,7 +402,9 @@ internal class MutableSceneTransitionLayoutStateImpl(
} else {
transition.updateOverscrollSpecs(fromSpec = null, toSpec = null)
}
+ }
+ private fun startTransitionInternal(transition: TransitionState.Transition, chain: Boolean) {
when (val currentState = transitionStates.last()) {
is TransitionState.Idle -> {
// Replace [Idle] by [transition].
@@ -471,42 +464,6 @@ internal class MutableSceneTransitionLayoutStateImpl(
)
}
- private fun cancelActiveTransitionLinks(transition: TransitionState.Transition) {
- transition.activeTransitionLinks.forEach { (link, linkedTransition) ->
- link.target.finishTransition(linkedTransition)
- }
- transition.activeTransitionLinks.clear()
- }
-
- private fun CoroutineScope.setupTransitionLinks(transition: TransitionState.Transition) {
- stateLinks.fastForEach { stateLink ->
- val matchingLinks =
- stateLink.transitionLinks.fastFilter { it.isMatchingLink(transition) }
- if (matchingLinks.isEmpty()) return@fastForEach
- if (matchingLinks.size > 1) error("More than one link matched.")
-
- val targetCurrentScene = stateLink.target.transitionState.currentScene
- val matchingLink = matchingLinks[0]
-
- if (!matchingLink.targetIsInValidState(targetCurrentScene)) return@fastForEach
-
- val linkedTransition =
- LinkedTransition(
- originalTransition = transition,
- fromScene = targetCurrentScene,
- toScene = matchingLink.targetTo,
- key = matchingLink.targetTransitionKey,
- )
-
- // Start with UNDISPATCHED so that startTransition is called directly and the new linked
- // transition is observable directly.
- launch(start = CoroutineStart.UNDISPATCHED) {
- stateLink.target.startTransition(linkedTransition)
- }
- transition.activeTransitionLinks[stateLink] = linkedTransition
- }
- }
-
/**
* Notify that [transition] was finished and that it settled to its
* [currentScene][TransitionState.currentScene]. This will do nothing if [transition] was
@@ -520,9 +477,9 @@ internal class MutableSceneTransitionLayoutStateImpl(
return
}
- // Make sure that this transition settles in case it was force finished, for instance by
- // calling snapToScene().
- transition.freezeAndAnimateToCurrentState()
+ // Make sure that this transition is cancelled in case it was force finished, for instance
+ // if snapToScene() is called.
+ transition.coroutineScope.cancel()
val transitionStates = this.transitionStates
if (!transitionStates.contains(transition)) {
@@ -530,14 +487,12 @@ internal class MutableSceneTransitionLayoutStateImpl(
return
}
+ Log.i(TAG, "finishTransition(transition=$transition)")
check(transitionStates.fastAll { it is TransitionState.Transition })
// Mark this transition as finished.
finishedTransitions.add(transition)
- // Finish all linked transitions.
- finishActiveTransitionLinks(transition)
-
// Keep a reference to the last transition, in case we remove all transitions and should
// settle to Idle.
val lastTransition = transitionStates.last()
@@ -560,13 +515,10 @@ internal class MutableSceneTransitionLayoutStateImpl(
// If all transitions are finished, we are idle.
if (i == nStates) {
check(finishedTransitions.isEmpty())
- this.transitionStates =
- listOf(
- TransitionState.Idle(
- lastTransition.currentScene,
- lastTransition.currentOverlays,
- )
- )
+ val idle =
+ TransitionState.Idle(lastTransition.currentScene, lastTransition.currentOverlays)
+ Log.i(TAG, "all transitions finished. idle=$idle")
+ this.transitionStates = listOf(idle)
} else if (i > 0) {
this.transitionStates = transitionStates.subList(fromIndex = i, toIndex = nStates)
}
@@ -584,13 +536,6 @@ internal class MutableSceneTransitionLayoutStateImpl(
transitionStates = listOf(TransitionState.Idle(scene, currentOverlays))
}
- private fun finishActiveTransitionLinks(transition: TransitionState.Transition) {
- for ((link, linkedTransition) in transition.activeTransitionLinks) {
- link.target.finishTransition(linkedTransition)
- }
- transition.activeTransitionLinks.clear()
- }
-
/**
* Check if a transition is in progress. If the progress value is near 0 or 1, immediately snap
* to the closest scene.
@@ -614,8 +559,8 @@ internal class MutableSceneTransitionLayoutStateImpl(
}
val shouldSnap =
- (isProgressCloseTo(0f) && transition.currentScene == transition.fromContent) ||
- (isProgressCloseTo(1f) && transition.currentScene == transition.toContent)
+ (isProgressCloseTo(0f) && transition.isFromCurrentContent()) ||
+ (isProgressCloseTo(1f) && transition.isToCurrentContent())
return if (shouldSnap) {
finishAllTransitions()
true
@@ -755,22 +700,23 @@ internal class MutableSceneTransitionLayoutStateImpl(
animate()
}
- private fun transformationsWithElevation(
+ private fun transformationFactoriesWithElevation(
transitionStates: List
- ): List {
+ ): List {
return buildList {
transitionStates.fastForEach { state ->
if (state !is TransitionState.Transition) {
return@fastForEach
}
- state.transformationSpec.transformations.fastForEach { transformationWithRange ->
- val transformation = transformationWithRange.transformation
+ state.transformationSpec.transformationMatchers.fastForEach { transformationMatcher
+ ->
+ val factory = transformationMatcher.factory
if (
- transformation is SharedElementTransformation &&
- transformation.elevateInContent != null
+ factory is SharedElementTransformation.Factory &&
+ factory.elevateInContent != null
) {
- add(transformation)
+ add(factory)
}
}
}
@@ -785,10 +731,10 @@ internal class MutableSceneTransitionLayoutStateImpl(
* necessary, for performance.
*/
internal fun isElevationPossible(content: ContentKey, element: ElementKey?): Boolean {
- if (transformationsWithElevation.isEmpty()) return false
- return transformationsWithElevation.fastAny { transformation ->
- transformation.elevateInContent == content &&
- (element == null || transformation.matcher.matches(element, content))
+ if (transformationFactoriesWithElevation.isEmpty()) return false
+ return transformationFactoriesWithElevation.fastAny { factory ->
+ factory.elevateInContent == content &&
+ (element == null || factory.matcher.matches(element, content))
}
}
}
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitions.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitions.kt
index b083f79aebf515bf4b907a5a59309c741f169074..8df3f2d932b32a0ce485abeeaf8bede511231b38 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitions.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitions.kt
@@ -26,18 +26,10 @@ import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.util.fastForEach
import com.android.compose.animation.scene.content.state.TransitionState
-import com.android.compose.animation.scene.transformation.AnchoredSize
-import com.android.compose.animation.scene.transformation.AnchoredTranslate
-import com.android.compose.animation.scene.transformation.DrawScale
-import com.android.compose.animation.scene.transformation.EdgeTranslate
-import com.android.compose.animation.scene.transformation.Fade
-import com.android.compose.animation.scene.transformation.OverscrollTranslate
import com.android.compose.animation.scene.transformation.PropertyTransformation
-import com.android.compose.animation.scene.transformation.ScaleSize
import com.android.compose.animation.scene.transformation.SharedElementTransformation
-import com.android.compose.animation.scene.transformation.Transformation
+import com.android.compose.animation.scene.transformation.TransformationMatcher
import com.android.compose.animation.scene.transformation.TransformationWithRange
-import com.android.compose.animation.scene.transformation.Translate
/** The transitions configuration of a [SceneTransitionLayout]. */
class SceneTransitions
@@ -169,7 +161,7 @@ internal constructor(
}
/** The definition of a transition between [from] and [to]. */
-interface TransitionSpec {
+internal interface TransitionSpec {
/** The key of this [TransitionSpec]. */
val key: TransitionKey?
@@ -209,7 +201,7 @@ interface TransitionSpec {
fun previewTransformationSpec(transition: TransitionState.Transition): TransformationSpec?
}
-interface TransformationSpec {
+internal interface TransformationSpec {
/**
* The [AnimationSpec] used to animate the associated transition progress from `0` to `1` when
* the transition is triggered (i.e. it is not gesture-based).
@@ -232,8 +224,8 @@ interface TransformationSpec {
*/
val distance: UserActionDistance?
- /** The list of [Transformation] applied to elements during this transition. */
- val transformations: List>
+ /** The list of [TransformationMatcher] applied to elements during this transformation. */
+ val transformationMatchers: List
companion object {
internal val Empty =
@@ -241,7 +233,7 @@ interface TransformationSpec {
progressSpec = snap(),
swipeSpec = null,
distance = null,
- transformations = emptyList(),
+ transformationMatchers = emptyList(),
)
internal val EmptyProvider = { _: TransitionState.Transition -> Empty }
}
@@ -272,7 +264,14 @@ internal class TransitionSpecImpl(
progressSpec = reverse.progressSpec,
swipeSpec = reverse.swipeSpec,
distance = reverse.distance,
- transformations = reverse.transformations.map { it.reversed() },
+ transformationMatchers =
+ reverse.transformationMatchers.map {
+ TransformationMatcher(
+ matcher = it.matcher,
+ factory = it.factory,
+ range = it.range?.reversed(),
+ )
+ },
)
},
)
@@ -288,7 +287,7 @@ internal class TransitionSpecImpl(
}
/** The definition of the overscroll behavior of the [content]. */
-interface OverscrollSpec {
+internal interface OverscrollSpec {
/** The scene we are over scrolling. */
val content: ContentKey
@@ -325,7 +324,7 @@ internal class TransformationSpecImpl(
override val progressSpec: AnimationSpec,
override val swipeSpec: SpringSpec?,
override val distance: UserActionDistance?,
- override val transformations: List>,
+ override val transformationMatchers: List,
) : TransformationSpec {
private val cache = mutableMapOf>()
@@ -335,7 +334,7 @@ internal class TransformationSpecImpl(
.getOrPut(content) { computeTransformations(element, content) }
}
- /** Filter [transformations] to compute the [ElementTransformations] of [element]. */
+ /** Filter [transformationMatchers] to compute the [ElementTransformations] of [element]. */
private fun computeTransformations(
element: ElementKey,
content: ContentKey,
@@ -346,48 +345,56 @@ internal class TransformationSpecImpl(
var drawScale: TransformationWithRange>? = null
var alpha: TransformationWithRange>? = null
- transformations.fastForEach { transformationWithRange ->
- val transformation = transformationWithRange.transformation
- if (!transformation.matcher.matches(element, content)) {
+ transformationMatchers.fastForEach { transformationMatcher ->
+ if (!transformationMatcher.matcher.matches(element, content)) {
return@fastForEach
}
- when (transformation) {
- is SharedElementTransformation -> {
- throwIfNotNull(shared, element, name = "shared")
- shared =
- transformationWithRange
- as TransformationWithRange
+ val transformation = transformationMatcher.factory.create()
+ val property =
+ when (transformation) {
+ is SharedElementTransformation -> {
+ throwIfNotNull(shared, element, name = "shared")
+ shared =
+ TransformationWithRange(transformation, transformationMatcher.range)
+ return@fastForEach
+ }
+ is PropertyTransformation<*> -> transformation.property
}
- is Translate,
- is OverscrollTranslate,
- is EdgeTranslate,
- is AnchoredTranslate -> {
+
+ when (property) {
+ is PropertyTransformation.Property.Offset -> {
throwIfNotNull(offset, element, name = "offset")
offset =
- transformationWithRange
- as TransformationWithRange>
+ TransformationWithRange(
+ transformation as PropertyTransformation,
+ transformationMatcher.range,
+ )
}
- is ScaleSize,
- is AnchoredSize -> {
+ is PropertyTransformation.Property.Size -> {
throwIfNotNull(size, element, name = "size")
size =
- transformationWithRange
- as TransformationWithRange>
+ TransformationWithRange(
+ transformation as PropertyTransformation,
+ transformationMatcher.range,
+ )
}
- is DrawScale -> {
+ is PropertyTransformation.Property.Scale -> {
throwIfNotNull(drawScale, element, name = "drawScale")
drawScale =
- transformationWithRange
- as TransformationWithRange>
+ TransformationWithRange(
+ transformation as PropertyTransformation,
+ transformationMatcher.range,
+ )
}
- is Fade -> {
+ is PropertyTransformation.Property.Alpha -> {
throwIfNotNull(alpha, element, name = "alpha")
alpha =
- transformationWithRange
- as TransformationWithRange>
+ TransformationWithRange(
+ transformation as PropertyTransformation,
+ transformationMatcher.range,
+ )
}
- else -> error("Unknown transformation: $transformation")
}
}
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeAnimation.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeAnimation.kt
index f0043e1e89b0a3eb477b30a15e40cb5f1bfc6aa0..dbfeb5cd0168eaf92c5f97b384867009ef74b153 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeAnimation.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeAnimation.kt
@@ -24,7 +24,6 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
-import androidx.compose.ui.unit.IntSize
import com.android.compose.animation.scene.content.state.TransitionState
import com.android.compose.animation.scene.content.state.TransitionState.HasOverscrollProperties.Companion.DistanceUnspecified
import kotlin.math.absoluteValue
@@ -66,8 +65,9 @@ internal fun createSwipeAnimation(
val absoluteDistance =
with(animation.contentTransition.transformationSpec.distance ?: DefaultSwipeDistance) {
layoutImpl.userActionDistanceScope.absoluteDistance(
- layoutImpl.content(animation.fromContent).targetSize,
- orientation,
+ fromContent = animation.fromContent,
+ toContent = animation.toContent,
+ orientation = orientation,
)
}
@@ -475,12 +475,14 @@ internal class SwipeAnimation(
private object DefaultSwipeDistance : UserActionDistance {
override fun UserActionDistanceScope.absoluteDistance(
- fromSceneSize: IntSize,
+ fromContent: ContentKey,
+ toContent: ContentKey,
orientation: Orientation,
): Float {
+ val fromContentSize = checkNotNull(fromContent.targetSize())
return when (orientation) {
- Orientation.Horizontal -> fromSceneSize.width
- Orientation.Vertical -> fromSceneSize.height
+ Orientation.Horizontal -> fromContentSize.width
+ Orientation.Vertical -> fromContentSize.height
}.toFloat()
}
}
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeToScene.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeToScene.kt
index ba5f4144aff987c55157a832d9ec7e176e75b79a..5ab306a63a7e1021e836c3bc4b2cd6107caf81c8 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeToScene.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeToScene.kt
@@ -56,7 +56,7 @@ private fun DraggableHandlerImpl.contentForSwipes(): Content {
}
/** Whether swipe should be enabled in the given [orientation]. */
-private fun Content.shouldEnableSwipes(orientation: Orientation): Boolean {
+internal fun Content.shouldEnableSwipes(orientation: Orientation): Boolean {
if (userActions.isEmpty()) {
return false
}
@@ -165,8 +165,7 @@ private class SwipeToSceneNode(
private val nestedScrollHandlerImpl =
NestedScrollHandlerImpl(
- layoutImpl = draggableHandler.layoutImpl,
- orientation = draggableHandler.orientation,
+ draggableHandler = draggableHandler,
topOrLeftBehavior = NestedScrollBehavior.Default,
bottomOrRightBehavior = NestedScrollBehavior.Default,
isExternalOverscrollGesture = { false },
@@ -200,10 +199,10 @@ private class SwipeToSceneNode(
override fun onCancelPointerInput() = multiPointerDraggableNode.onCancelPointerInput()
- private fun startDragImmediately(pointersInfo: PointersInfo): Boolean {
+ private fun startDragImmediately(pointersDown: PointersInfo.PointersDown): Boolean {
// Immediately start the drag if the user can't swipe in the other direction and the gesture
// handler can intercept it.
- return !canOppositeSwipe() && draggableHandler.shouldImmediatelyIntercept(pointersInfo)
+ return !canOppositeSwipe() && draggableHandler.shouldImmediatelyIntercept(pointersDown)
}
private fun canOppositeSwipe(): Boolean {
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDsl.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDsl.kt
index dc26b6b382b4ad56f71054b2991322d8e665e2bb..48f08a7086d61752acd099ca032f66722d8b20ff 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDsl.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDsl.kt
@@ -26,6 +26,7 @@ import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import com.android.compose.animation.scene.content.state.TransitionState
+import com.android.compose.animation.scene.transformation.Transformation
import kotlin.math.tanh
/** Define the [transitions][SceneTransitions] to be used with a [SceneTransitionLayout]. */
@@ -75,7 +76,7 @@ interface SceneTransitionsBuilder {
preview: (TransitionBuilder.() -> Unit)? = null,
reversePreview: (TransitionBuilder.() -> Unit)? = null,
builder: TransitionBuilder.() -> Unit = {},
- ): TransitionSpec
+ )
/**
* Define the animation to be played when transitioning [from] the specified content. For the
@@ -101,7 +102,7 @@ interface SceneTransitionsBuilder {
preview: (TransitionBuilder.() -> Unit)? = null,
reversePreview: (TransitionBuilder.() -> Unit)? = null,
builder: TransitionBuilder.() -> Unit = {},
- ): TransitionSpec
+ )
/**
* Define the animation to be played when the [content] is overscrolled in the given
@@ -114,13 +115,13 @@ interface SceneTransitionsBuilder {
content: ContentKey,
orientation: Orientation,
builder: OverscrollBuilder.() -> Unit,
- ): OverscrollSpec
+ )
/**
* Prevents overscroll the [content] in the given [orientation], allowing ancestors to
* eventually consume the remaining gesture.
*/
- fun overscrollDisabled(content: ContentKey, orientation: Orientation): OverscrollSpec
+ fun overscrollDisabled(content: ContentKey, orientation: Orientation)
}
interface BaseTransitionBuilder : PropertyTransformationBuilder {
@@ -527,6 +528,9 @@ interface PropertyTransformationBuilder {
anchorWidth: Boolean = true,
anchorHeight: Boolean = true,
)
+
+ /** Apply a [transformation] to the element(s) matching [matcher]. */
+ fun transformation(matcher: ElementMatcher, transformation: Transformation.Factory)
}
/** This converter lets you change a linear progress into a function of your choice. */
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDslImpl.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDslImpl.kt
index e461f9ccc295e6bd3c75e58f2c98f448d6990034..6742b3200ac450495076635a8dba54e75116a709 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDslImpl.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDslImpl.kt
@@ -37,8 +37,8 @@ import com.android.compose.animation.scene.transformation.OverscrollTranslate
import com.android.compose.animation.scene.transformation.ScaleSize
import com.android.compose.animation.scene.transformation.SharedElementTransformation
import com.android.compose.animation.scene.transformation.Transformation
+import com.android.compose.animation.scene.transformation.TransformationMatcher
import com.android.compose.animation.scene.transformation.TransformationRange
-import com.android.compose.animation.scene.transformation.TransformationWithRange
import com.android.compose.animation.scene.transformation.Translate
internal fun transitionsImpl(builder: SceneTransitionsBuilder.() -> Unit): SceneTransitions {
@@ -66,8 +66,8 @@ private class SceneTransitionsBuilderImpl : SceneTransitionsBuilder {
preview: (TransitionBuilder.() -> Unit)?,
reversePreview: (TransitionBuilder.() -> Unit)?,
builder: TransitionBuilder.() -> Unit,
- ): TransitionSpec {
- return transition(from = null, to = to, key = key, preview, reversePreview, builder)
+ ) {
+ transition(from = null, to = to, key = key, preview, reversePreview, builder)
}
override fun from(
@@ -77,25 +77,25 @@ private class SceneTransitionsBuilderImpl : SceneTransitionsBuilder {
preview: (TransitionBuilder.() -> Unit)?,
reversePreview: (TransitionBuilder.() -> Unit)?,
builder: TransitionBuilder.() -> Unit,
- ): TransitionSpec {
- return transition(from = from, to = to, key = key, preview, reversePreview, builder)
+ ) {
+ transition(from = from, to = to, key = key, preview, reversePreview, builder)
}
override fun overscroll(
content: ContentKey,
orientation: Orientation,
builder: OverscrollBuilder.() -> Unit,
- ): OverscrollSpec {
+ ) {
val impl = OverscrollBuilderImpl().apply(builder)
- check(impl.transformations.isNotEmpty()) {
+ check(impl.transformationMatchers.isNotEmpty()) {
"This method does not allow empty transformations. " +
"Use overscrollDisabled($content, $orientation) instead."
}
- return overscrollSpec(content, orientation, impl)
+ overscrollSpec(content, orientation, impl)
}
- override fun overscrollDisabled(content: ContentKey, orientation: Orientation): OverscrollSpec {
- return overscrollSpec(content, orientation, OverscrollBuilderImpl())
+ override fun overscrollDisabled(content: ContentKey, orientation: Orientation) {
+ overscrollSpec(content, orientation, OverscrollBuilderImpl())
}
private fun overscrollSpec(
@@ -112,7 +112,7 @@ private class SceneTransitionsBuilderImpl : SceneTransitionsBuilder {
progressSpec = snap(),
swipeSpec = null,
distance = impl.distance,
- transformations = impl.transformations,
+ transformationMatchers = impl.transformationMatchers,
),
progressConverter = impl.progressConverter,
)
@@ -137,7 +137,7 @@ private class SceneTransitionsBuilderImpl : SceneTransitionsBuilder {
progressSpec = impl.spec,
swipeSpec = impl.swipeSpec,
distance = impl.distance,
- transformations = impl.transformations,
+ transformationMatchers = impl.transformationMatchers,
)
}
@@ -157,7 +157,7 @@ private class SceneTransitionsBuilderImpl : SceneTransitionsBuilder {
}
internal abstract class BaseTransitionBuilderImpl : BaseTransitionBuilder {
- val transformations = mutableListOf>()
+ val transformationMatchers = mutableListOf()
private var range: TransformationRange? = null
protected var reversed = false
override var distance: UserActionDistance? = null
@@ -173,23 +173,31 @@ internal abstract class BaseTransitionBuilderImpl : BaseTransitionBuilder {
range = null
}
- protected fun transformation(transformation: Transformation) {
- val transformationWithRange = TransformationWithRange(transformation, range)
- transformations.add(
- if (reversed) {
- transformationWithRange.reversed()
- } else {
- transformationWithRange
- }
+ protected fun addTransformation(
+ matcher: ElementMatcher,
+ transformation: Transformation.Factory,
+ ) {
+ transformationMatchers.add(
+ TransformationMatcher(
+ matcher,
+ transformation,
+ range?.let { range ->
+ if (reversed) {
+ range.reversed()
+ } else {
+ range
+ }
+ },
+ )
)
}
override fun fade(matcher: ElementMatcher) {
- transformation(Fade(matcher))
+ addTransformation(matcher, Fade.Factory)
}
override fun translate(matcher: ElementMatcher, x: Dp, y: Dp) {
- transformation(Translate(matcher, x, y))
+ addTransformation(matcher, Translate.Factory(x, y))
}
override fun translate(
@@ -197,19 +205,19 @@ internal abstract class BaseTransitionBuilderImpl : BaseTransitionBuilder {
edge: Edge,
startsOutsideLayoutBounds: Boolean,
) {
- transformation(EdgeTranslate(matcher, edge, startsOutsideLayoutBounds))
+ addTransformation(matcher, EdgeTranslate.Factory(edge, startsOutsideLayoutBounds))
}
override fun anchoredTranslate(matcher: ElementMatcher, anchor: ElementKey) {
- transformation(AnchoredTranslate(matcher, anchor))
+ addTransformation(matcher, AnchoredTranslate.Factory(anchor))
}
override fun scaleSize(matcher: ElementMatcher, width: Float, height: Float) {
- transformation(ScaleSize(matcher, width, height))
+ addTransformation(matcher, ScaleSize.Factory(width, height))
}
override fun scaleDraw(matcher: ElementMatcher, scaleX: Float, scaleY: Float, pivot: Offset) {
- transformation(DrawScale(matcher, scaleX, scaleY, pivot))
+ addTransformation(matcher, DrawScale.Factory(scaleX, scaleY, pivot))
}
override fun anchoredSize(
@@ -218,7 +226,12 @@ internal abstract class BaseTransitionBuilderImpl : BaseTransitionBuilder {
anchorWidth: Boolean,
anchorHeight: Boolean,
) {
- transformation(AnchoredSize(matcher, anchor, anchorWidth, anchorHeight))
+ addTransformation(matcher, AnchoredSize.Factory(anchor, anchorWidth, anchorHeight))
+ }
+
+ override fun transformation(matcher: ElementMatcher, transformation: Transformation.Factory) {
+ check(range == null) { "Custom transformations can not be applied inside a range" }
+ addTransformation(matcher, transformation)
}
}
@@ -257,7 +270,10 @@ internal class TransitionBuilderImpl(override val transition: TransitionState.Tr
"(${transition.toContent.debugName})"
}
- transformation(SharedElementTransformation(matcher, enabled, elevateInContent))
+ addTransformation(
+ matcher,
+ SharedElementTransformation.Factory(matcher, enabled, elevateInContent),
+ )
}
override fun timestampRange(
@@ -288,6 +304,6 @@ internal open class OverscrollBuilderImpl : BaseTransitionBuilderImpl(), Overscr
x: OverscrollScope.() -> Float,
y: OverscrollScope.() -> Float,
) {
- transformation(OverscrollTranslate(matcher, x, y))
+ addTransformation(matcher, OverscrollTranslate.Factory(x, y))
}
}
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/Content.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/Content.kt
index 8187e393297537efe79302a017ea2b0924b4c9d2..255a16c6de6b7377715c39893ac308288e8ef79a 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/Content.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/Content.kt
@@ -16,7 +16,7 @@
package com.android.compose.animation.scene.content
-import androidx.compose.foundation.gestures.Orientation
+import android.annotation.SuppressLint
import androidx.compose.foundation.layout.Box
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
@@ -72,6 +72,7 @@ internal sealed class Content(
var targetSize by mutableStateOf(IntSize.Zero)
var userActions by mutableStateOf(actions)
+ @SuppressLint("NotConstructor")
@Composable
fun Content(modifier: Modifier = Modifier) {
Box(
@@ -151,8 +152,7 @@ internal class ContentScopeImpl(
isExternalOverscrollGesture: () -> Boolean,
): Modifier {
return nestedScrollToScene(
- layoutImpl = layoutImpl,
- orientation = Orientation.Horizontal,
+ draggableHandler = layoutImpl.horizontalDraggableHandler,
topOrLeftBehavior = leftBehavior,
bottomOrRightBehavior = rightBehavior,
isExternalOverscrollGesture = isExternalOverscrollGesture,
@@ -165,8 +165,7 @@ internal class ContentScopeImpl(
isExternalOverscrollGesture: () -> Boolean,
): Modifier {
return nestedScrollToScene(
- layoutImpl = layoutImpl,
- orientation = Orientation.Vertical,
+ draggableHandler = layoutImpl.verticalDraggableHandler,
topOrLeftBehavior = topBehavior,
bottomOrRightBehavior = bottomBehavior,
isExternalOverscrollGesture = isExternalOverscrollGesture,
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/state/TransitionState.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/state/TransitionState.kt
index 7d29a68e3a8dddf719049d79f5835413b91e1ab6..d66fe42084de2d7da43d7437716974bce3f9e045 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/state/TransitionState.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/state/TransitionState.kt
@@ -18,6 +18,7 @@ package com.android.compose.animation.scene.content.state
import androidx.compose.animation.core.Animatable
import androidx.compose.animation.core.AnimationVector1D
+import androidx.compose.animation.core.Spring
import androidx.compose.animation.core.spring
import androidx.compose.foundation.gestures.Orientation
import androidx.compose.runtime.Stable
@@ -34,8 +35,8 @@ import com.android.compose.animation.scene.SceneTransitionLayoutImpl
import com.android.compose.animation.scene.TransformationSpec
import com.android.compose.animation.scene.TransformationSpecImpl
import com.android.compose.animation.scene.TransitionKey
-import com.android.compose.animation.scene.transition.link.LinkedTransition
-import com.android.compose.animation.scene.transition.link.StateLink
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.launch
/** The state associated to a [SceneTransitionLayout] at some specific point in time. */
@@ -89,6 +90,10 @@ sealed interface TransitionState {
// The set of overlays does not change in a [ChangeCurrentScene] transition.
return currentOverlaysWhenTransitionStarted
}
+
+ override fun toString(): String {
+ return "ChangeScene(fromScene=$fromScene, toScene=$toScene)"
+ }
}
/**
@@ -129,7 +134,7 @@ sealed interface TransitionState {
* starting a swipe transition to show [overlay] and will be `true` only once the swipe
* transition is committed.
*/
- protected abstract val isEffectivelyShown: Boolean
+ abstract val isEffectivelyShown: Boolean
init {
check(
@@ -145,6 +150,12 @@ sealed interface TransitionState {
currentOverlaysWhenTransitionStarted - overlay
}
}
+
+ override fun toString(): String {
+ val isShowing = overlay == toContent
+ return "ShowOrHideOverlay(overlay=$overlay, fromOrToScene=$fromOrToScene, " +
+ "isShowing=$isShowing)"
+ }
}
/** We are transitioning from [fromOverlay] to [toOverlay]. */
@@ -164,7 +175,7 @@ sealed interface TransitionState {
* [fromOverlay] by [toOverlay] and will [toOverlay] once the swipe transition is
* committed.
*/
- protected abstract val effectivelyShownOverlay: OverlayKey
+ abstract val effectivelyShownOverlay: OverlayKey
init {
check(fromOverlay != toOverlay)
@@ -193,6 +204,10 @@ sealed interface TransitionState {
add(include)
}
}
+
+ override fun toString(): String {
+ return "ReplaceOverlay(fromOverlay=$fromOverlay, toOverlay=$toOverlay)"
+ }
}
/**
@@ -280,8 +295,24 @@ sealed interface TransitionState {
*/
private var interruptionDecay: Animatable? = null
- /** The map of active links that connects this transition to other transitions. */
- internal val activeTransitionLinks = mutableMapOf()
+ /**
+ * The coroutine scope associated to this transition.
+ *
+ * This coroutine scope can be used to launch animations associated to this transition,
+ * which will not finish until at least one animation/job is still running in the scope.
+ *
+ * Important: Make sure to never launch long-running jobs in this scope, otherwise the
+ * transition will never be considered as finished.
+ */
+ internal val coroutineScope: CoroutineScope
+ get() =
+ _coroutineScope
+ ?: error(
+ "Transition.coroutineScope can only be accessed once the transition was " +
+ "started "
+ )
+
+ private var _coroutineScope: CoroutineScope? = null
init {
check(fromContent != toContent)
@@ -327,8 +358,23 @@ sealed interface TransitionState {
}
}
+ /** Whether [fromContent] is effectively the current content of the transition. */
+ internal fun isFromCurrentContent() = isCurrentContent(expectedFrom = true)
+
+ /** Whether [toContent] is effectively the current content of the transition. */
+ internal fun isToCurrentContent() = isCurrentContent(expectedFrom = false)
+
+ private fun isCurrentContent(expectedFrom: Boolean): Boolean {
+ val expectedContent = if (expectedFrom) fromContent else toContent
+ return when (this) {
+ is ChangeScene -> currentScene == expectedContent
+ is ReplaceOverlay -> effectivelyShownOverlay == expectedContent
+ is ShowOrHideOverlay -> isEffectivelyShown == (expectedContent == overlay)
+ }
+ }
+
/** Run this transition and return once it is finished. */
- abstract suspend fun run()
+ protected abstract suspend fun run()
/**
* Freeze this transition state so that neither [currentScene] nor [currentOverlays] will
@@ -341,6 +387,14 @@ sealed interface TransitionState {
*/
abstract fun freezeAndAnimateToCurrentState()
+ internal suspend fun runInternal() {
+ check(_coroutineScope == null) { "A Transition can be started only once." }
+ coroutineScope {
+ _coroutineScope = this
+ run()
+ }
+ }
+
internal fun updateOverscrollSpecs(
fromSpec: OverscrollSpecImpl?,
toSpec: OverscrollSpecImpl?,
@@ -361,7 +415,7 @@ sealed interface TransitionState {
else -> null
} ?: return true
- return specForCurrentScene.transformationSpec.transformations.isNotEmpty()
+ return specForCurrentScene.transformationSpec.transformationMatchers.isNotEmpty()
}
internal open fun interruptionProgress(layoutImpl: SceneTransitionLayoutImpl): Float {
@@ -376,7 +430,7 @@ sealed interface TransitionState {
val progressSpec =
spring(
stiffness = swipeSpec.stiffness,
- dampingRatio = swipeSpec.dampingRatio,
+ dampingRatio = Spring.DampingRatioNoBouncy,
visibilityThreshold = ProgressVisibilityThreshold,
)
animatable.animateTo(0f, progressSpec)
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/reveal/ContainerReveal.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/reveal/ContainerReveal.kt
new file mode 100644
index 0000000000000000000000000000000000000000..bfb5ca733d90794fdfeb8b7256b1dd2877ee11b2
--- /dev/null
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/reveal/ContainerReveal.kt
@@ -0,0 +1,289 @@
+/*
+ * 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.compose.animation.scene.reveal
+
+import androidx.compose.animation.core.AnimationVector1D
+import androidx.compose.animation.core.DeferredTargetAnimation
+import androidx.compose.animation.core.ExperimentalAnimatableApi
+import androidx.compose.animation.core.FiniteAnimationSpec
+import androidx.compose.animation.core.Spring
+import androidx.compose.animation.core.VectorConverter
+import androidx.compose.animation.core.spring
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.IntSize
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.util.fastCoerceAtLeast
+import androidx.compose.ui.util.fastCoerceAtMost
+import com.android.compose.animation.scene.ContentKey
+import com.android.compose.animation.scene.ElementKey
+import com.android.compose.animation.scene.OverlayKey
+import com.android.compose.animation.scene.SceneKey
+import com.android.compose.animation.scene.TransitionBuilder
+import com.android.compose.animation.scene.UserActionDistance
+import com.android.compose.animation.scene.content.state.TransitionState
+import com.android.compose.animation.scene.transformation.CustomPropertyTransformation
+import com.android.compose.animation.scene.transformation.PropertyTransformation
+import com.android.compose.animation.scene.transformation.PropertyTransformationScope
+import kotlin.math.roundToInt
+import kotlinx.coroutines.CoroutineScope
+
+interface ContainerRevealHaptics {
+ /**
+ * Called when the reveal threshold is crossed while the user was dragging on screen.
+ *
+ * Important: This callback is called during layout and its implementation should therefore be
+ * very fast or posted to a different thread.
+ *
+ * @param revealed whether we go from hidden to revealed, i.e. whether the container size is
+ * going to jump from a smaller size to a bigger size.
+ */
+ fun onRevealThresholdCrossed(revealed: Boolean)
+}
+
+/** Animate the reveal of [container] by animating its size. */
+fun TransitionBuilder.verticalContainerReveal(
+ container: ElementKey,
+ haptics: ContainerRevealHaptics,
+) {
+ // Make the swipe distance be exactly the target height of the container.
+ // TODO(b/376438969): Make sure that this works correctly when the target size of the element
+ // is changing during the transition (e.g. a notification was added). At the moment, the user
+ // action distance is only called until it returns a value > 0f, which is then cached.
+ distance = UserActionDistance { fromContent, toContent, _ ->
+ val targetSizeInFromContent = container.targetSize(fromContent)
+ val targetSizeInToContent = container.targetSize(toContent)
+ if (targetSizeInFromContent != null && targetSizeInToContent != null) {
+ error(
+ "verticalContainerReveal should not be used with shared elements, but " +
+ "${container.debugName} is in both ${fromContent.debugName} and " +
+ toContent.debugName
+ )
+ }
+
+ (targetSizeInToContent?.height ?: targetSizeInFromContent?.height)?.toFloat() ?: 0f
+ }
+
+ // TODO(b/376438969): Improve the motion of this gesture using Motion Mechanics.
+
+ // The min distance to swipe before triggering the reveal spring.
+ val distanceThreshold = 80.dp
+
+ // The minimum height of the container.
+ val minHeight = 10.dp
+
+ // The amount removed from the container width at 0% progress.
+ val widthDelta = 140.dp
+
+ // The ratio at which the distance is tracked before reaching the threshold, e.g. if the user
+ // drags 60dp then the height will be 60dp * 0.25f = 15dp.
+ val trackingRatio = 0.25f
+
+ // The max progress starting from which the container should always be visible, even if we are
+ // animating the container out. This is used so that we don't immediately fade out the container
+ // when triggering a one-off animation that hides it.
+ val alphaProgressThreshold = 0.05f
+
+ // The spring animating the size of the container.
+ val sizeSpec = spring(stiffness = 380f, dampingRatio = 0.9f)
+
+ // The spring animating the alpha of the container.
+ val alphaSpec = spring(stiffness = 1200f, dampingRatio = 0.99f)
+
+ // The spring animating the progress when releasing the finger.
+ swipeSpec =
+ spring(
+ stiffness = Spring.StiffnessMediumLow,
+ dampingRatio = Spring.DampingRatioNoBouncy,
+ visibilityThreshold = 0.5f,
+ )
+
+ // Size transformation.
+ transformation(container) {
+ VerticalContainerRevealSizeTransformation(
+ haptics,
+ distanceThreshold,
+ trackingRatio,
+ minHeight,
+ widthDelta,
+ sizeSpec,
+ )
+ }
+
+ // Alpha transformation.
+ transformation(container) {
+ ContainerRevealAlphaTransformation(alphaSpec, alphaProgressThreshold)
+ }
+}
+
+@OptIn(ExperimentalAnimatableApi::class)
+private class VerticalContainerRevealSizeTransformation(
+ private val haptics: ContainerRevealHaptics,
+ private val distanceThreshold: Dp,
+ private val trackingRatio: Float,
+ private val minHeight: Dp,
+ private val widthDelta: Dp,
+ private val spec: FiniteAnimationSpec,
+) : CustomPropertyTransformation {
+ override val property = PropertyTransformation.Property.Size
+
+ private val widthAnimation = DeferredTargetAnimation(Float.VectorConverter)
+ private val heightAnimation = DeferredTargetAnimation(Float.VectorConverter)
+
+ private var previousHasReachedThreshold: Boolean? = null
+
+ override fun PropertyTransformationScope.transform(
+ content: ContentKey,
+ element: ElementKey,
+ transition: TransitionState.Transition,
+ transitionScope: CoroutineScope,
+ ): IntSize {
+ // The distance to go to 100%. Note that we don't use
+ // TransitionState.HasOverscrollProperties.absoluteDistance because the transition will not
+ // implement HasOverscrollProperties if the transition is triggered and not gesture based.
+ val idleSize = checkNotNull(element.targetSize(content))
+ val userActionDistance = idleSize.height
+ val progress =
+ when ((transition as? TransitionState.HasOverscrollProperties)?.bouncingContent) {
+ null -> transition.progressTo(content)
+ content -> 1f
+ else -> 0f
+ }
+ val distance = (progress * userActionDistance).fastCoerceAtLeast(0f)
+ val threshold = distanceThreshold.toPx()
+
+ // Width.
+ val widthDelta = widthDelta.toPx()
+ val width =
+ (idleSize.width - widthDelta +
+ animateSize(
+ size = widthDelta,
+ distance = distance,
+ threshold = threshold,
+ transitionScope = transitionScope,
+ animation = widthAnimation,
+ ))
+ .roundToInt()
+
+ // Height.
+ val minHeight = minHeight.toPx()
+ val height =
+ (
+ // 1) The minimum size of the container.
+ minHeight +
+
+ // 2) The animated size between the minimum size and the threshold.
+ animateSize(
+ size = threshold - minHeight,
+ distance = distance,
+ threshold = threshold,
+ transitionScope = transitionScope,
+ animation = heightAnimation,
+ ) +
+
+ // 3) The remaining height after the threshold, tracking the finger.
+ (distance - threshold).fastCoerceAtLeast(0f))
+ .roundToInt()
+ .fastCoerceAtMost(idleSize.height)
+
+ // Haptics.
+ val hasReachedThreshold = distance >= threshold
+ if (
+ previousHasReachedThreshold != null &&
+ hasReachedThreshold != previousHasReachedThreshold &&
+ transition.isUserInputOngoing
+ ) {
+ haptics.onRevealThresholdCrossed(revealed = hasReachedThreshold)
+ }
+ previousHasReachedThreshold = hasReachedThreshold
+
+ return IntSize(width = width, height = height)
+ }
+
+ /**
+ * Animate a size up to [size], so that it is equal to 0f when distance is 0f and equal to
+ * [size] when `distance >= threshold`, taking the [trackingRatio] into account.
+ */
+ @OptIn(ExperimentalAnimatableApi::class)
+ private fun animateSize(
+ size: Float,
+ distance: Float,
+ threshold: Float,
+ transitionScope: CoroutineScope,
+ animation: DeferredTargetAnimation,
+ ): Float {
+ val trackingSize = distance.fastCoerceAtMost(threshold) / threshold * size * trackingRatio
+ val springTarget =
+ if (distance >= threshold) {
+ size * (1f - trackingRatio)
+ } else {
+ 0f
+ }
+ val springSize = animation.updateTarget(springTarget, transitionScope, spec)
+ return trackingSize + springSize
+ }
+}
+
+@OptIn(ExperimentalAnimatableApi::class)
+private class ContainerRevealAlphaTransformation(
+ private val spec: FiniteAnimationSpec,
+ private val progressThreshold: Float,
+) : CustomPropertyTransformation {
+ override val property = PropertyTransformation.Property.Alpha
+ private val alphaAnimation = DeferredTargetAnimation(Float.VectorConverter)
+
+ override fun PropertyTransformationScope.transform(
+ content: ContentKey,
+ element: ElementKey,
+ transition: TransitionState.Transition,
+ transitionScope: CoroutineScope,
+ ): Float {
+ return alphaAnimation.updateTarget(targetAlpha(transition, content), transitionScope, spec)
+ }
+
+ private fun targetAlpha(transition: TransitionState.Transition, content: ContentKey): Float {
+ if (transition.isUserInputOngoing) {
+ if (transition !is TransitionState.HasOverscrollProperties) {
+ error(
+ "Unsupported transition driven by user input but that does not have " +
+ "overscroll properties: $transition"
+ )
+ }
+
+ val bouncingContent = transition.bouncingContent
+ return if (bouncingContent != null) {
+ if (bouncingContent == content) 1f else 0f
+ } else {
+ if (transition.progressTo(content) > 0f) 1f else 0f
+ }
+ }
+
+ // The transition was committed (the user released their finger), so the alpha depends on
+ // whether we are animating towards the content (showing the container) or away from it
+ // (hiding the container).
+ val isShowingContainer =
+ when (content) {
+ is SceneKey -> transition.currentScene == content
+ is OverlayKey -> transition.currentOverlays.contains(content)
+ }
+
+ return if (isShowingContainer || transition.progressTo(content) >= progressThreshold) {
+ 1f
+ } else {
+ 0f
+ }
+ }
+}
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/AnchoredSize.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/AnchoredSize.kt
index 0ddeb7c7445f8c83598f7d89cfe5dc2e29d339f3..6575068201d885e63874d69bccfa0976371d1c4b 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/AnchoredSize.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/AnchoredSize.kt
@@ -19,16 +19,17 @@ package com.android.compose.animation.scene.transformation
import androidx.compose.ui.unit.IntSize
import com.android.compose.animation.scene.ContentKey
import com.android.compose.animation.scene.ElementKey
-import com.android.compose.animation.scene.ElementMatcher
import com.android.compose.animation.scene.content.state.TransitionState
/** Anchor the size of an element to the size of another element. */
-internal class AnchoredSize(
- override val matcher: ElementMatcher,
+internal class AnchoredSize
+private constructor(
private val anchor: ElementKey,
private val anchorWidth: Boolean,
private val anchorHeight: Boolean,
-) : PropertyTransformation {
+) : InterpolatedPropertyTransformation {
+ override val property = PropertyTransformation.Property.Size
+
override fun PropertyTransformationScope.transform(
content: ContentKey,
element: ElementKey,
@@ -59,4 +60,12 @@ internal class AnchoredSize(
anchorSizeIn(transition.fromContent)
}
}
+
+ class Factory(
+ private val anchor: ElementKey,
+ private val anchorWidth: Boolean,
+ private val anchorHeight: Boolean,
+ ) : Transformation.Factory {
+ override fun create(): Transformation = AnchoredSize(anchor, anchorWidth, anchorHeight)
+ }
}
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/AnchoredTranslate.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/AnchoredTranslate.kt
index 47508b41633c06b02d464d3bb600f1314fbc96a2..890902b7ab67735719ae0dd2fc59ef8636b3984e 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/AnchoredTranslate.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/AnchoredTranslate.kt
@@ -19,14 +19,13 @@ package com.android.compose.animation.scene.transformation
import androidx.compose.ui.geometry.Offset
import com.android.compose.animation.scene.ContentKey
import com.android.compose.animation.scene.ElementKey
-import com.android.compose.animation.scene.ElementMatcher
import com.android.compose.animation.scene.content.state.TransitionState
/** Anchor the translation of an element to another element. */
-internal class AnchoredTranslate(
- override val matcher: ElementMatcher,
- private val anchor: ElementKey,
-) : PropertyTransformation {
+internal class AnchoredTranslate private constructor(private val anchor: ElementKey) :
+ InterpolatedPropertyTransformation {
+ override val property = PropertyTransformation.Property.Offset
+
override fun PropertyTransformationScope.transform(
content: ContentKey,
element: ElementKey,
@@ -56,6 +55,10 @@ internal class AnchoredTranslate(
Offset(idleValue.x + offset.x, idleValue.y + offset.y)
}
}
+
+ class Factory(private val anchor: ElementKey) : Transformation.Factory {
+ override fun create(): Transformation = AnchoredTranslate(anchor)
+ }
}
internal fun throwMissingAnchorException(
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/DrawScale.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/DrawScale.kt
index 8488ae5178b04fcae05fd6a5855d96663b0e4e0d..347f1c325058067d06fde15066c3efa3bcdc24e2 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/DrawScale.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/DrawScale.kt
@@ -19,7 +19,6 @@ package com.android.compose.animation.scene.transformation
import androidx.compose.ui.geometry.Offset
import com.android.compose.animation.scene.ContentKey
import com.android.compose.animation.scene.ElementKey
-import com.android.compose.animation.scene.ElementMatcher
import com.android.compose.animation.scene.Scale
import com.android.compose.animation.scene.content.state.TransitionState
@@ -27,12 +26,14 @@ import com.android.compose.animation.scene.content.state.TransitionState
* Scales the draw size of an element. Note this will only scale the draw inside of an element,
* therefore it won't impact layout of elements around it.
*/
-internal class DrawScale(
- override val matcher: ElementMatcher,
+internal class DrawScale
+private constructor(
private val scaleX: Float,
private val scaleY: Float,
- private val pivot: Offset = Offset.Unspecified,
-) : PropertyTransformation {
+ private val pivot: Offset,
+) : InterpolatedPropertyTransformation {
+ override val property = PropertyTransformation.Property.Scale
+
override fun PropertyTransformationScope.transform(
content: ContentKey,
element: ElementKey,
@@ -41,4 +42,9 @@ internal class DrawScale(
): Scale {
return Scale(scaleX, scaleY, pivot)
}
+
+ class Factory(private val scaleX: Float, private val scaleY: Float, private val pivot: Offset) :
+ Transformation.Factory {
+ override fun create(): Transformation = DrawScale(scaleX, scaleY, pivot)
+ }
}
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/EdgeTranslate.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/EdgeTranslate.kt
index 884aae4b8b1aae6e462abcc777b24dd7d713a867..f8e6dc09ce75c9ec33473e936e003ff15301f793 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/EdgeTranslate.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/EdgeTranslate.kt
@@ -20,15 +20,14 @@ import androidx.compose.ui.geometry.Offset
import com.android.compose.animation.scene.ContentKey
import com.android.compose.animation.scene.Edge
import com.android.compose.animation.scene.ElementKey
-import com.android.compose.animation.scene.ElementMatcher
import com.android.compose.animation.scene.content.state.TransitionState
/** Translate an element from an edge of the layout. */
-internal class EdgeTranslate(
- override val matcher: ElementMatcher,
- private val edge: Edge,
- private val startsOutsideLayoutBounds: Boolean = true,
-) : PropertyTransformation {
+internal class EdgeTranslate
+private constructor(private val edge: Edge, private val startsOutsideLayoutBounds: Boolean) :
+ InterpolatedPropertyTransformation {
+ override val property = PropertyTransformation.Property.Offset
+
override fun PropertyTransformationScope.transform(
content: ContentKey,
element: ElementKey,
@@ -67,4 +66,9 @@ internal class EdgeTranslate(
}
}
}
+
+ class Factory(private val edge: Edge, private val startsOutsideLayoutBounds: Boolean) :
+ Transformation.Factory {
+ override fun create(): Transformation = EdgeTranslate(edge, startsOutsideLayoutBounds)
+ }
}
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/Fade.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/Fade.kt
index ef769e7d0c19b34dff864032f0f577554a01d2d5..d92419ef368df45ee660aefcbc9ffa9467b87af4 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/Fade.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/Fade.kt
@@ -18,11 +18,12 @@ package com.android.compose.animation.scene.transformation
import com.android.compose.animation.scene.ContentKey
import com.android.compose.animation.scene.ElementKey
-import com.android.compose.animation.scene.ElementMatcher
import com.android.compose.animation.scene.content.state.TransitionState
/** Fade an element in or out. */
-internal class Fade(override val matcher: ElementMatcher) : PropertyTransformation {
+internal object Fade : InterpolatedPropertyTransformation {
+ override val property = PropertyTransformation.Property.Alpha
+
override fun PropertyTransformationScope.transform(
content: ContentKey,
element: ElementKey,
@@ -33,4 +34,8 @@ internal class Fade(override val matcher: ElementMatcher) : PropertyTransformati
// fading out, which is `0` in both cases.
return 0f
}
+
+ object Factory : Transformation.Factory {
+ override fun create(): Transformation = Fade
+ }
}
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/ScaleSize.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/ScaleSize.kt
index ef3654b65b0a5838ca109188b6a927b93ab15fcc..5d31fd9ca1961327673821bccfb31f9156a514e0 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/ScaleSize.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/ScaleSize.kt
@@ -19,7 +19,6 @@ package com.android.compose.animation.scene.transformation
import androidx.compose.ui.unit.IntSize
import com.android.compose.animation.scene.ContentKey
import com.android.compose.animation.scene.ElementKey
-import com.android.compose.animation.scene.ElementMatcher
import com.android.compose.animation.scene.content.state.TransitionState
import kotlin.math.roundToInt
@@ -27,11 +26,10 @@ import kotlin.math.roundToInt
* Scales the size of an element. Note that this makes the element resize every frame and will
* therefore impact the layout of other elements.
*/
-internal class ScaleSize(
- override val matcher: ElementMatcher,
- private val width: Float = 1f,
- private val height: Float = 1f,
-) : PropertyTransformation {
+internal class ScaleSize private constructor(private val width: Float, private val height: Float) :
+ InterpolatedPropertyTransformation {
+ override val property = PropertyTransformation.Property.Size
+
override fun PropertyTransformationScope.transform(
content: ContentKey,
element: ElementKey,
@@ -43,4 +41,9 @@ internal class ScaleSize(
height = (idleValue.height * height).roundToInt(),
)
}
+
+ class Factory(private val width: Float = 1f, private val height: Float = 1f) :
+ Transformation.Factory {
+ override fun create(): Transformation = ScaleSize(width, height)
+ }
}
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/Transformation.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/Transformation.kt
index 74a3ead3fbd707df9dea0d39234fa0bd28a12963..e0b42189854a395696660e8a5191e04a2f7a3bc5 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/Transformation.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/Transformation.kt
@@ -18,7 +18,9 @@ package com.android.compose.animation.scene.transformation
import androidx.compose.animation.core.Easing
import androidx.compose.animation.core.LinearEasing
+import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.unit.Density
+import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.util.fastCoerceAtLeast
import androidx.compose.ui.util.fastCoerceAtMost
@@ -27,30 +29,65 @@ import com.android.compose.animation.scene.ContentKey
import com.android.compose.animation.scene.ElementKey
import com.android.compose.animation.scene.ElementMatcher
import com.android.compose.animation.scene.ElementStateScope
+import com.android.compose.animation.scene.Scale
import com.android.compose.animation.scene.content.state.TransitionState
+import kotlinx.coroutines.CoroutineScope
/** A transformation applied to one or more elements during a transition. */
sealed interface Transformation {
- /**
- * The matcher that should match the element(s) to which this transformation should be applied.
- */
- val matcher: ElementMatcher
-
- /*
- * Reverse this transformation. This is called when we use Transition(from = A, to = B) when
- * animating from B to A and there is no Transition(from = B, to = A) defined.
- */
- fun reversed(): Transformation = this
+ fun interface Factory {
+ fun create(): Transformation
+ }
}
-internal class SharedElementTransformation(
- override val matcher: ElementMatcher,
+// Important: SharedElementTransformation must be a data class because we check that we don't
+// provide 2 different transformations for the same element in Element.kt
+internal data class SharedElementTransformation(
internal val enabled: Boolean,
internal val elevateInContent: ContentKey?,
-) : Transformation
+) : Transformation {
+ class Factory(
+ internal val matcher: ElementMatcher,
+ internal val enabled: Boolean,
+ internal val elevateInContent: ContentKey?,
+ ) : Transformation.Factory {
+ override fun create(): Transformation {
+ return SharedElementTransformation(enabled, elevateInContent)
+ }
+ }
+}
+
+/**
+ * A transformation that changes the value of an element [Property], like its [size][Property.Size]
+ * or [offset][Property.Offset].
+ */
+sealed interface PropertyTransformation : Transformation {
+ /** The property to which this transformation is applied. */
+ val property: Property
+
+ sealed class Property {
+ /** The size of an element. */
+ data object Size : Property()
+
+ /** The offset (position) of an element. */
+ data object Offset : Property()
+
+ /** The alpha of an element. */
+ data object Alpha : Property()
+
+ /**
+ * The drawing scale of an element. Animating the scale does not have any effect on the
+ * layout.
+ */
+ data object Scale : Property()
+ }
+}
-/** A transformation that changes the value of an element property, like its size or offset. */
-interface PropertyTransformation : Transformation {
+/**
+ * A transformation to a target/transformed value that is automatically interpolated using the
+ * transition progress and transformation range.
+ */
+interface InterpolatedPropertyTransformation