diff options
481 files changed, 10056 insertions, 3598 deletions
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg index cdf5df6c6bd3..30ed7de92614 100644 --- a/PREUPLOAD.cfg +++ b/PREUPLOAD.cfg @@ -8,6 +8,7 @@ clang_format = --commit ${PREUPLOAD_COMMIT} --style file --extensions c,h,cc,cpp cmds/input/ cmds/uinput/ core/jni/ + libs/hwui/ libs/input/ native/ services/core/jni/ diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java b/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java index e05f0b062dbe..223f3b04d4e6 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java +++ b/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java @@ -665,9 +665,18 @@ class JobConcurrencyManager { WorkTypeConfig(@NonNull String configIdentifier, int defaultMaxTotal, List<Pair<Integer, Integer>> defaultMin, List<Pair<Integer, Integer>> defaultMax) { mConfigIdentifier = configIdentifier; - mDefaultMaxTotal = mMaxTotal = defaultMaxTotal; + mDefaultMaxTotal = mMaxTotal = Math.min(defaultMaxTotal, MAX_JOB_CONTEXTS_COUNT); + int numReserved = 0; for (int i = defaultMin.size() - 1; i >= 0; --i) { mDefaultMinReservedSlots.put(defaultMin.get(i).first, defaultMin.get(i).second); + numReserved += defaultMin.get(i).second; + } + if (mDefaultMaxTotal < 0 || numReserved > mDefaultMaxTotal) { + // We only create new configs on boot, so this should trigger during development + // (before the code gets checked in), so this makes sure the hard-coded defaults + // make sense. DeviceConfig values will be handled gracefully in update(). + throw new IllegalArgumentException("Invalid default config: t=" + defaultMaxTotal + + " min=" + defaultMin + " max=" + defaultMax); } for (int i = defaultMax.size() - 1; i >= 0; --i) { mDefaultMaxAllowedSlots.put(defaultMax.get(i).first, defaultMax.get(i).second); diff --git a/apex/media/aidl/private/android/media/IMediaCommunicationService.aidl b/apex/media/aidl/private/android/media/IMediaCommunicationService.aidl new file mode 100644 index 000000000000..3d50d14e1b83 --- /dev/null +++ b/apex/media/aidl/private/android/media/IMediaCommunicationService.aidl @@ -0,0 +1,21 @@ +/** + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.media; + +/** {@hide} */ +interface IMediaCommunicationService { +} + diff --git a/apex/media/framework/Android.bp b/apex/media/framework/Android.bp index 60dea079a36b..5773e4de3f4e 100644 --- a/apex/media/framework/Android.bp +++ b/apex/media/framework/Android.bp @@ -38,6 +38,7 @@ java_library { static_libs: [ "exoplayer2-extractor", "mediatranscoding_aidl_interface-java", + "modules-utils-build", ], jarjar_rules: "jarjar_rules.txt", @@ -52,6 +53,7 @@ java_library { visibility: [ "//frameworks/av/apex:__subpackages__", "//frameworks/base", // For framework-all + "//frameworks/base/apex/media/service", ], } @@ -80,6 +82,7 @@ filegroup { "java/android/media/Session2CommandGroup.java", "java/android/media/Session2Link.java", "java/android/media/Session2Token.java", + "java/android/media/MediaCommunicationManager.java", ], path: "java", } diff --git a/apex/media/framework/api/current.txt b/apex/media/framework/api/current.txt index 2543a9cad576..8b9990f9e833 100644 --- a/apex/media/framework/api/current.txt +++ b/apex/media/framework/api/current.txt @@ -28,6 +28,9 @@ package android.media { ctor public ApplicationMediaCapabilities.FormatNotFoundException(@NonNull String); } + public class MediaCommunicationManager { + } + public class MediaController2 implements java.lang.AutoCloseable { method public void cancelSessionCommand(@NonNull Object); method public void close(); diff --git a/apex/media/framework/jarjar_rules.txt b/apex/media/framework/jarjar_rules.txt index d89d9d3343d1..eb71fddc05cb 100644 --- a/apex/media/framework/jarjar_rules.txt +++ b/apex/media/framework/jarjar_rules.txt @@ -1 +1,2 @@ +rule com.android.modules.utils.** android.media.internal.utils.@1 rule com.google.android.exoplayer2.** android.media.internal.exo.@1 diff --git a/apex/media/framework/java/android/media/MediaCommunicationManager.java b/apex/media/framework/java/android/media/MediaCommunicationManager.java new file mode 100644 index 000000000000..b8065ef8c597 --- /dev/null +++ b/apex/media/framework/java/android/media/MediaCommunicationManager.java @@ -0,0 +1,49 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.media; + +import android.annotation.NonNull; +import android.annotation.SystemService; +import android.content.Context; + +import com.android.modules.utils.build.SdkLevel; + +/** + * Provides support for interacting with {@link android.media.MediaSession2 MediaSession2s} + * that applications have published to express their ongoing media playback state. + */ +// TODO: Add notifySession2Created() and sendMessage(). +@SystemService(Context.MEDIA_COMMUNICATION_SERVICE) +public class MediaCommunicationManager { + private static final String TAG = "MediaCommunicationManager"; + + private final Context mContext; + private final IMediaCommunicationService mService; + + /** + * @hide + */ + public MediaCommunicationManager(@NonNull Context context) { + if (!SdkLevel.isAtLeastS()) { + throw new UnsupportedOperationException("Android version must be S or greater."); + } + mContext = context; + mService = IMediaCommunicationService.Stub.asInterface( + MediaFrameworkInitializer.getMediaServiceManager() + .getMediaCommunicationServiceRegisterer() + .get()); + } +} diff --git a/apex/media/framework/java/android/media/MediaFrameworkInitializer.java b/apex/media/framework/java/android/media/MediaFrameworkInitializer.java index 813ad7b43932..93328355026e 100644 --- a/apex/media/framework/java/android/media/MediaFrameworkInitializer.java +++ b/apex/media/framework/java/android/media/MediaFrameworkInitializer.java @@ -19,10 +19,11 @@ package android.media; import android.annotation.NonNull; import android.annotation.SystemApi; import android.annotation.SystemApi.Client; -import android.media.MediaTranscodeManager; import android.app.SystemServiceRegistry; import android.content.Context; +import com.android.modules.utils.build.SdkLevel; + /** * Class for performing registration for all media services on com.android.media apex. * @@ -74,5 +75,12 @@ public class MediaFrameworkInitializer { MediaTranscodeManager.class, context -> new MediaTranscodeManager(context) ); + if (SdkLevel.isAtLeastS()) { + SystemServiceRegistry.registerContextAwareService( + Context.MEDIA_COMMUNICATION_SERVICE, + MediaCommunicationManager.class, + context -> new MediaCommunicationManager(context) + ); + } } } diff --git a/apex/media/service/Android.bp b/apex/media/service/Android.bp new file mode 100644 index 000000000000..5b24cfa4219b --- /dev/null +++ b/apex/media/service/Android.bp @@ -0,0 +1,41 @@ +// Copyright 2020 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +filegroup { + name: "service-media-s-sources", + srcs: [ + "java/**/*.java", + ], + path: "java", + visibility: ["//frameworks/base/services"], // TODO(b/177640454): Should be private. +} + +java_sdk_library { + name: "service-media-s", + permitted_packages: [ + "com.android.server.media", + ], + defaults: ["framework-system-server-module-defaults"], + srcs: [ + ":service-media-s-sources", + ], + libs: [ + "updatable-media", + ], + sdk_version: "system_server_current", + min_sdk_version: "29", // TODO: We may need to bump this at some point. + apex_available: [ + "com.android.media", + ], +} + diff --git a/apex/media/service/api/current.txt b/apex/media/service/api/current.txt new file mode 100644 index 000000000000..d802177e249b --- /dev/null +++ b/apex/media/service/api/current.txt @@ -0,0 +1 @@ +// Signature format: 2.0 diff --git a/apex/media/service/api/removed.txt b/apex/media/service/api/removed.txt new file mode 100644 index 000000000000..d802177e249b --- /dev/null +++ b/apex/media/service/api/removed.txt @@ -0,0 +1 @@ +// Signature format: 2.0 diff --git a/apex/media/service/api/system-server-current.txt b/apex/media/service/api/system-server-current.txt new file mode 100644 index 000000000000..d802177e249b --- /dev/null +++ b/apex/media/service/api/system-server-current.txt @@ -0,0 +1 @@ +// Signature format: 2.0 diff --git a/apex/media/service/api/system-server-removed.txt b/apex/media/service/api/system-server-removed.txt new file mode 100644 index 000000000000..d802177e249b --- /dev/null +++ b/apex/media/service/api/system-server-removed.txt @@ -0,0 +1 @@ +// Signature format: 2.0 diff --git a/apex/media/service/java/com/android/server/media/MediaCommunicationService.java b/apex/media/service/java/com/android/server/media/MediaCommunicationService.java new file mode 100644 index 000000000000..0468fdf30ba8 --- /dev/null +++ b/apex/media/service/java/com/android/server/media/MediaCommunicationService.java @@ -0,0 +1,41 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.server.media; + +import android.content.Context; +import android.media.IMediaCommunicationService; + +import com.android.server.SystemService; + +/** + * A system service that managers {@link android.media.MediaSession2} creations + * and their ongoing media playback state. + * @hide + */ +public class MediaCommunicationService extends SystemService { + + public MediaCommunicationService(Context context) { + super(context); + } + + @Override + public void onStart() { + publishBinderService(Context.MEDIA_COMMUNICATION_SERVICE, new Stub()); + } + + private class Stub extends IMediaCommunicationService.Stub { + } +} diff --git a/core/api/current.txt b/core/api/current.txt index b49e7247708c..d1b9716b4cd3 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -8350,6 +8350,7 @@ package android.appwidget { method public android.appwidget.AppWidgetProviderInfo clone(); method public int describeContents(); method public final android.os.UserHandle getProfile(); + method @NonNull public android.content.pm.ActivityInfo getProviderInfo(); method @Nullable public final String loadDescription(@NonNull android.content.Context); method public final android.graphics.drawable.Drawable loadIcon(@NonNull android.content.Context, int); method public final String loadLabel(android.content.pm.PackageManager); @@ -10374,6 +10375,7 @@ package android.content { field public static final String LAUNCHER_APPS_SERVICE = "launcherapps"; field public static final String LAYOUT_INFLATER_SERVICE = "layout_inflater"; field public static final String LOCATION_SERVICE = "location"; + field public static final String MEDIA_COMMUNICATION_SERVICE = "media_communication"; field public static final String MEDIA_METRICS_SERVICE = "media_metrics"; field public static final String MEDIA_PROJECTION_SERVICE = "media_projection"; field public static final String MEDIA_ROUTER_SERVICE = "media_router"; @@ -11867,6 +11869,7 @@ package android.content.pm { } public class LauncherActivityInfo { + method @NonNull public android.content.pm.ActivityInfo getActivityInfo(); method public android.content.pm.ApplicationInfo getApplicationInfo(); method public android.graphics.drawable.Drawable getBadgedIcon(int); method public android.content.ComponentName getComponentName(); @@ -12239,6 +12242,7 @@ package android.content.pm { method @NonNull public abstract android.content.pm.ActivityInfo getReceiverInfo(@NonNull android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException; method @NonNull public abstract android.content.res.Resources getResourcesForActivity(@NonNull android.content.ComponentName) throws android.content.pm.PackageManager.NameNotFoundException; method @NonNull public abstract android.content.res.Resources getResourcesForApplication(@NonNull android.content.pm.ApplicationInfo) throws android.content.pm.PackageManager.NameNotFoundException; + method @NonNull public android.content.res.Resources getResourcesForApplication(@NonNull android.content.pm.ApplicationInfo, @Nullable android.content.res.Configuration) throws android.content.pm.PackageManager.NameNotFoundException; method @NonNull public abstract android.content.res.Resources getResourcesForApplication(@NonNull String) throws android.content.pm.PackageManager.NameNotFoundException; method @NonNull public abstract android.content.pm.ServiceInfo getServiceInfo(@NonNull android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException; method @NonNull public abstract java.util.List<android.content.pm.SharedLibraryInfo> getSharedLibraries(int); @@ -16799,6 +16803,18 @@ package android.graphics.text { package android.hardware { + public abstract class Battery { + ctor public Battery(); + method @FloatRange(from=-1.0F, to=1.0f) public abstract float getCapacity(); + method public abstract int getStatus(); + method public abstract boolean hasBattery(); + field public static final int STATUS_CHARGING = 2; // 0x2 + field public static final int STATUS_DISCHARGING = 3; // 0x3 + field public static final int STATUS_FULL = 5; // 0x5 + field public static final int STATUS_NOT_CHARGING = 4; // 0x4 + field public static final int STATUS_UNKNOWN = 1; // 0x1 + } + @Deprecated public class Camera { method @Deprecated public final void addCallbackBuffer(byte[]); method @Deprecated public final void autoFocus(android.hardware.Camera.AutoFocusCallback); @@ -18499,6 +18515,7 @@ package android.hardware.input { public final class InputManager { method public android.view.InputDevice getInputDevice(int); method public int[] getInputDeviceIds(); + method public float getMaximumObscuringOpacityForTouch(); method public void registerInputDeviceListener(android.hardware.input.InputManager.InputDeviceListener, android.os.Handler); method public void unregisterInputDeviceListener(android.hardware.input.InputManager.InputDeviceListener); method @Nullable public android.view.VerifiedInputEvent verifyInputEvent(@NonNull android.view.InputEvent); @@ -25630,8 +25647,6 @@ package android.net { method public void applyTransportModeTransform(@NonNull java.net.Socket, int, @NonNull android.net.IpSecTransform) throws java.io.IOException; method public void applyTransportModeTransform(@NonNull java.net.DatagramSocket, int, @NonNull android.net.IpSecTransform) throws java.io.IOException; method public void applyTransportModeTransform(@NonNull java.io.FileDescriptor, int, @NonNull android.net.IpSecTransform) throws java.io.IOException; - method @RequiresPermission("android.permission.MANAGE_IPSEC_TUNNELS") public void applyTunnelModeTransform(@NonNull android.net.IpSecManager.IpSecTunnelInterface, int, @NonNull android.net.IpSecTransform) throws java.io.IOException; - method @NonNull @RequiresPermission("android.permission.MANAGE_IPSEC_TUNNELS") public android.net.IpSecManager.IpSecTunnelInterface createIpSecTunnelInterface(@NonNull android.net.Network) throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException; method @NonNull public android.net.IpSecManager.UdpEncapsulationSocket openUdpEncapsulationSocket(int) throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException; method @NonNull public android.net.IpSecManager.UdpEncapsulationSocket openUdpEncapsulationSocket() throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException; method public void removeTransportModeTransforms(@NonNull java.net.Socket) throws java.io.IOException; @@ -25641,12 +25656,6 @@ package android.net { field public static final int DIRECTION_OUT = 1; // 0x1 } - public static final class IpSecManager.IpSecTunnelInterface implements java.lang.AutoCloseable { - method @RequiresPermission("android.permission.MANAGE_IPSEC_TUNNELS") public void addAddress(@NonNull java.net.InetAddress, int) throws java.io.IOException; - method public void close(); - method @RequiresPermission("android.permission.MANAGE_IPSEC_TUNNELS") public void removeAddress(@NonNull java.net.InetAddress, int) throws java.io.IOException; - } - public static final class IpSecManager.ResourceUnavailableException extends android.util.AndroidException { } @@ -46366,6 +46375,7 @@ package android.view { public final class InputDevice implements android.os.Parcelable { method public int describeContents(); + method @NonNull public android.hardware.Battery getBattery(); method public int getControllerNumber(); method public String getDescriptor(); method public static android.view.InputDevice getDevice(int); @@ -46420,6 +46430,7 @@ package android.view { field public static final int SOURCE_MOUSE = 8194; // 0x2002 field public static final int SOURCE_MOUSE_RELATIVE = 131076; // 0x20004 field public static final int SOURCE_ROTARY_ENCODER = 4194304; // 0x400000 + field public static final int SOURCE_SENSOR = 67108864; // 0x4000000 field public static final int SOURCE_STYLUS = 16386; // 0x4002 field public static final int SOURCE_TOUCHPAD = 1048584; // 0x100008 field public static final int SOURCE_TOUCHSCREEN = 4098; // 0x1002 diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt index 2b9f1712bd87..e8650faad1f6 100644 --- a/core/api/module-lib-current.txt +++ b/core/api/module-lib-current.txt @@ -103,6 +103,7 @@ package android.media { } public class MediaServiceManager { + method @NonNull public android.media.MediaServiceManager.ServiceRegisterer getMediaCommunicationServiceRegisterer(); method @NonNull public android.media.MediaServiceManager.ServiceRegisterer getMediaSessionServiceRegisterer(); method @NonNull public android.media.MediaServiceManager.ServiceRegisterer getMediaTranscodingServiceRegisterer(); } @@ -156,6 +157,10 @@ package android.media.session { package android.net { + public final class ConnectivityFrameworkInitializer { + method public static void registerServiceWrappers(); + } + public class ConnectivityManager { method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void requestBackgroundNetwork(@NonNull android.net.NetworkRequest, @Nullable android.os.Handler, @NonNull android.net.ConnectivityManager.NetworkCallback); method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_TEST_NETWORKS, android.Manifest.permission.NETWORK_STACK}) public void simulateDataStall(int, long, @NonNull android.net.Network, @NonNull android.os.PersistableBundle); diff --git a/core/api/system-current.txt b/core/api/system-current.txt index f40bf5d9f759..1d13b73b7020 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -138,6 +138,7 @@ package android { field public static final String MANAGE_ROTATION_RESOLVER = "android.permission.MANAGE_ROTATION_RESOLVER"; field public static final String MANAGE_SEARCH_UI = "android.permission.MANAGE_SEARCH_UI"; field public static final String MANAGE_SENSOR_PRIVACY = "android.permission.MANAGE_SENSOR_PRIVACY"; + field public static final String MANAGE_SMARTSPACE = "android.permission.MANAGE_SMARTSPACE"; field public static final String MANAGE_SOUND_TRIGGER = "android.permission.MANAGE_SOUND_TRIGGER"; field public static final String MANAGE_SUBSCRIPTION_PLANS = "android.permission.MANAGE_SUBSCRIPTION_PLANS"; field public static final String MANAGE_TEST_NETWORKS = "android.permission.MANAGE_TEST_NETWORKS"; @@ -1493,6 +1494,169 @@ package android.app.search { } +package android.app.smartspace { + + public final class SmartspaceAction implements android.os.Parcelable { + method public int describeContents(); + method @Nullable public CharSequence getContentDescription(); + method @Nullable public android.os.Bundle getExtras(); + method @Nullable public android.graphics.drawable.Icon getIcon(); + method @NonNull public String getId(); + method @Nullable public android.content.Intent getIntent(); + method @Nullable public android.app.PendingIntent getPendingIntent(); + method @Nullable public CharSequence getSubtitle(); + method @NonNull public CharSequence getTitle(); + method @Nullable public android.os.UserHandle getUserHandle(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.app.smartspace.SmartspaceAction> CREATOR; + } + + public static final class SmartspaceAction.Builder { + ctor public SmartspaceAction.Builder(@NonNull String, @NonNull String); + method @NonNull public android.app.smartspace.SmartspaceAction build(); + method @NonNull public android.app.smartspace.SmartspaceAction.Builder setContentDescription(@Nullable CharSequence); + method @NonNull public android.app.smartspace.SmartspaceAction.Builder setExtras(@Nullable android.os.Bundle); + method @NonNull public android.app.smartspace.SmartspaceAction.Builder setIcon(@Nullable android.graphics.drawable.Icon); + method @NonNull public android.app.smartspace.SmartspaceAction.Builder setIntent(@Nullable android.content.Intent); + method @NonNull public android.app.smartspace.SmartspaceAction.Builder setPendingIntent(@Nullable android.app.PendingIntent); + method @NonNull public android.app.smartspace.SmartspaceAction.Builder setSubtitle(@Nullable CharSequence); + method @NonNull public android.app.smartspace.SmartspaceAction.Builder setUserHandle(@Nullable android.os.UserHandle); + } + + public final class SmartspaceConfig implements android.os.Parcelable { + method public int describeContents(); + method @Nullable public android.os.Bundle getExtras(); + method @NonNull public String getPackageName(); + method @NonNull public int getSmartspaceTargetCount(); + method @NonNull public String getUiSurface(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.app.smartspace.SmartspaceConfig> CREATOR; + } + + public static final class SmartspaceConfig.Builder { + ctor public SmartspaceConfig.Builder(@NonNull android.content.Context, @NonNull String); + method @NonNull public android.app.smartspace.SmartspaceConfig build(); + method @NonNull public android.app.smartspace.SmartspaceConfig.Builder setExtras(@NonNull android.os.Bundle); + method @NonNull public android.app.smartspace.SmartspaceConfig.Builder setSmartspaceTargetCount(int); + } + + public final class SmartspaceManager { + method @NonNull public android.app.smartspace.SmartspaceSession createSmartspaceSession(@NonNull android.app.smartspace.SmartspaceConfig); + } + + public final class SmartspaceSession implements java.lang.AutoCloseable { + method public void close(); + method public void destroy(); + method protected void finalize(); + method public void notifySmartspaceEvent(@NonNull android.app.smartspace.SmartspaceTargetEvent); + method public void registerSmartspaceUpdates(@NonNull java.util.concurrent.Executor, @NonNull android.app.smartspace.SmartspaceSession.Callback); + method public void requestSmartspaceUpdate(); + method public void unregisterSmartspaceUpdates(@NonNull android.app.smartspace.SmartspaceSession.Callback); + } + + public static interface SmartspaceSession.Callback { + method public void onTargetsAvailable(@NonNull java.util.List<android.app.smartspace.SmartspaceTarget>); + } + + public final class SmartspaceSessionId implements android.os.Parcelable { + method public int describeContents(); + method @Nullable public String getId(); + method @NonNull public int getUserId(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.app.smartspace.SmartspaceSessionId> CREATOR; + } + + public final class SmartspaceTarget implements android.os.Parcelable { + method public int describeContents(); + method @NonNull public java.util.List<android.app.smartspace.SmartspaceAction> getActionChips(); + method @Nullable public String getAssociatedSmartspaceTargetId(); + method @Nullable public android.app.smartspace.SmartspaceAction getBaseAction(); + method @NonNull public android.content.ComponentName getComponentName(); + method @NonNull public long getCreationTimeMillis(); + method @NonNull public long getExpiryTimeMillis(); + method @NonNull public int getFeatureType(); + method @Nullable public android.app.smartspace.SmartspaceAction getHeaderAction(); + method @NonNull public java.util.List<android.app.smartspace.SmartspaceAction> getIconGrid(); + method @NonNull public float getScore(); + method @Nullable public android.net.Uri getSliceUri(); + method @NonNull public String getSmartspaceTargetId(); + method @Nullable public String getSourceNotificationKey(); + method @NonNull public android.os.UserHandle getUserHandle(); + method @Nullable public android.appwidget.AppWidgetProviderInfo getWidgetId(); + method @NonNull public boolean isSensitive(); + method @NonNull public boolean shouldShowExpanded(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.app.smartspace.SmartspaceTarget> CREATOR; + field public static final int FEATURE_ALARM = 7; // 0x7 + field public static final int FEATURE_BEDTIME_ROUTINE = 16; // 0x10 + field public static final int FEATURE_CALENDAR = 2; // 0x2 + field public static final int FEATURE_COMMUTE_TIME = 3; // 0x3 + field public static final int FEATURE_CONSENT = 11; // 0xb + field public static final int FEATURE_ETA_MONITORING = 18; // 0x12 + field public static final int FEATURE_FITNESS_TRACKING = 17; // 0x11 + field public static final int FEATURE_FLIGHT = 4; // 0x4 + field public static final int FEATURE_LOYALTY_CARD = 14; // 0xe + field public static final int FEATURE_MEDIA = 15; // 0xf + field public static final int FEATURE_MISSED_CALL = 19; // 0x13 + field public static final int FEATURE_ONBOARDING = 8; // 0x8 + field public static final int FEATURE_PACKAGE_TRACKING = 20; // 0x14 + field public static final int FEATURE_REMINDER = 6; // 0x6 + field public static final int FEATURE_SHOPPING_LIST = 13; // 0xd + field public static final int FEATURE_SPORTS = 9; // 0x9 + field public static final int FEATURE_STOCK_PRICE_CHANGE = 12; // 0xc + field public static final int FEATURE_STOPWATCH = 22; // 0x16 + field public static final int FEATURE_TIMER = 21; // 0x15 + field public static final int FEATURE_TIPS = 5; // 0x5 + field public static final int FEATURE_UNDEFINED = 0; // 0x0 + field public static final int FEATURE_UPCOMING_ALARM = 23; // 0x17 + field public static final int FEATURE_WEATHER = 1; // 0x1 + field public static final int FEATURE_WEATHER_ALERT = 10; // 0xa + } + + public static final class SmartspaceTarget.Builder { + ctor public SmartspaceTarget.Builder(@NonNull String, @NonNull android.content.ComponentName, @NonNull android.os.UserHandle); + method @NonNull public android.app.smartspace.SmartspaceTarget build(); + method @NonNull public android.app.smartspace.SmartspaceTarget.Builder setActionChips(@NonNull java.util.List<android.app.smartspace.SmartspaceAction>); + method @NonNull public android.app.smartspace.SmartspaceTarget.Builder setAssociatedSmartspaceTargetId(@NonNull String); + method @NonNull public android.app.smartspace.SmartspaceTarget.Builder setBaseAction(@NonNull android.app.smartspace.SmartspaceAction); + method @NonNull public android.app.smartspace.SmartspaceTarget.Builder setCreationTimeMillis(@NonNull long); + method @NonNull public android.app.smartspace.SmartspaceTarget.Builder setExpiryTimeMillis(@NonNull long); + method @NonNull public android.app.smartspace.SmartspaceTarget.Builder setFeatureType(@NonNull int); + method @NonNull public android.app.smartspace.SmartspaceTarget.Builder setHeaderAction(@NonNull android.app.smartspace.SmartspaceAction); + method @NonNull public android.app.smartspace.SmartspaceTarget.Builder setIconGrid(@NonNull java.util.List<android.app.smartspace.SmartspaceAction>); + method @NonNull public android.app.smartspace.SmartspaceTarget.Builder setScore(@NonNull float); + method @NonNull public android.app.smartspace.SmartspaceTarget.Builder setSensitive(@NonNull boolean); + method @NonNull public android.app.smartspace.SmartspaceTarget.Builder setShouldShowExpanded(@NonNull boolean); + method @NonNull public android.app.smartspace.SmartspaceTarget.Builder setSliceUri(@NonNull android.net.Uri); + method @NonNull public android.app.smartspace.SmartspaceTarget.Builder setSourceNotificationKey(@NonNull String); + method @NonNull public android.app.smartspace.SmartspaceTarget.Builder setWidgetId(@NonNull android.appwidget.AppWidgetProviderInfo); + } + + public final class SmartspaceTargetEvent implements android.os.Parcelable { + method public int describeContents(); + method @NonNull public int getEventType(); + method @Nullable public String getSmartspaceActionId(); + method @Nullable public android.app.smartspace.SmartspaceTarget getSmartspaceTarget(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.app.smartspace.SmartspaceTargetEvent> CREATOR; + field public static final int EVENT_TARGET_BLOCK = 5; // 0x5 + field public static final int EVENT_TARGET_DISMISS = 4; // 0x4 + field public static final int EVENT_TARGET_INTERACTION = 1; // 0x1 + field public static final int EVENT_TARGET_IN_VIEW = 2; // 0x2 + field public static final int EVENT_TARGET_OUT_OF_VIEW = 3; // 0x3 + field public static final int EVENT_UI_SURFACE_IN_VIEW = 6; // 0x6 + field public static final int EVENT_UI_SURFACE_OUT_OF_VIEW = 7; // 0x7 + } + + public static final class SmartspaceTargetEvent.Builder { + ctor public SmartspaceTargetEvent.Builder(int); + method @NonNull public android.app.smartspace.SmartspaceTargetEvent build(); + method @NonNull public android.app.smartspace.SmartspaceTargetEvent.Builder setSmartspaceActionId(@NonNull String); + method @NonNull public android.app.smartspace.SmartspaceTargetEvent.Builder setSmartspaceTarget(@NonNull android.app.smartspace.SmartspaceTarget); + } + +} + package android.app.time { public final class TimeManager { @@ -1955,6 +2119,7 @@ package android.content { field public static final String ROLLBACK_SERVICE = "rollback"; field public static final String SEARCH_UI_SERVICE = "search_ui"; field public static final String SECURE_ELEMENT_SERVICE = "secure_element"; + field public static final String SMARTSPACE_SERVICE = "smartspace"; field public static final String STATS_MANAGER = "stats"; field public static final String STATUS_BAR_SERVICE = "statusbar"; field public static final String SYSTEM_CONFIG_SERVICE = "system_config"; @@ -3183,6 +3348,7 @@ package android.hardware.location { public class ContextHubClientCallback { ctor public ContextHubClientCallback(); + method public void onClientAuthorizationChanged(@NonNull android.hardware.location.ContextHubClient, long, int); method public void onHubReset(android.hardware.location.ContextHubClient); method public void onMessageFromNanoApp(android.hardware.location.ContextHubClient, android.hardware.location.NanoAppMessage); method public void onNanoAppAborted(android.hardware.location.ContextHubClient, long, int); @@ -3219,6 +3385,7 @@ package android.hardware.location { public class ContextHubIntentEvent { method @NonNull public static android.hardware.location.ContextHubIntentEvent fromIntent(@NonNull android.content.Intent); + method public int getClientAuthorizationState(); method @NonNull public android.hardware.location.ContextHubInfo getContextHubInfo(); method public int getEventType(); method public int getNanoAppAbortCode(); @@ -3227,8 +3394,10 @@ package android.hardware.location { } public final class ContextHubManager { + method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.ACCESS_CONTEXT_HUB}) public android.hardware.location.ContextHubClient createClient(@Nullable android.content.Context, @NonNull android.hardware.location.ContextHubInfo, @NonNull java.util.concurrent.Executor, @NonNull android.hardware.location.ContextHubClientCallback); method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.ACCESS_CONTEXT_HUB}) public android.hardware.location.ContextHubClient createClient(@NonNull android.hardware.location.ContextHubInfo, @NonNull android.hardware.location.ContextHubClientCallback, @NonNull java.util.concurrent.Executor); method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.ACCESS_CONTEXT_HUB}) public android.hardware.location.ContextHubClient createClient(@NonNull android.hardware.location.ContextHubInfo, @NonNull android.hardware.location.ContextHubClientCallback); + method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.ACCESS_CONTEXT_HUB}) public android.hardware.location.ContextHubClient createClient(@Nullable android.content.Context, @NonNull android.hardware.location.ContextHubInfo, @NonNull android.app.PendingIntent, long); method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.ACCESS_CONTEXT_HUB}) public android.hardware.location.ContextHubClient createClient(@NonNull android.hardware.location.ContextHubInfo, @NonNull android.app.PendingIntent, long); method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.ACCESS_CONTEXT_HUB}) public android.hardware.location.ContextHubTransaction<java.lang.Void> disableNanoApp(@NonNull android.hardware.location.ContextHubInfo, long); method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.ACCESS_CONTEXT_HUB}) public android.hardware.location.ContextHubTransaction<java.lang.Void> enableNanoApp(@NonNull android.hardware.location.ContextHubInfo, long); @@ -3246,6 +3415,10 @@ package android.hardware.location { method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.ACCESS_CONTEXT_HUB}) public int unloadNanoApp(int); method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.ACCESS_CONTEXT_HUB}) public android.hardware.location.ContextHubTransaction<java.lang.Void> unloadNanoApp(@NonNull android.hardware.location.ContextHubInfo, long); method @Deprecated public int unregisterCallback(@NonNull android.hardware.location.ContextHubManager.Callback); + field public static final int AUTHORIZATION_DENIED = 0; // 0x0 + field public static final int AUTHORIZATION_DENIED_GRACE_PERIOD = 1; // 0x1 + field public static final int AUTHORIZATION_GRANTED = 2; // 0x2 + field public static final int EVENT_CLIENT_AUTHORIZATION = 7; // 0x7 field public static final int EVENT_HUB_RESET = 6; // 0x6 field public static final int EVENT_NANOAPP_ABORTED = 4; // 0x4 field public static final int EVENT_NANOAPP_DISABLED = 3; // 0x3 @@ -3253,6 +3426,7 @@ package android.hardware.location { field public static final int EVENT_NANOAPP_LOADED = 0; // 0x0 field public static final int EVENT_NANOAPP_MESSAGE = 5; // 0x5 field public static final int EVENT_NANOAPP_UNLOADED = 1; // 0x1 + field public static final String EXTRA_CLIENT_AUTHORIZATION_STATE = "android.hardware.location.extra.CLIENT_AUTHORIZATION_STATE"; field public static final String EXTRA_CONTEXT_HUB_INFO = "android.hardware.location.extra.CONTEXT_HUB_INFO"; field public static final String EXTRA_EVENT_TYPE = "android.hardware.location.extra.EVENT_TYPE"; field public static final String EXTRA_MESSAGE = "android.hardware.location.extra.MESSAGE"; @@ -3491,8 +3665,10 @@ package android.hardware.location { public final class NanoAppState implements android.os.Parcelable { ctor public NanoAppState(long, int, boolean); + ctor public NanoAppState(long, int, boolean, @NonNull java.util.List<java.lang.String>); method public int describeContents(); method public long getNanoAppId(); + method @NonNull public java.util.List<java.lang.String> getNanoAppPermissions(); method public long getNanoAppVersion(); method public boolean isEnabled(); method public void writeToParcel(android.os.Parcel, int); @@ -5817,6 +5993,7 @@ package android.media.tv.tuner.filter { public final class RestartEvent extends android.media.tv.tuner.filter.FilterEvent { method public int getStartId(); + field public static final int NEW_FILTER_FIRST_START_ID = 0; // 0x0 } public final class ScramblingStatusEvent extends android.media.tv.tuner.filter.FilterEvent { @@ -6951,11 +7128,15 @@ package android.net { } public final class IpSecManager { - method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public android.net.IpSecManager.IpSecTunnelInterface createIpSecTunnelInterface(@NonNull java.net.InetAddress, @NonNull java.net.InetAddress, @NonNull android.net.Network) throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException; + method @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public void applyTunnelModeTransform(@NonNull android.net.IpSecManager.IpSecTunnelInterface, int, @NonNull android.net.IpSecTransform) throws java.io.IOException; + method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public android.net.IpSecManager.IpSecTunnelInterface createIpSecTunnelInterface(@NonNull java.net.InetAddress, @NonNull java.net.InetAddress, @NonNull android.net.Network) throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException; } public static final class IpSecManager.IpSecTunnelInterface implements java.lang.AutoCloseable { + method @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public void addAddress(@NonNull java.net.InetAddress, int) throws java.io.IOException; + method public void close(); method @NonNull public String getInterfaceName(); + method @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public void removeAddress(@NonNull java.net.InetAddress, int) throws java.io.IOException; } public static class IpSecTransform.Builder { @@ -8896,6 +9077,7 @@ package android.provider { field @Deprecated public static final String NAMESPACE_STORAGE = "storage"; field public static final String NAMESPACE_STORAGE_NATIVE_BOOT = "storage_native_boot"; field public static final String NAMESPACE_SYSTEMUI = "systemui"; + field public static final String NAMESPACE_SYSTEM_TIME = "system_time"; field public static final String NAMESPACE_TELEPHONY = "telephony"; field public static final String NAMESPACE_TEXTCLASSIFIER = "textclassifier"; field public static final String NAMESPACE_WINDOW_MANAGER_NATIVE_BOOT = "window_manager_native_boot"; @@ -9845,6 +10027,7 @@ package android.service.notification { method public void onNotificationDirectReplied(@NonNull String); method @Nullable public abstract android.service.notification.Adjustment onNotificationEnqueued(@NonNull android.service.notification.StatusBarNotification); method @Nullable public android.service.notification.Adjustment onNotificationEnqueued(@NonNull android.service.notification.StatusBarNotification, @NonNull android.app.NotificationChannel); + method @Nullable public android.service.notification.Adjustment onNotificationEnqueued(@NonNull android.service.notification.StatusBarNotification, @NonNull android.app.NotificationChannel, @NonNull android.service.notification.NotificationListenerService.RankingMap); method public void onNotificationExpansionChanged(@NonNull String, boolean, boolean); method public abstract void onNotificationSnoozedUntilContext(@NonNull android.service.notification.StatusBarNotification, @NonNull String); method public void onNotificationVisibilityChanged(@NonNull String, boolean); @@ -10070,6 +10253,21 @@ package android.service.settings.suggestions { } +package android.service.smartspace { + + public abstract class SmartspaceService extends android.app.Service { + ctor public SmartspaceService(); + method @MainThread public abstract void notifySmartspaceEvent(@NonNull android.app.smartspace.SmartspaceSessionId, @NonNull android.app.smartspace.SmartspaceTargetEvent); + method @NonNull public final android.os.IBinder onBind(@NonNull android.content.Intent); + method public abstract void onCreateSmartspaceSession(@NonNull android.app.smartspace.SmartspaceConfig, @NonNull android.app.smartspace.SmartspaceSessionId); + method @MainThread public abstract void onDestroy(@NonNull android.app.smartspace.SmartspaceSessionId); + method public abstract void onDestroySmartspaceSession(@NonNull android.app.smartspace.SmartspaceSessionId); + method @MainThread public abstract void onRequestSmartspaceUpdate(@NonNull android.app.smartspace.SmartspaceSessionId); + method public final void updateSmartspaceTargets(@NonNull android.app.smartspace.SmartspaceSessionId, @NonNull java.util.List<android.app.smartspace.SmartspaceTarget>); + } + +} + package android.service.storage { public abstract class ExternalStorageService extends android.app.Service { diff --git a/core/api/system-lint-baseline.txt b/core/api/system-lint-baseline.txt index 8b3cee403bca..58f6c52d2b05 100644 --- a/core/api/system-lint-baseline.txt +++ b/core/api/system-lint-baseline.txt @@ -6,9 +6,11 @@ ArrayReturn: android.view.contentcapture.ViewNode#getAutofillOptions(): BuilderSetStyle: android.net.IpSecTransform.Builder#buildTunnelModeTransform(java.net.InetAddress, android.net.IpSecManager.SecurityParameterIndex): Builder methods names should use setFoo() / addFoo() / clearFoo() style: method android.net.IpSecTransform.Builder.buildTunnelModeTransform(java.net.InetAddress,android.net.IpSecManager.SecurityParameterIndex) + ExecutorRegistration: android.media.MediaPlayer#setOnRtpRxNoticeListener(android.content.Context, android.media.MediaPlayer.OnRtpRxNoticeListener, android.os.Handler): Registration methods should have overload that accepts delivery Executor: `setOnRtpRxNoticeListener` - + + GenericException: android.app.prediction.AppPredictor#finalize(): GenericException: android.hardware.location.ContextHubClient#finalize(): @@ -21,6 +23,8 @@ GenericException: android.service.autofill.augmented.FillWindow#finalize(): IntentBuilderName: android.app.search.SearchAction#getIntent(): +IntentBuilderName: android.app.smartspace.SmartspaceAction#getIntent(): + Methods creating an Intent should be named `create<Foo>Intent()`, was `getIntent` KotlinKeyword: android.app.Notification#when: @@ -83,6 +87,10 @@ MissingNullability: android.telephony.mbms.DownloadRequest.Builder#setServiceId( +OnNameExpected: android.service.smartspace.SmartspaceService#notifySmartspaceEvent(android.app.smartspace.SmartspaceSessionId, android.app.smartspace.SmartspaceTargetEvent): + Methods implemented by developers should follow the on<Something> style, was `notifySmartspaceEvent` + + ProtectedMember: android.printservice.recommendation.RecommendationService#attachBaseContext(android.content.Context): ProtectedMember: android.service.contentcapture.ContentCaptureService#dump(java.io.FileDescriptor, java.io.PrintWriter, String[]): @@ -187,11 +195,10 @@ SamShouldBeLast: android.media.AudioRecordingMonitor#registerAudioRecordingCallb SamShouldBeLast: android.media.AudioRouting#addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler): -SamShouldBeLast: android.media.MediaPlayer#setOnRtpRxNoticeListener(android.content.Context, android.media.MediaPlayer.OnRtpRxNoticeListener, android.os.Handler): - SAM-compatible parameters (such as parameter 2, "listener", in android.media.MediaPlayer.setOnRtpRxNoticeListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions - SamShouldBeLast: android.media.AudioTrack#addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler): +SamShouldBeLast: android.media.MediaPlayer#setOnRtpRxNoticeListener(android.content.Context, android.media.MediaPlayer.OnRtpRxNoticeListener, android.os.Handler): + SAM-compatible parameters (such as parameter 2, "listener", in android.media.MediaPlayer.setOnRtpRxNoticeListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions SamShouldBeLast: android.media.MediaRecorder#addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler): SamShouldBeLast: android.media.MediaRecorder#registerAudioRecordingCallback(java.util.concurrent.Executor, android.media.AudioManager.AudioRecordingCallback): @@ -258,3 +265,5 @@ UserHandleName: android.app.search.SearchAction.Builder#setUserHandle(android.os Method taking UserHandle should be named `doFooAsUser` or `queryFooForUser`, was `setUserHandle` UserHandleName: android.app.search.SearchTarget.Builder#setUserHandle(android.os.UserHandle): +UserHandleName: android.app.smartspace.SmartspaceAction.Builder#setUserHandle(android.os.UserHandle): + Method taking UserHandle should be named `doFooAsUser` or `queryFooForUser`, was `setUserHandle` diff --git a/core/api/test-current.txt b/core/api/test-current.txt index 445824a129ac..bc1858b63783 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -944,9 +944,8 @@ package android.hardware.input { public final class InputManager { method public int getBlockUntrustedTouchesMode(@NonNull android.content.Context); - method public float getMaximumObscuringOpacityForTouch(@NonNull android.content.Context); method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setBlockUntrustedTouchesMode(@NonNull android.content.Context, int); - method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setMaximumObscuringOpacityForTouch(@NonNull android.content.Context, float); + method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setMaximumObscuringOpacityForTouch(float); field public static final long BLOCK_UNTRUSTED_TOUCHES = 158002302L; // 0x96aec7eL } diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 9b141b7bc649..1f9cb6430a5d 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -2291,9 +2291,10 @@ public final class ActivityThread extends ClientTransactionHandler { * Resources if one has already been created. */ Resources getTopLevelResources(String resDir, String[] splitResDirs, String[] overlayDirs, - String[] libDirs, LoadedApk pkgInfo) { + String[] libDirs, LoadedApk pkgInfo, Configuration overrideConfig) { return mResourcesManager.getResources(null, resDir, splitResDirs, overlayDirs, libDirs, - null, null, pkgInfo.getCompatibilityInfo(), pkgInfo.getClassLoader(), null); + null, overrideConfig, pkgInfo.getCompatibilityInfo(), pkgInfo.getClassLoader(), + null); } @UnsupportedAppUsage diff --git a/core/java/android/app/ApplicationExitInfo.java b/core/java/android/app/ApplicationExitInfo.java index d716a3cf5445..7410a1ca04c8 100644 --- a/core/java/android/app/ApplicationExitInfo.java +++ b/core/java/android/app/ApplicationExitInfo.java @@ -50,7 +50,7 @@ import java.util.zip.GZIPInputStream; * * <p> * Application process could die for many reasons, for example {@link #REASON_LOW_MEMORY} - * when it was killed by the ystem because it was running low on memory. Reason + * when it was killed by the system because it was running low on memory. Reason * of the death can be retrieved via {@link #getReason}. Besides the reason, there are a few other * auxiliary APIs like {@link #getStatus} and {@link #getImportance} to help the caller with * additional diagnostic information. diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java index 77542bda22a0..7e7f887766e2 100644 --- a/core/java/android/app/ApplicationPackageManager.java +++ b/core/java/android/app/ApplicationPackageManager.java @@ -70,6 +70,7 @@ import android.content.pm.SuspendDialogInfo; import android.content.pm.VerifierDeviceIdentity; import android.content.pm.VersionedPackage; import android.content.pm.dex.ArtManager; +import android.content.res.Configuration; import android.content.res.Resources; import android.content.res.XmlResourceParser; import android.graphics.Bitmap; @@ -1691,20 +1692,29 @@ public class ApplicationPackageManager extends PackageManager { @Override public Resources getResourcesForApplication(@NonNull ApplicationInfo app) throws NameNotFoundException { + return getResourcesForApplication(app, null); + } + + @Override + public Resources getResourcesForApplication(@NonNull ApplicationInfo app, + @Nullable Configuration configuration) throws NameNotFoundException { if (app.packageName.equals("system")) { - return mContext.mMainThread.getSystemUiContext().getResources(); + Context sysuiContext = mContext.mMainThread.getSystemUiContext(); + if (configuration != null) { + sysuiContext = sysuiContext.createConfigurationContext(configuration); + } + return sysuiContext.getResources(); } final boolean sameUid = (app.uid == Process.myUid()); final Resources r = mContext.mMainThread.getTopLevelResources( - sameUid ? app.sourceDir : app.publicSourceDir, - sameUid ? app.splitSourceDirs : app.splitPublicSourceDirs, - app.resourceDirs, app.sharedLibraryFiles, - mContext.mPackageInfo); + sameUid ? app.sourceDir : app.publicSourceDir, + sameUid ? app.splitSourceDirs : app.splitPublicSourceDirs, + app.resourceDirs, app.sharedLibraryFiles, + mContext.mPackageInfo, configuration); if (r != null) { return r; } throw new NameNotFoundException("Unable to open " + app.publicSourceDir); - } @Override diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java index 534f3e25acde..671315f37b20 100644 --- a/core/java/android/app/PendingIntent.java +++ b/core/java/android/app/PendingIntent.java @@ -21,6 +21,7 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; +import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.annotation.SystemApi.Client; import android.annotation.TestApi; @@ -1275,6 +1276,7 @@ public final class PendingIntent implements Parcelable { * @param flags MATCH_* flags from {@link android.content.pm.PackageManager}. * @hide */ + @SuppressLint("NullableCollection") @RequiresPermission(permission.GET_INTENT_SENDER_INTENT) @SystemApi(client = Client.MODULE_LIBRARIES) @TestApi diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java index 1498dae764a9..f05c7b58e202 100644 --- a/core/java/android/app/SystemServiceRegistry.java +++ b/core/java/android/app/SystemServiceRegistry.java @@ -34,6 +34,7 @@ import android.app.prediction.AppPredictionManager; import android.app.role.RoleFrameworkInitializer; import android.app.search.SearchUiManager; import android.app.slice.SliceManager; +import android.app.smartspace.SmartspaceManager; import android.app.time.TimeManager; import android.app.timedetector.TimeDetector; import android.app.timedetector.TimeDetectorImpl; @@ -120,21 +121,16 @@ import android.media.tv.ITvInputManager; import android.media.tv.TvInputManager; import android.media.tv.tunerresourcemanager.ITunerResourceManager; import android.media.tv.tunerresourcemanager.TunerResourceManager; -import android.net.ConnectivityDiagnosticsManager; -import android.net.ConnectivityManager; +import android.net.ConnectivityFrameworkInitializer; import android.net.EthernetManager; -import android.net.IConnectivityManager; import android.net.IEthernetManager; import android.net.IIpSecService; import android.net.INetworkPolicyManager; -import android.net.ITestNetworkManager; import android.net.IpSecManager; import android.net.NetworkPolicyManager; import android.net.NetworkScoreManager; import android.net.NetworkWatchlistManager; -import android.net.TestNetworkManager; import android.net.TetheringManager; -import android.net.VpnManager; import android.net.lowpan.ILowpanManager; import android.net.lowpan.LowpanManager; import android.net.nsd.INsdManager; @@ -163,7 +159,6 @@ import android.os.IUserManager; import android.os.IncidentManager; import android.os.PowerManager; import android.os.RecoverySystem; -import android.os.RemoteException; import android.os.ServiceManager; import android.os.ServiceManager.ServiceNotFoundException; import android.os.StatsFrameworkInitializer; @@ -370,15 +365,6 @@ public final class SystemServiceRegistry { // (which extends it). SYSTEM_SERVICE_NAMES.put(android.text.ClipboardManager.class, Context.CLIPBOARD_SERVICE); - registerService(Context.CONNECTIVITY_SERVICE, ConnectivityManager.class, - new StaticApplicationContextServiceFetcher<ConnectivityManager>() { - @Override - public ConnectivityManager createService(Context context) throws ServiceNotFoundException { - IBinder b = ServiceManager.getServiceOrThrow(Context.CONNECTIVITY_SERVICE); - IConnectivityManager service = IConnectivityManager.Stub.asInterface(b); - return new ConnectivityManager(context, service); - }}); - registerService(Context.NETD_SERVICE, IBinder.class, new StaticServiceFetcher<IBinder>() { @Override public IBinder createService() throws ServiceNotFoundException { @@ -412,50 +398,6 @@ public final class SystemServiceRegistry { return new IpSecManager(ctx, service); }}); - registerService(Context.VPN_MANAGEMENT_SERVICE, VpnManager.class, - new CachedServiceFetcher<VpnManager>() { - @Override - public VpnManager createService(ContextImpl ctx) throws ServiceNotFoundException { - IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE); - IConnectivityManager service = IConnectivityManager.Stub.asInterface(b); - return new VpnManager(ctx, service); - }}); - - registerService(Context.CONNECTIVITY_DIAGNOSTICS_SERVICE, - ConnectivityDiagnosticsManager.class, - new CachedServiceFetcher<ConnectivityDiagnosticsManager>() { - @Override - public ConnectivityDiagnosticsManager createService(ContextImpl ctx) - throws ServiceNotFoundException { - // ConnectivityDiagnosticsManager is backed by ConnectivityService - IBinder b = ServiceManager.getServiceOrThrow(Context.CONNECTIVITY_SERVICE); - IConnectivityManager service = IConnectivityManager.Stub.asInterface(b); - return new ConnectivityDiagnosticsManager(ctx, service); - }}); - - registerService( - Context.TEST_NETWORK_SERVICE, - TestNetworkManager.class, - new StaticApplicationContextServiceFetcher<TestNetworkManager>() { - @Override - public TestNetworkManager createService(Context context) - throws ServiceNotFoundException { - IBinder csBinder = - ServiceManager.getServiceOrThrow(Context.CONNECTIVITY_SERVICE); - IConnectivityManager csMgr = - IConnectivityManager.Stub.asInterface(csBinder); - - final IBinder tnBinder; - try { - tnBinder = csMgr.startOrGetTestNetworkService(); - } catch (RemoteException e) { - throw new ServiceNotFoundException(Context.TEST_NETWORK_SERVICE); - } - ITestNetworkManager tnMgr = ITestNetworkManager.Stub.asInterface(tnBinder); - return new TestNetworkManager(tnMgr); - } - }); - registerService(Context.COUNTRY_DETECTOR, CountryDetector.class, new StaticServiceFetcher<CountryDetector>() { @Override @@ -1224,6 +1166,16 @@ public final class SystemServiceRegistry { } }); + registerService(Context.SMARTSPACE_SERVICE, SmartspaceManager.class, + new CachedServiceFetcher<SmartspaceManager>() { + @Override + public SmartspaceManager createService(ContextImpl ctx) + throws ServiceNotFoundException { + IBinder b = ServiceManager.getService(Context.SMARTSPACE_SERVICE); + return b == null ? null : new SmartspaceManager(ctx); + } + }); + registerService(Context.APP_PREDICTION_SERVICE, AppPredictionManager.class, new CachedServiceFetcher<AppPredictionManager>() { @Override @@ -1441,6 +1393,7 @@ public final class SystemServiceRegistry { try { // Note: the following functions need to be @SystemApis, once they become mainline // modules. + ConnectivityFrameworkInitializer.registerServiceWrappers(); JobSchedulerFrameworkInitializer.registerServiceWrappers(); BlobStoreManagerFrameworkInitializer.initialize(); TelephonyFrameworkInitializer.registerServiceWrappers(); diff --git a/core/java/android/app/TaskInfo.java b/core/java/android/app/TaskInfo.java index 623c878d7bfa..e31e0243cae0 100644 --- a/core/java/android/app/TaskInfo.java +++ b/core/java/android/app/TaskInfo.java @@ -36,7 +36,6 @@ import android.window.TaskSnapshot; import android.window.WindowContainerToken; import java.util.ArrayList; -import java.util.List; import java.util.Objects; /** @@ -180,6 +179,19 @@ public class TaskInfo { public ActivityInfo topActivityInfo; /** + * The top activity in this task. + * @hide + */ + @Nullable + public IBinder topActivityToken; + + /** + * Whether the direct top activity is in size compat mode on foreground. + * @hide + */ + public boolean topActivityInSizeCompat; + + /** * Whether this task is resizable. Unlike {@link #resizeMode} (which is what the top activity * supports), this is what the system actually uses for resizability based on other policy and * developer options. @@ -356,6 +368,8 @@ public class TaskInfo { parentTaskId = source.readInt(); isFocused = source.readBoolean(); isVisible = source.readBoolean(); + topActivityToken = source.readStrongBinder(); + topActivityInSizeCompat = source.readBoolean(); } /** @@ -391,6 +405,8 @@ public class TaskInfo { dest.writeInt(parentTaskId); dest.writeBoolean(isFocused); dest.writeBoolean(isVisible); + dest.writeStrongBinder(topActivityToken); + dest.writeBoolean(topActivityInSizeCompat); } @Override @@ -415,6 +431,8 @@ public class TaskInfo { + " parentTaskId=" + parentTaskId + " isFocused=" + isFocused + " isVisible=" + isVisible + + " topActivityToken=" + topActivityToken + + " topActivityInSizeCompat=" + topActivityInSizeCompat + "}"; } } diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java index 65a21640bb98..2b52875f4b0b 100644 --- a/core/java/android/app/assist/AssistStructure.java +++ b/core/java/android/app/assist/AssistStructure.java @@ -2,6 +2,7 @@ package android.app.assist; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.app.Activity; import android.content.ComponentName; @@ -1542,6 +1543,7 @@ public class AssistStructure implements Parcelable { * {@link View#getOnReceiveContentMimeTypes()} for details. */ @Nullable + @SuppressLint("NullableCollection") public String[] getOnReceiveContentMimeTypes() { return mOnReceiveContentMimeTypes; } diff --git a/core/java/android/app/search/Query.java b/core/java/android/app/search/Query.java index 447ca314b99b..3ab20bb30b22 100644 --- a/core/java/android/app/search/Query.java +++ b/core/java/android/app/search/Query.java @@ -17,6 +17,7 @@ package android.app.search; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.os.Bundle; import android.os.Parcel; @@ -46,6 +47,7 @@ public final class Query implements Parcelable { public Query(@NonNull String input, long timestamp, + @SuppressLint("NullableCollection") @Nullable Bundle extras) { mInput = input; mTimestamp = timestamp; @@ -69,6 +71,7 @@ public final class Query implements Parcelable { } @Nullable + @SuppressLint("NullableCollection") public Bundle getExtras() { return mExtras; } diff --git a/core/java/android/app/search/SearchAction.java b/core/java/android/app/search/SearchAction.java index a76154af63b6..9e40e7ebaef0 100644 --- a/core/java/android/app/search/SearchAction.java +++ b/core/java/android/app/search/SearchAction.java @@ -18,6 +18,7 @@ package android.app.search; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.app.PendingIntent; import android.content.Intent; @@ -167,6 +168,7 @@ public final class SearchAction implements Parcelable { /** * Returns the extra bundle for this object. */ + @SuppressLint("NullableCollection") public @Nullable Bundle getExtras() { return mExtras; } @@ -325,7 +327,8 @@ public final class SearchAction implements Parcelable { * Sets the extra. */ @NonNull - public SearchAction.Builder setExtras(@Nullable Bundle extras) { + public SearchAction.Builder setExtras( + @SuppressLint("NullableCollection") @Nullable Bundle extras) { mExtras = extras; return this; } diff --git a/core/java/android/app/search/SearchContext.java b/core/java/android/app/search/SearchContext.java index 9bf766dc8668..548b7daff3a6 100644 --- a/core/java/android/app/search/SearchContext.java +++ b/core/java/android/app/search/SearchContext.java @@ -17,6 +17,7 @@ package android.app.search; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.os.Bundle; import android.os.Parcel; @@ -52,7 +53,7 @@ public final class SearchContext implements Parcelable { public SearchContext(int resultTypes, int queryTimeoutMillis, - @Nullable Bundle extras) { + @SuppressLint("NullableCollection") @Nullable Bundle extras) { mResultTypes = resultTypes; mTimeoutMillis = queryTimeoutMillis; mExtras = extras; @@ -83,6 +84,7 @@ public final class SearchContext implements Parcelable { } @Nullable + @SuppressLint("NullableCollection") public Bundle getExtras() { return mExtras; } diff --git a/core/java/android/app/search/SearchTarget.java b/core/java/android/app/search/SearchTarget.java index cac22d81c67b..6a80f8bd222a 100644 --- a/core/java/android/app/search/SearchTarget.java +++ b/core/java/android/app/search/SearchTarget.java @@ -17,6 +17,7 @@ package android.app.search; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.appwidget.AppWidgetProviderInfo; import android.content.pm.ShortcutInfo; @@ -224,6 +225,7 @@ public final class SearchTarget implements Parcelable { * Return extra bundle. */ @Nullable + @SuppressLint("NullableCollection") public Bundle getExtras() { return mExtras; } @@ -386,7 +388,7 @@ public final class SearchTarget implements Parcelable { * TODO: add comment */ @NonNull - public Builder setExtras(@Nullable Bundle extras) { + public Builder setExtras(@SuppressLint("NullableCollection") @Nullable Bundle extras) { mExtras = extras; return this; } diff --git a/core/java/android/app/smartspace/ISmartspaceCallback.aidl b/core/java/android/app/smartspace/ISmartspaceCallback.aidl new file mode 100644 index 000000000000..df105f9db7c1 --- /dev/null +++ b/core/java/android/app/smartspace/ISmartspaceCallback.aidl @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.app.smartspace; + +import android.content.pm.ParceledListSlice; + +/** + * @hide + */ +oneway interface ISmartspaceCallback { + + void onResult(in ParceledListSlice result); +} diff --git a/core/java/android/app/smartspace/ISmartspaceManager.aidl b/core/java/android/app/smartspace/ISmartspaceManager.aidl new file mode 100644 index 000000000000..e7ec8891ea83 --- /dev/null +++ b/core/java/android/app/smartspace/ISmartspaceManager.aidl @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.app.smartspace; + +import android.app.smartspace.SmartspaceTarget; +import android.app.smartspace.SmartspaceTargetEvent; +import android.app.smartspace.SmartspaceSessionId; +import android.app.smartspace.SmartspaceConfig; +import android.app.smartspace.ISmartspaceCallback; +import android.content.pm.ParceledListSlice; + +/** + * @hide + */ +interface ISmartspaceManager { + + void createSmartspaceSession(in SmartspaceConfig config, in SmartspaceSessionId sessionId, + in IBinder token); + + void notifySmartspaceEvent(in SmartspaceSessionId sessionId, in SmartspaceTargetEvent event); + + void requestSmartspaceUpdate(in SmartspaceSessionId sessionId); + + void registerSmartspaceUpdates(in SmartspaceSessionId sessionId, + in ISmartspaceCallback callback); + + void unregisterSmartspaceUpdates(in SmartspaceSessionId sessionId, + in ISmartspaceCallback callback); + + void destroySmartspaceSession(in SmartspaceSessionId sessionId); +} diff --git a/core/java/android/app/smartspace/SmartspaceAction.java b/core/java/android/app/smartspace/SmartspaceAction.java new file mode 100644 index 000000000000..033cda1ba845 --- /dev/null +++ b/core/java/android/app/smartspace/SmartspaceAction.java @@ -0,0 +1,353 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.app.smartspace; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SystemApi; +import android.app.PendingIntent; +import android.content.Intent; +import android.graphics.drawable.Icon; +import android.os.Bundle; +import android.os.Parcel; +import android.os.Parcelable; +import android.os.UserHandle; +import android.text.TextUtils; + +import java.util.Objects; + +/** + * A {@link SmartspaceAction} represents an action which can be taken by a user by tapping on either + * the title, the subtitle or on the icon. Supported instances are Intents, PendingIntents or a + * ShortcutInfo (by putting the ShortcutInfoId in the bundle). These actions can be called from + * another process or within the client process. + * + * Clients can also receive conditional Intents/PendingIntents in the extras bundle which are + * supposed to be fired when the conditions are met. For example, a user can invoke a dismiss/block + * action on a game score card but the intention is to only block the team and not the entire + * feature. + * + * @hide + */ +@SystemApi +public final class SmartspaceAction implements Parcelable { + + private static final String TAG = "SmartspaceAction"; + + /** A unique Id of this {@link SmartspaceAction}. */ + @NonNull + private final String mId; + + /** An Icon which can be displayed in the UI. */ + @Nullable + private final Icon mIcon; + + /** Title associated with an action. */ + @NonNull + private final CharSequence mTitle; + + /** Subtitle associated with an action. */ + @Nullable + private final CharSequence mSubtitle; + + @Nullable + private final CharSequence mContentDescription; + + @Nullable + private final PendingIntent mPendingIntent; + + @Nullable + private final Intent mIntent; + + @Nullable + private final UserHandle mUserHandle; + + @Nullable + private Bundle mExtras; + + SmartspaceAction(Parcel in) { + mId = in.readString(); + mIcon = in.readTypedObject(Icon.CREATOR); + mTitle = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); + mSubtitle = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); + mContentDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); + mPendingIntent = in.readTypedObject(PendingIntent.CREATOR); + mIntent = in.readTypedObject(Intent.CREATOR); + mUserHandle = in.readTypedObject(UserHandle.CREATOR); + mExtras = in.readTypedObject(Bundle.CREATOR); + } + + private SmartspaceAction( + @NonNull String id, + @Nullable Icon icon, + @NonNull CharSequence title, + @Nullable CharSequence subtitle, + @Nullable CharSequence contentDescription, + @Nullable PendingIntent pendingIntent, + @Nullable Intent intent, + @Nullable UserHandle userHandle, + @Nullable Bundle extras) { + mId = Objects.requireNonNull(id); + mIcon = icon; + mTitle = Objects.requireNonNull(title); + mSubtitle = subtitle; + mContentDescription = contentDescription; + mPendingIntent = pendingIntent; + mIntent = intent; + mUserHandle = userHandle; + mExtras = extras; + } + + /** + * Returns the unique id of this object. + */ + public @NonNull String getId() { + return mId; + } + + /** + * Returns an icon representing the action. + */ + public @Nullable Icon getIcon() { + return mIcon; + } + + /** + * Returns a title representing the action. + */ + public @NonNull CharSequence getTitle() { + return mTitle; + } + + /** + * Returns a subtitle representing the action. + */ + public @Nullable CharSequence getSubtitle() { + return mSubtitle; + } + + /** + * Returns a content description representing the action. + */ + public @Nullable CharSequence getContentDescription() { + return mContentDescription; + } + + /** + * Returns the action intent. + */ + public @Nullable PendingIntent getPendingIntent() { + return mPendingIntent; + } + + /** + * Returns the intent. + */ + public @Nullable Intent getIntent() { + return mIntent; + } + + /** + * Returns the user handle. + */ + public @Nullable UserHandle getUserHandle() { + return mUserHandle; + } + + /** + * Returns the extra bundle for this object. + */ + public @Nullable Bundle getExtras() { + return mExtras; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof SmartspaceAction)) return false; + SmartspaceAction that = (SmartspaceAction) o; + return mId.equals(that.mId); + } + + @Override + public int hashCode() { + return Objects.hash(mId); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel out, int flags) { + out.writeString(mId); + out.writeTypedObject(mIcon, flags); + TextUtils.writeToParcel(mTitle, out, flags); + TextUtils.writeToParcel(mSubtitle, out, flags); + TextUtils.writeToParcel(mContentDescription, out, flags); + out.writeTypedObject(mPendingIntent, flags); + out.writeTypedObject(mIntent, flags); + out.writeTypedObject(mUserHandle, flags); + out.writeBundle(mExtras); + } + + @Override + public String toString() { + return "SmartspaceAction{" + + "mId='" + mId + '\'' + + ", mIcon=" + mIcon + + ", mTitle=" + mTitle + + ", mSubtitle=" + mSubtitle + + ", mContentDescription=" + mContentDescription + + ", mPendingIntent=" + mPendingIntent + + ", mIntent=" + mIntent + + ", mUserHandle=" + mUserHandle + + ", mExtras=" + mExtras + + '}'; + } + + public static final @NonNull Creator<SmartspaceAction> CREATOR = + new Creator<SmartspaceAction>() { + public SmartspaceAction createFromParcel(Parcel in) { + return new SmartspaceAction(in); + } + public SmartspaceAction[] newArray(int size) { + return new SmartspaceAction[size]; + } + }; + + /** + * A builder for Smartspace action object. + * + * @hide + */ + @SystemApi + public static final class Builder { + @NonNull + private String mId; + + @Nullable + private Icon mIcon; + + @NonNull + private CharSequence mTitle; + + @Nullable + private CharSequence mSubtitle; + + @Nullable + private CharSequence mContentDescription; + + @Nullable + private PendingIntent mPendingIntent; + + @Nullable + private Intent mIntent; + + @Nullable + private UserHandle mUserHandle; + + @Nullable + private Bundle mExtras; + + /** + * Id and title are required. + */ + public Builder(@NonNull String id, @NonNull String title) { + mId = Objects.requireNonNull(id); + mTitle = Objects.requireNonNull(title); + } + + /** + * Sets the icon. + */ + @NonNull + public Builder setIcon( + @Nullable Icon icon) { + mIcon = icon; + return this; + } + + /** + * Sets the subtitle. + */ + @NonNull + public Builder setSubtitle( + @Nullable CharSequence subtitle) { + mSubtitle = subtitle; + return this; + } + + /** + * Sets the content description. + */ + @NonNull + public Builder setContentDescription( + @Nullable CharSequence contentDescription) { + mContentDescription = contentDescription; + return this; + } + + /** + * Sets the pending intent. + */ + @NonNull + public Builder setPendingIntent(@Nullable PendingIntent pendingIntent) { + mPendingIntent = pendingIntent; + return this; + } + + /** + * Sets the user handle. + */ + @NonNull + public Builder setUserHandle(@Nullable UserHandle userHandle) { + mUserHandle = userHandle; + return this; + } + + /** + * Sets the intent. + */ + @NonNull + public Builder setIntent(@Nullable Intent intent) { + mIntent = intent; + return this; + } + + /** + * Sets the extra. + */ + @NonNull + public Builder setExtras(@Nullable Bundle extras) { + mExtras = extras; + return this; + } + + /** + * Builds a new SmartspaceAction instance. + * + * @throws IllegalStateException if no target is set + */ + @NonNull + public SmartspaceAction build() { + return new SmartspaceAction(mId, mIcon, mTitle, mSubtitle, mContentDescription, + mPendingIntent, mIntent, mUserHandle, mExtras); + } + } +} diff --git a/core/java/android/app/smartspace/SmartspaceConfig.aidl b/core/java/android/app/smartspace/SmartspaceConfig.aidl new file mode 100644 index 000000000000..136b6f412b54 --- /dev/null +++ b/core/java/android/app/smartspace/SmartspaceConfig.aidl @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2021, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.app.smartspace; + +parcelable SmartspaceConfig;
\ No newline at end of file diff --git a/core/java/android/app/smartspace/SmartspaceConfig.java b/core/java/android/app/smartspace/SmartspaceConfig.java new file mode 100644 index 000000000000..1f9cbb5ca33b --- /dev/null +++ b/core/java/android/app/smartspace/SmartspaceConfig.java @@ -0,0 +1,202 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.app.smartspace; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SystemApi; +import android.content.Context; +import android.os.Bundle; +import android.os.Parcel; +import android.os.Parcelable; + +import java.util.Objects; + +/** + * A {@link SmartspaceConfig} instance is supposed to be created by a smartspace client for each + * UISurface. The client can specify some initialization conditions for the UISurface like its name, + * expected number of smartspace cards etc. The clients can also specify if they want periodic + * updates or their desired maximum refresh frequency. + * + * @hide + */ +@SystemApi +public final class SmartspaceConfig implements Parcelable { + + /** + * The least number of smartspace targets expected to be predicted by the backend. The backend + * will always try to satisfy this threshold but it is not guaranteed to always meet it. + */ + private final int mSmartspaceTargetCount; + + /** + * A {@link mUiSurface} is the name of the surface which will be used to display the cards. A + * few examples are homescreen, lockscreen, aod etc. + */ + @NonNull + private final String mUiSurface; + + /** Package name of the client. */ + @NonNull + private String mPackageName; + + /** Send other client UI configurations in extras. + * + * This can include: + * + * - Desired maximum update frequency + * - Request to get periodic updates + * - Request to support multiple clients for the same UISurface. + */ + @Nullable + private final Bundle mExtras; + + private SmartspaceConfig(@NonNull String uiSurface, int numPredictedTargets, + @NonNull String packageName, @Nullable Bundle extras) { + mUiSurface = uiSurface; + mSmartspaceTargetCount = numPredictedTargets; + mPackageName = packageName; + mExtras = extras; + } + + private SmartspaceConfig(Parcel parcel) { + mUiSurface = parcel.readString(); + mSmartspaceTargetCount = parcel.readInt(); + mPackageName = parcel.readString(); + mExtras = parcel.readBundle(); + } + + /** Returns the package name of the prediction context. */ + @NonNull + public String getPackageName() { + return mPackageName; + } + + /** Returns the number of smartspace targets requested by the user. */ + @NonNull + public int getSmartspaceTargetCount() { + return mSmartspaceTargetCount; + } + + /** Returns the UISurface requested by the client. */ + @NonNull + public String getUiSurface() { + return mUiSurface; + } + + @Nullable + public Bundle getExtras() { + return mExtras; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeString(mUiSurface); + dest.writeInt(mSmartspaceTargetCount); + dest.writeString(mPackageName); + dest.writeBundle(mExtras); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + SmartspaceConfig that = (SmartspaceConfig) o; + return mSmartspaceTargetCount == that.mSmartspaceTargetCount + && Objects.equals(mUiSurface, that.mUiSurface) + && Objects.equals(mPackageName, that.mPackageName) + && Objects.equals(mExtras, that.mExtras); + } + + @Override + public int hashCode() { + return Objects.hash(mSmartspaceTargetCount, mUiSurface, mPackageName, mExtras); + } + + /** + * @see Creator + */ + @NonNull + public static final Creator<SmartspaceConfig> CREATOR = + new Creator<SmartspaceConfig>() { + public SmartspaceConfig createFromParcel(Parcel parcel) { + return new SmartspaceConfig(parcel); + } + + public SmartspaceConfig[] newArray(int size) { + return new SmartspaceConfig[size]; + } + }; + + /** + * A builder for {@link SmartspaceConfig}. + * + * @hide + */ + @SystemApi + public static final class Builder { + @NonNull + private int mSmartspaceTargetCount = 5; // Default count is 5 + @NonNull + private final String mUiSurface; + @NonNull + private final String mPackageName; + @NonNull + private Bundle mExtras = Bundle.EMPTY; + + /** + * @param context The {@link Context} which is used to fetch the package name. + * @param uiSurface the UI Surface name associated with this context. + * @hide + */ + @SystemApi + public Builder(@NonNull Context context, @NonNull String uiSurface) { + mPackageName = context.getPackageName(); + this.mUiSurface = uiSurface; + } + + /** + * Used to set the expected number of cards for this context. + */ + @NonNull + public Builder setSmartspaceTargetCount(int smartspaceTargetCount) { + this.mSmartspaceTargetCount = smartspaceTargetCount; + return this; + } + + /** + * Used to send a bundle containing extras for the {@link SmartspaceConfig}. + */ + @NonNull + public Builder setExtras(@NonNull Bundle extras) { + this.mExtras = extras; + return this; + } + + /** + * Returns an instance of {@link SmartspaceConfig}. + */ + @NonNull + public SmartspaceConfig build() { + return new SmartspaceConfig(mUiSurface, mSmartspaceTargetCount, mPackageName, mExtras); + } + } +} diff --git a/core/java/android/app/smartspace/SmartspaceManager.java b/core/java/android/app/smartspace/SmartspaceManager.java new file mode 100644 index 000000000000..ff5eb109dfe0 --- /dev/null +++ b/core/java/android/app/smartspace/SmartspaceManager.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.app.smartspace; + +import android.annotation.NonNull; +import android.annotation.SystemApi; +import android.content.Context; + +import java.util.Objects; + +/** + * Smartspace is a container in Android which is used to show contextual content powered by the + * intelligence service running on the device. A smartspace container can be on AoD, lockscreen or + * on the homescreen and can show personalized cards which are either derived from on device or + * online signals. + * + * {@link SmartspaceManager} is a system service that provides methods to create Smartspace session + * clients. An instance of this class is returned when a client calls + * <code> context.getSystemService("smartspace"); </code>. + * + * After receiving the service, a client must call + * {@link SmartspaceManager#createSmartspaceSession(SmartspaceConfig)} with a corresponding + * {@link SmartspaceConfig} to get an instance of {@link SmartspaceSession}. + * This session is then a client's point of contact with the api. They can send events, request for + * updates using the session. It is client's duty to call {@link SmartspaceSession#destroy()} to + * destroy the session once they no longer need it. + * + * @hide + */ +@SystemApi +public final class SmartspaceManager { + + private final Context mContext; + + /** + * @hide + */ + public SmartspaceManager(Context context) { + mContext = Objects.requireNonNull(context); + } + + /** + * Creates a new Smartspace session. + */ + @NonNull + public SmartspaceSession createSmartspaceSession( + @NonNull SmartspaceConfig smartspaceConfig) { + return new SmartspaceSession(mContext, smartspaceConfig); + } +} diff --git a/core/java/android/app/smartspace/SmartspaceSession.java b/core/java/android/app/smartspace/SmartspaceSession.java new file mode 100644 index 000000000000..16def61239cf --- /dev/null +++ b/core/java/android/app/smartspace/SmartspaceSession.java @@ -0,0 +1,284 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.app.smartspace; + +import android.annotation.CallbackExecutor; +import android.annotation.NonNull; +import android.annotation.SystemApi; +import android.app.smartspace.ISmartspaceCallback.Stub; +import android.content.Context; +import android.content.pm.ParceledListSlice; +import android.os.Binder; +import android.os.IBinder; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.util.ArrayMap; +import android.util.Log; + +import dalvik.system.CloseGuard; + +import java.util.List; +import java.util.UUID; +import java.util.concurrent.Executor; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Consumer; + +/** + * Client API to share information about the Smartspace UI state and execute query. + * + * <p> + * Usage: <pre> {@code + * + * class MyActivity { + * private SmartspaceSession mSmartspaceSession; + * + * void onCreate() { + * mSmartspaceSession = mSmartspaceManager.createSmartspaceSession(smartspaceConfig) + * mSmartspaceSession.registerSmartspaceUpdates(...) + * } + * + * void onStart() { + * mSmartspaceSession.requestSmartspaceUpdate() + * } + * + * void onTouch(...) OR + * void onStateTransitionStarted(...) OR + * void onResume(...) OR + * void onStop(...) { + * mSmartspaceSession.notifyEvent(event); + * } + * + * void onDestroy() { + * mSmartspaceSession.unregisterPredictionUpdates() + * mSmartspaceSession.destroy(); + * } + * + * }</pre> + * + * @hide + */ +@SystemApi +public final class SmartspaceSession implements AutoCloseable { + + private static final String TAG = SmartspaceSession.class.getSimpleName(); + private static final boolean DEBUG = false; + + private final android.app.smartspace.ISmartspaceManager mInterface; + private final CloseGuard mCloseGuard = CloseGuard.get(); + private final AtomicBoolean mIsClosed = new AtomicBoolean(false); + + private final SmartspaceSessionId mSessionId; + private final ArrayMap<Callback, CallbackWrapper> mRegisteredCallbacks = new ArrayMap<>(); + private final IBinder mToken = new Binder(); + + /** + * Creates a new Smartspace ui client. + * <p> + * The caller should call {@link SmartspaceSession#destroy()} to dispose the client once it + * no longer used. + * + * @param context the {@link Context} of the user of this {@link SmartspaceSession}. + * @param smartspaceConfig the Smartspace context. + */ + // b/177858121 Create weak reference child objects to not leak context. + SmartspaceSession(@NonNull Context context, @NonNull SmartspaceConfig smartspaceConfig) { + IBinder b = ServiceManager.getService(Context.SMARTSPACE_SERVICE); + mInterface = android.app.smartspace.ISmartspaceManager.Stub.asInterface(b); + mSessionId = new SmartspaceSessionId( + context.getPackageName() + ":" + UUID.randomUUID().toString(), context.getUserId()); + try { + mInterface.createSmartspaceSession(smartspaceConfig, mSessionId, mToken); + } catch (RemoteException e) { + Log.e(TAG, "Failed to cerate Smartspace session", e); + e.rethrowFromSystemServer(); + } + + mCloseGuard.open("close"); + } + + /** + * Notifies the Smartspace service of a Smartspace target event. + * + * @param event The {@link SmartspaceTargetEvent} that represents the Smartspace target event. + */ + public void notifySmartspaceEvent(@NonNull SmartspaceTargetEvent event) { + if (mIsClosed.get()) { + throw new IllegalStateException("This client has already been destroyed."); + } + try { + mInterface.notifySmartspaceEvent(mSessionId, event); + } catch (RemoteException e) { + Log.e(TAG, "Failed to notify event", e); + e.rethrowFromSystemServer(); + } + } + + /** + * Requests the smartspace service for an update. + */ + public void requestSmartspaceUpdate() { + if (mIsClosed.get()) { + throw new IllegalStateException("This client has already been destroyed."); + } + try { + mInterface.requestSmartspaceUpdate(mSessionId); + } catch (RemoteException e) { + Log.e(TAG, "Failed to request update.", e); + e.rethrowFromSystemServer(); + } + } + + /** + * Requests the smartspace service provide continuous updates of smartspace cards via the + * provided callback, until the given callback is unregistered. + * + * @param callbackExecutor The callback executor to use when calling the callback. + * @param callback The Callback to be called when updates of Smartspace targets are + * available. + */ + public void registerSmartspaceUpdates(@NonNull @CallbackExecutor Executor callbackExecutor, + @NonNull Callback callback) { + if (mIsClosed.get()) { + throw new IllegalStateException("This client has already been destroyed."); + } + + if (mRegisteredCallbacks.containsKey(callback)) { + // Skip if this callback is already registered + return; + } + try { + final CallbackWrapper callbackWrapper = new CallbackWrapper(callbackExecutor, + callback::onTargetsAvailable); + mRegisteredCallbacks.put(callback, callbackWrapper); + mInterface.registerSmartspaceUpdates(mSessionId, callbackWrapper); + mInterface.requestSmartspaceUpdate(mSessionId); + } catch (RemoteException e) { + Log.e(TAG, "Failed to register for smartspace updates", e); + e.rethrowAsRuntimeException(); + } + } + + /** + * Requests the smartspace service to stop providing continuous updates to the provided + * callback until the callback is re-registered. + * + * @see {@link SmartspaceSession#registerSmartspaceUpdates(Executor, Callback)}. + * + * @param callback The callback to be unregistered. + */ + public void unregisterSmartspaceUpdates(@NonNull Callback callback) { + if (mIsClosed.get()) { + throw new IllegalStateException("This client has already been destroyed."); + } + + if (!mRegisteredCallbacks.containsKey(callback)) { + // Skip if this callback was never registered + return; + } + try { + final CallbackWrapper callbackWrapper = mRegisteredCallbacks.remove(callback); + mInterface.unregisterSmartspaceUpdates(mSessionId, callbackWrapper); + } catch (RemoteException e) { + Log.e(TAG, "Failed to unregister for smartspace updates", e); + e.rethrowAsRuntimeException(); + } + } + + /** + * Destroys the client and unregisters the callback. Any method on this class after this call + * will throw {@link IllegalStateException}. + */ + public void destroy() { + if (!mIsClosed.getAndSet(true)) { + mCloseGuard.close(); + + // Do destroy; + try { + mInterface.destroySmartspaceSession(mSessionId); + } catch (RemoteException e) { + Log.e(TAG, "Failed to notify Smartspace target event", e); + e.rethrowFromSystemServer(); + } + } else { + throw new IllegalStateException("This client has already been destroyed."); + } + } + + @Override + protected void finalize() { + try { + if (mCloseGuard != null) { + mCloseGuard.warnIfOpen(); + } + if (!mIsClosed.get()) { + destroy(); + } + } finally { + try { + super.finalize(); + } catch (Throwable throwable) { + throwable.printStackTrace(); + } + } + } + + @Override + public void close() { + try { + finalize(); + } catch (Throwable throwable) { + throwable.printStackTrace(); + } + } + + /** + * Callback for receiving smartspace updates. + */ + public interface Callback { + + /** + * Called when a new set of smartspace targets are available. + * + * @param targets Sorted list of smartspace targets. + */ + void onTargetsAvailable(@NonNull List<SmartspaceTarget> targets); + } + + static class CallbackWrapper extends Stub { + + private final Consumer<List<SmartspaceTarget>> mCallback; + private final Executor mExecutor; + + CallbackWrapper(@NonNull Executor callbackExecutor, + @NonNull Consumer<List<SmartspaceTarget>> callback) { + mCallback = callback; + mExecutor = callbackExecutor; + } + + @Override + public void onResult(ParceledListSlice result) { + final long identity = Binder.clearCallingIdentity(); + try { + if (DEBUG) { + Log.d(TAG, "CallbackWrapper.onResult result=" + result.getList()); + } + mExecutor.execute(() -> mCallback.accept(result.getList())); + } finally { + Binder.restoreCallingIdentity(identity); + } + } + } +} diff --git a/core/java/android/app/smartspace/SmartspaceSessionId.aidl b/core/java/android/app/smartspace/SmartspaceSessionId.aidl new file mode 100644 index 000000000000..a864412edd65 --- /dev/null +++ b/core/java/android/app/smartspace/SmartspaceSessionId.aidl @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2021, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.app.smartspace; + +parcelable SmartspaceSessionId;
\ No newline at end of file diff --git a/core/java/android/app/smartspace/SmartspaceSessionId.java b/core/java/android/app/smartspace/SmartspaceSessionId.java new file mode 100644 index 000000000000..5220c35d7064 --- /dev/null +++ b/core/java/android/app/smartspace/SmartspaceSessionId.java @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.app.smartspace; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SystemApi; +import android.os.Parcel; +import android.os.Parcelable; + +import java.util.Objects; + +/** + * The id for an Smartspace session. See {@link SmartspaceSession}. + * + * @hide + */ +@SystemApi +public final class SmartspaceSessionId implements Parcelable { + + @NonNull + private final String mId; + + @NonNull + private final int mUserId; + + /** + * Creates a new id for a Smartspace session. + * + * @hide + */ + public SmartspaceSessionId(@NonNull final String id, @NonNull final int userId) { + mId = id; + mUserId = userId; + } + + private SmartspaceSessionId(Parcel p) { + mId = p.readString(); + mUserId = p.readInt(); + } + + /** + * Returns a {@link String} Id of this sessionId. + */ + @Nullable + public String getId() { + return mId; + } + + /** + * Returns the userId associated with this sessionId. + */ + @NonNull + public int getUserId() { + return mUserId; + } + + @Override + public boolean equals(@Nullable Object o) { + if (!getClass().equals(o != null ? o.getClass() : null)) return false; + + SmartspaceSessionId other = (SmartspaceSessionId) o; + return mId.equals(other.mId) && mUserId == other.mUserId; + } + + @Override + public String toString() { + return "SmartspaceSessionId{" + + "mId='" + mId + '\'' + + ", mUserId=" + mUserId + + '}'; + } + + @Override + public int hashCode() { + return Objects.hash(mId, mUserId); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeString(mId); + dest.writeInt(mUserId); + } + + public static final @NonNull Creator<SmartspaceSessionId> CREATOR = + new Creator<SmartspaceSessionId>() { + public SmartspaceSessionId createFromParcel(Parcel parcel) { + return new SmartspaceSessionId(parcel); + } + + public SmartspaceSessionId[] newArray(int size) { + return new SmartspaceSessionId[size]; + } + }; +} diff --git a/core/java/android/app/smartspace/SmartspaceTarget.aidl b/core/java/android/app/smartspace/SmartspaceTarget.aidl new file mode 100644 index 000000000000..3442cf294cbb --- /dev/null +++ b/core/java/android/app/smartspace/SmartspaceTarget.aidl @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2021, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.app.smartspace; + +parcelable SmartspaceTarget;
\ No newline at end of file diff --git a/core/java/android/app/smartspace/SmartspaceTarget.java b/core/java/android/app/smartspace/SmartspaceTarget.java new file mode 100644 index 000000000000..ce5040eb0a3e --- /dev/null +++ b/core/java/android/app/smartspace/SmartspaceTarget.java @@ -0,0 +1,660 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.app.smartspace; + +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SystemApi; +import android.appwidget.AppWidgetProviderInfo; +import android.content.ComponentName; +import android.net.Uri; +import android.os.Parcel; +import android.os.Parcelable; +import android.os.UserHandle; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +/** + * A {@link SmartspaceTarget} is a data class which holds all properties necessary to inflate a + * smartspace card. It contains data and related metadata which is supposed to be utilized by + * smartspace clients based on their own UI/UX requirements. Some of the properties have + * {@link SmartspaceAction} as their type because they can have associated actions. + * + * <p><b>NOTE: </b> + * If {@link mWidgetId} is set, it should be preferred over all other properties. + * Else, if {@link mSliceUri} is set, it should be preferred over all other data properties. + * Otherwise, the instance should be treated as a data object. + * + * @hide + */ +@SystemApi +public final class SmartspaceTarget implements Parcelable { + + /** A unique Id for an instance of {@link SmartspaceTarget}. */ + @NonNull + private final String mSmartspaceTargetId; + + /** A {@link SmartspaceAction} for the header in the Smartspace card. */ + @Nullable + private final SmartspaceAction mHeaderAction; + + /** A {@link SmartspaceAction} for the base action in the Smartspace card. */ + @Nullable + private final SmartspaceAction mBaseAction; + + /** A timestamp indicating when the card was created. */ + @NonNull + private final long mCreationTimeMillis; + + /** + * A timestamp indicating when the card should be removed from view, in case the service + * disconnects or restarts. + */ + @NonNull + private final long mExpiryTimeMillis; + + /** A score assigned to a target. */ + @NonNull + private final float mScore; + + /** A {@link List<SmartspaceAction>} containing all action chips. */ + @NonNull + private final List<SmartspaceAction> mActionChips; + + /** A {@link List<SmartspaceAction>} containing all icons for the grid. */ + @NonNull + private final List<SmartspaceAction> mIconGrid; + + /** + * {@link FeatureType} indicating the feature type of this card. + * + * @see FeatureType + */ + @FeatureType + @NonNull + private final int mFeatureType; + + /** + * Indicates whether the content is sensitive. Certain UI surfaces may choose to skip rendering + * real content until the device is unlocked. + */ + @NonNull + private final boolean mSensitive; + + /** Indicating if the UI should show this target in its expanded state. */ + @NonNull + private final boolean mShouldShowExpanded; + + /** A Notification key if the target was generated using a notification. */ + @Nullable + private final String mSourceNotificationKey; + + /** {@link ComponentName} for this target. */ + @NonNull + private final ComponentName mComponentName; + + /** {@link UserHandle} for this target. */ + @NonNull + private final UserHandle mUserHandle; + + /** Target Ids of other {@link SmartspaceTarget}s if they are associated with this target. */ + @Nullable + private final String mAssociatedSmartspaceTargetId; + + /** {@link Uri} Slice Uri if this target is a slice. */ + @Nullable + private final Uri mSliceUri; + + /** {@link AppWidgetProviderInfo} if this target is a widget. */ + @Nullable + private final AppWidgetProviderInfo mWidgetId; + + public static final int FEATURE_UNDEFINED = 0; + public static final int FEATURE_WEATHER = 1; + public static final int FEATURE_CALENDAR = 2; + public static final int FEATURE_COMMUTE_TIME = 3; + public static final int FEATURE_FLIGHT = 4; + public static final int FEATURE_TIPS = 5; + public static final int FEATURE_REMINDER = 6; + public static final int FEATURE_ALARM = 7; + public static final int FEATURE_ONBOARDING = 8; + public static final int FEATURE_SPORTS = 9; + public static final int FEATURE_WEATHER_ALERT = 10; + public static final int FEATURE_CONSENT = 11; + public static final int FEATURE_STOCK_PRICE_CHANGE = 12; + public static final int FEATURE_SHOPPING_LIST = 13; + public static final int FEATURE_LOYALTY_CARD = 14; + public static final int FEATURE_MEDIA = 15; + public static final int FEATURE_BEDTIME_ROUTINE = 16; + public static final int FEATURE_FITNESS_TRACKING = 17; + public static final int FEATURE_ETA_MONITORING = 18; + public static final int FEATURE_MISSED_CALL = 19; + public static final int FEATURE_PACKAGE_TRACKING = 20; + public static final int FEATURE_TIMER = 21; + public static final int FEATURE_STOPWATCH = 22; + public static final int FEATURE_UPCOMING_ALARM = 23; + + /** + * @hide + */ + @IntDef(prefix = {"FEATURE_"}, value = { + FEATURE_UNDEFINED, + FEATURE_WEATHER, + FEATURE_CALENDAR, + FEATURE_COMMUTE_TIME, + FEATURE_FLIGHT, + FEATURE_TIPS, + FEATURE_REMINDER, + FEATURE_ALARM, + FEATURE_ONBOARDING, + FEATURE_SPORTS, + FEATURE_WEATHER_ALERT, + FEATURE_CONSENT, + FEATURE_STOCK_PRICE_CHANGE, + FEATURE_SHOPPING_LIST, + FEATURE_LOYALTY_CARD, + FEATURE_MEDIA, + FEATURE_BEDTIME_ROUTINE, + FEATURE_FITNESS_TRACKING, + FEATURE_ETA_MONITORING, + FEATURE_MISSED_CALL, + FEATURE_PACKAGE_TRACKING, + FEATURE_TIMER, + FEATURE_STOPWATCH, + FEATURE_UPCOMING_ALARM + }) + @Retention(RetentionPolicy.SOURCE) + public @interface FeatureType { + } + + private SmartspaceTarget(Parcel in) { + this.mSmartspaceTargetId = in.readString(); + this.mHeaderAction = in.readTypedObject(SmartspaceAction.CREATOR); + this.mBaseAction = in.readTypedObject(SmartspaceAction.CREATOR); + this.mCreationTimeMillis = in.readLong(); + this.mExpiryTimeMillis = in.readLong(); + this.mScore = in.readFloat(); + this.mActionChips = in.createTypedArrayList(SmartspaceAction.CREATOR); + this.mIconGrid = in.createTypedArrayList(SmartspaceAction.CREATOR); + this.mFeatureType = in.readInt(); + this.mSensitive = in.readBoolean(); + this.mShouldShowExpanded = in.readBoolean(); + this.mSourceNotificationKey = in.readString(); + this.mComponentName = in.readTypedObject(ComponentName.CREATOR); + this.mUserHandle = in.readTypedObject(UserHandle.CREATOR); + this.mAssociatedSmartspaceTargetId = in.readString(); + this.mSliceUri = in.readTypedObject(Uri.CREATOR); + this.mWidgetId = in.readTypedObject(AppWidgetProviderInfo.CREATOR); + } + + private SmartspaceTarget(String smartspaceTargetId, + SmartspaceAction headerAction, SmartspaceAction baseAction, long creationTimeMillis, + long expiryTimeMillis, float score, + List<SmartspaceAction> actionChips, + List<SmartspaceAction> iconGrid, int featureType, boolean sensitive, + boolean shouldShowExpanded, String sourceNotificationKey, + ComponentName componentName, UserHandle userHandle, + String associatedSmartspaceTargetId, Uri sliceUri, + AppWidgetProviderInfo widgetId) { + mSmartspaceTargetId = smartspaceTargetId; + mHeaderAction = headerAction; + mBaseAction = baseAction; + mCreationTimeMillis = creationTimeMillis; + mExpiryTimeMillis = expiryTimeMillis; + mScore = score; + mActionChips = actionChips; + mIconGrid = iconGrid; + mFeatureType = featureType; + mSensitive = sensitive; + mShouldShowExpanded = shouldShowExpanded; + mSourceNotificationKey = sourceNotificationKey; + mComponentName = componentName; + mUserHandle = userHandle; + mAssociatedSmartspaceTargetId = associatedSmartspaceTargetId; + mSliceUri = sliceUri; + mWidgetId = widgetId; + } + + /** + * Returns the Id of the target. + */ + @NonNull + public String getSmartspaceTargetId() { + return mSmartspaceTargetId; + } + + /** + * Returns the header action of the target. + */ + @Nullable + public SmartspaceAction getHeaderAction() { + return mHeaderAction; + } + + /** + * Returns the base action of the target. + */ + @Nullable + public SmartspaceAction getBaseAction() { + return mBaseAction; + } + + /** + * Returns the creation time of the target. + */ + @NonNull + public long getCreationTimeMillis() { + return mCreationTimeMillis; + } + + /** + * Returns the expiry time of the target. + */ + @NonNull + public long getExpiryTimeMillis() { + return mExpiryTimeMillis; + } + + /** + * Returns the score of the target. + */ + @NonNull + public float getScore() { + return mScore; + } + + /** + * Return the action chips of the target. + */ + @NonNull + public List<SmartspaceAction> getActionChips() { + return mActionChips; + } + + /** + * Return the icons of the target. + */ + @NonNull + public List<SmartspaceAction> getIconGrid() { + return mIconGrid; + } + + /** + * Returns the feature type of the target. + */ + @NonNull + public int getFeatureType() { + return mFeatureType; + } + + /** + * Returns whether the target is sensitive or not. + */ + @NonNull + public boolean isSensitive() { + return mSensitive; + } + + /** + * Returns whether the target should be shown in expanded state. + */ + @NonNull + public boolean shouldShowExpanded() { + return mShouldShowExpanded; + } + + /** + * Returns the source notification key of the target. + */ + @Nullable + public String getSourceNotificationKey() { + return mSourceNotificationKey; + } + + /** + * Returns the component name of the target. + */ + @NonNull + public ComponentName getComponentName() { + return mComponentName; + } + + /** + * Returns the user handle of the target. + */ + @NonNull + public UserHandle getUserHandle() { + return mUserHandle; + } + + /** + * Returns the id of a target associated with this instance. + */ + @Nullable + public String getAssociatedSmartspaceTargetId() { + return mAssociatedSmartspaceTargetId; + } + + /** + * Returns the slice uri, if the target is a slice. + */ + @Nullable + public Uri getSliceUri() { + return mSliceUri; + } + + /** + * Returns the AppWidgetProviderInfo, if the target is a widget. + */ + @Nullable + public AppWidgetProviderInfo getWidgetId() { + return mWidgetId; + } + + /** + * @see Parcelable.Creator + */ + @NonNull + public static final Creator<SmartspaceTarget> CREATOR = new Creator<SmartspaceTarget>() { + @Override + public SmartspaceTarget createFromParcel(Parcel source) { + return new SmartspaceTarget(source); + } + + @Override + public SmartspaceTarget[] newArray(int size) { + return new SmartspaceTarget[size]; + } + }; + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeString(this.mSmartspaceTargetId); + dest.writeTypedObject(this.mHeaderAction, flags); + dest.writeTypedObject(this.mBaseAction, flags); + dest.writeLong(this.mCreationTimeMillis); + dest.writeLong(this.mExpiryTimeMillis); + dest.writeFloat(this.mScore); + dest.writeTypedList(this.mActionChips); + dest.writeTypedList(this.mIconGrid); + dest.writeInt(this.mFeatureType); + dest.writeBoolean(this.mSensitive); + dest.writeBoolean(this.mShouldShowExpanded); + dest.writeString(this.mSourceNotificationKey); + dest.writeTypedObject(this.mComponentName, flags); + dest.writeTypedObject(this.mUserHandle, flags); + dest.writeString(this.mAssociatedSmartspaceTargetId); + dest.writeTypedObject(this.mSliceUri, flags); + dest.writeTypedObject(this.mWidgetId, flags); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public String toString() { + return "SmartspaceTarget{" + + "mSmartspaceTargetId='" + mSmartspaceTargetId + '\'' + + ", mHeaderAction=" + mHeaderAction + + ", mBaseAction=" + mBaseAction + + ", mCreationTimeMillis=" + mCreationTimeMillis + + ", mExpiryTimeMillis=" + mExpiryTimeMillis + + ", mScore=" + mScore + + ", mActionChips=" + mActionChips + + ", mIconGrid=" + mIconGrid + + ", mFeatureType=" + mFeatureType + + ", mSensitive=" + mSensitive + + ", mShouldShowExpanded=" + mShouldShowExpanded + + ", mSourceNotificationKey='" + mSourceNotificationKey + '\'' + + ", mComponentName=" + mComponentName + + ", mUserHandle=" + mUserHandle + + ", mAssociatedSmartspaceTargetId='" + mAssociatedSmartspaceTargetId + '\'' + + ", mSliceUri=" + mSliceUri + + ", mWidgetId=" + mWidgetId + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + SmartspaceTarget that = (SmartspaceTarget) o; + return mCreationTimeMillis == that.mCreationTimeMillis + && mExpiryTimeMillis == that.mExpiryTimeMillis + && Float.compare(that.mScore, mScore) == 0 + && mFeatureType == that.mFeatureType + && mSensitive == that.mSensitive + && mShouldShowExpanded == that.mShouldShowExpanded + && mSmartspaceTargetId.equals(that.mSmartspaceTargetId) + && Objects.equals(mHeaderAction, that.mHeaderAction) + && Objects.equals(mBaseAction, that.mBaseAction) + && Objects.equals(mActionChips, that.mActionChips) + && Objects.equals(mIconGrid, that.mIconGrid) + && Objects.equals(mSourceNotificationKey, that.mSourceNotificationKey) + && mComponentName.equals(that.mComponentName) + && mUserHandle.equals(that.mUserHandle) + && Objects.equals(mAssociatedSmartspaceTargetId, + that.mAssociatedSmartspaceTargetId) + && Objects.equals(mSliceUri, that.mSliceUri) + && Objects.equals(mWidgetId, that.mWidgetId); + } + + @Override + public int hashCode() { + return Objects.hash(mSmartspaceTargetId, mHeaderAction, mBaseAction, mCreationTimeMillis, + mExpiryTimeMillis, mScore, mActionChips, mIconGrid, mFeatureType, mSensitive, + mShouldShowExpanded, mSourceNotificationKey, mComponentName, mUserHandle, + mAssociatedSmartspaceTargetId, mSliceUri, mWidgetId); + } + + /** + * A builder for {@link SmartspaceTarget} object. + * + * @hide + */ + @SystemApi + public static final class Builder { + private final String mSmartspaceTargetId; + private SmartspaceAction mHeaderAction; + private SmartspaceAction mBaseAction; + private long mCreationTimeMillis; + private long mExpiryTimeMillis; + private float mScore; + private List<SmartspaceAction> mActionChips = new ArrayList<>(); + private List<SmartspaceAction> mIconGrid = new ArrayList<>(); + private int mFeatureType; + private boolean mSensitive; + private boolean mShouldShowExpanded; + private String mSourceNotificationKey; + private final ComponentName mComponentName; + private final UserHandle mUserHandle; + private String mAssociatedSmartspaceTargetId; + private Uri mSliceUri; + private AppWidgetProviderInfo mWidgetId; + + /** + * A builder for {@link SmartspaceTarget}. + * + * @param smartspaceTargetId the id of this target + * @param componentName the componentName of this target + * @param userHandle the userHandle of this target + */ + public Builder(@NonNull String smartspaceTargetId, + @NonNull ComponentName componentName, @NonNull UserHandle userHandle) { + this.mSmartspaceTargetId = smartspaceTargetId; + this.mComponentName = componentName; + this.mUserHandle = userHandle; + } + + /** + * Sets the header action. + */ + @NonNull + public Builder setHeaderAction(@NonNull SmartspaceAction headerAction) { + this.mHeaderAction = headerAction; + return this; + } + + /** + * Sets the base action. + */ + @NonNull + public Builder setBaseAction(@NonNull SmartspaceAction baseAction) { + this.mBaseAction = baseAction; + return this; + } + + /** + * Sets the creation time. + */ + @NonNull + public Builder setCreationTimeMillis(@NonNull long creationTimeMillis) { + this.mCreationTimeMillis = creationTimeMillis; + return this; + } + + /** + * Sets the expiration time. + */ + @NonNull + public Builder setExpiryTimeMillis(@NonNull long expiryTimeMillis) { + this.mExpiryTimeMillis = expiryTimeMillis; + return this; + } + + /** + * Sets the score. + */ + @NonNull + public Builder setScore(@NonNull float score) { + this.mScore = score; + return this; + } + + /** + * Sets the action chips. + */ + @NonNull + public Builder setActionChips(@NonNull List<SmartspaceAction> actionChips) { + this.mActionChips = actionChips; + return this; + } + + /** + * Sets the icon grid. + */ + @NonNull + public Builder setIconGrid(@NonNull List<SmartspaceAction> iconGrid) { + this.mIconGrid = iconGrid; + return this; + } + + /** + * Sets the feature type. + */ + @NonNull + public Builder setFeatureType(@NonNull int featureType) { + this.mFeatureType = featureType; + return this; + } + + /** + * Sets whether the contents are sensitive. + */ + @NonNull + public Builder setSensitive(@NonNull boolean sensitive) { + this.mSensitive = sensitive; + return this; + } + + /** + * Sets whether to show the card as expanded. + */ + @NonNull + public Builder setShouldShowExpanded(@NonNull boolean shouldShowExpanded) { + this.mShouldShowExpanded = shouldShowExpanded; + return this; + } + + /** + * Sets the source notification key. + */ + @NonNull + public Builder setSourceNotificationKey(@NonNull String sourceNotificationKey) { + this.mSourceNotificationKey = sourceNotificationKey; + return this; + } + + /** + * Sets the associated smartspace target id. + */ + @NonNull + public Builder setAssociatedSmartspaceTargetId( + @NonNull String associatedSmartspaceTargetId) { + this.mAssociatedSmartspaceTargetId = associatedSmartspaceTargetId; + return this; + } + + /** + * Sets the slice uri. + * + * <p><b>NOTE: </b> If {@link mWidgetId} is also set, {@link mSliceUri} should be ignored. + */ + @NonNull + public Builder setSliceUri(@NonNull Uri sliceUri) { + this.mSliceUri = sliceUri; + return this; + } + + /** + * Sets the widget id. + * + * <p><b>NOTE: </b> If {@link mWidgetId} is set, all other @Nullable params should be + * ignored. + */ + @NonNull + public Builder setWidgetId(@NonNull AppWidgetProviderInfo widgetId) { + this.mWidgetId = widgetId; + return this; + } + + /** + * Builds a new {@link SmartspaceTarget}. + * + * @throws IllegalStateException when non null fields are set as null. + */ + @NonNull + public SmartspaceTarget build() { + if (mSmartspaceTargetId == null + || mComponentName == null + || mUserHandle == null) { + throw new IllegalStateException("Please assign a value to all @NonNull args."); + } + return new SmartspaceTarget(mSmartspaceTargetId, + mHeaderAction, mBaseAction, mCreationTimeMillis, mExpiryTimeMillis, mScore, + mActionChips, mIconGrid, mFeatureType, mSensitive, mShouldShowExpanded, + mSourceNotificationKey, mComponentName, mUserHandle, + mAssociatedSmartspaceTargetId, mSliceUri, mWidgetId); + } + } +} diff --git a/core/java/android/app/smartspace/SmartspaceTargetEvent.aidl b/core/java/android/app/smartspace/SmartspaceTargetEvent.aidl new file mode 100644 index 000000000000..e797a9b7e42c --- /dev/null +++ b/core/java/android/app/smartspace/SmartspaceTargetEvent.aidl @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2021, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.app.smartspace; + +parcelable SmartspaceTargetEvent; diff --git a/core/java/android/app/smartspace/SmartspaceTargetEvent.java b/core/java/android/app/smartspace/SmartspaceTargetEvent.java new file mode 100644 index 000000000000..1e0653d67ace --- /dev/null +++ b/core/java/android/app/smartspace/SmartspaceTargetEvent.java @@ -0,0 +1,204 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.app.smartspace; + +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SystemApi; +import android.os.Parcel; +import android.os.Parcelable; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * A representation of a smartspace event. + * + * @hide + */ +@SystemApi +public final class SmartspaceTargetEvent implements Parcelable { + + /** + * User interacted with the target. + */ + public static final int EVENT_TARGET_INTERACTION = 1; + + /** + * Smartspace target was brought into view. + */ + public static final int EVENT_TARGET_IN_VIEW = 2; + /** + * Smartspace target went out of view. + */ + public static final int EVENT_TARGET_OUT_OF_VIEW = 3; + /** + * A dismiss action was issued by the user. + */ + public static final int EVENT_TARGET_DISMISS = 4; + /** + * A block action was issued by the user. + */ + public static final int EVENT_TARGET_BLOCK = 5; + /** + * The Ui surface came into view. + */ + public static final int EVENT_UI_SURFACE_IN_VIEW = 6; + /** + * The Ui surface went out of view. + */ + public static final int EVENT_UI_SURFACE_OUT_OF_VIEW = 7; + + /** + * @see Parcelable.Creator + */ + @NonNull + public static final Creator<SmartspaceTargetEvent> CREATOR = + new Creator<SmartspaceTargetEvent>() { + public SmartspaceTargetEvent createFromParcel(Parcel parcel) { + return new SmartspaceTargetEvent(parcel); + } + + public SmartspaceTargetEvent[] newArray(int size) { + return new SmartspaceTargetEvent[size]; + } + }; + + @Nullable + private final SmartspaceTarget mSmartspaceTarget; + + @Nullable + private final String mSmartspaceActionId; + + @EventType + private final int mEventType; + + private SmartspaceTargetEvent(@Nullable SmartspaceTarget smartspaceTarget, + @Nullable String smartspaceActionId, + @EventType int eventType) { + mSmartspaceTarget = smartspaceTarget; + mSmartspaceActionId = smartspaceActionId; + mEventType = eventType; + } + + private SmartspaceTargetEvent(Parcel parcel) { + mSmartspaceTarget = parcel.readParcelable(null); + mSmartspaceActionId = parcel.readString(); + mEventType = parcel.readInt(); + } + + /** + * Get the {@link SmartspaceTarget} associated with this event. + */ + @Nullable + public SmartspaceTarget getSmartspaceTarget() { + return mSmartspaceTarget; + } + + /** + * Get the action id of the Smartspace Action associated with this event. + */ + @Nullable + public String getSmartspaceActionId() { + return mSmartspaceActionId; + } + + /** + * Get the {@link EventType} of this event. + */ + @NonNull + @EventType + public int getEventType() { + return mEventType; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeParcelable(mSmartspaceTarget, flags); + dest.writeString(mSmartspaceActionId); + dest.writeInt(mEventType); + } + + /** + * @hide + */ + @IntDef(prefix = {"EVENT_"}, value = { + EVENT_TARGET_INTERACTION, + EVENT_TARGET_IN_VIEW, + EVENT_TARGET_OUT_OF_VIEW, + EVENT_TARGET_DISMISS, + EVENT_TARGET_BLOCK, + EVENT_UI_SURFACE_IN_VIEW, + EVENT_UI_SURFACE_OUT_OF_VIEW + }) + @Retention(RetentionPolicy.SOURCE) + public @interface EventType { + } + + /** + * A builder for {@link SmartspaceTargetEvent}. + * + * @hide + */ + @SystemApi + public static final class Builder { + @EventType + private final int mEventType; + @Nullable + private SmartspaceTarget mSmartspaceTarget; + @Nullable + private String mSmartspaceActionId; + + /** + * A builder for {@link SmartspaceTargetEvent}. + */ + public Builder(@EventType int eventType) { + mEventType = eventType; + } + + /** + * Sets the SmartspaceTarget for this event. + */ + @NonNull + public Builder setSmartspaceTarget(@NonNull SmartspaceTarget smartspaceTarget) { + mSmartspaceTarget = smartspaceTarget; + return this; + } + + /** + * Sets the Smartspace action id for this event. + */ + @NonNull + public Builder setSmartspaceActionId(@NonNull String smartspaceActionId) { + mSmartspaceActionId = smartspaceActionId; + return this; + } + + /** + * Builds a new {@link SmartspaceTargetEvent} instance. + */ + @NonNull + public SmartspaceTargetEvent build() { + return new SmartspaceTargetEvent(mSmartspaceTarget, mSmartspaceActionId, mEventType); + } + } +} diff --git a/core/java/android/appwidget/AppWidgetProviderInfo.java b/core/java/android/appwidget/AppWidgetProviderInfo.java index 93d96d074db8..e96e22c4764a 100644 --- a/core/java/android/appwidget/AppWidgetProviderInfo.java +++ b/core/java/android/appwidget/AppWidgetProviderInfo.java @@ -406,6 +406,14 @@ public class AppWidgetProviderInfo implements Parcelable { return new UserHandle(UserHandle.getUserId(providerInfo.applicationInfo.uid)); } + /** + * Returns the broadcast receiver that is providing this widget. + */ + @NonNull + public ActivityInfo getProviderInfo() { + return providerInfo; + } + @Override @SuppressWarnings("deprecation") public void writeToParcel(Parcel out, int flags) { diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java index d6b38fd32e8f..4fb557780d04 100644 --- a/core/java/android/bluetooth/BluetoothHeadset.java +++ b/core/java/android/bluetooth/BluetoothHeadset.java @@ -80,7 +80,7 @@ public final class BluetoothHeadset implements BluetoothProfile { /** * Intent used to broadcast the change in the Audio Connection state of the - * HDP profile. + * HFP profile. * * <p>This intent will have 3 extras: * <ul> diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 6a2329e5235f..6d42703f2730 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -4371,6 +4371,16 @@ public abstract class Context { public static final String BIOMETRIC_SERVICE = "biometric"; /** + * Use with {@link #getSystemService(String)} to retrieve a + * {@link android.media.MediaCommunicationManager} + * for managing {@link android.media.MediaSession2}. + * + * @see #getSystemService(String) + * @see android.media.MediaCommunicationManager + */ + public static final String MEDIA_COMMUNICATION_SERVICE = "media_communication"; + + /** * Use with {@link #getSystemService} to retrieve a * {@link android.media.MediaRouter} for controlling and managing * routing of media. @@ -4615,6 +4625,18 @@ public abstract class Context { public static final String SEARCH_UI_SERVICE = "search_ui"; /** + * Used for getting the smartspace service. + * + * <p><b>NOTE: </b> this service is optional; callers of + * {@code Context.getSystemServiceName(SMARTSPACE_SERVICE)} should check for {@code null}. + * + * @hide + * @see #getSystemService(String) + */ + @SystemApi + public static final String SMARTSPACE_SERVICE = "smartspace"; + + /** * Use with {@link #getSystemService(String)} to access the * {@link com.android.server.voiceinteraction.SoundTriggerService}. * @@ -6144,6 +6166,7 @@ public abstract class Context { @UiContext @NonNull public Context createWindowContext(@NonNull Display display, @WindowType int type, + @SuppressLint("NullableCollection") @Nullable Bundle options) { throw new RuntimeException("Not implemented. Must override in a subclass."); } diff --git a/core/java/android/content/pm/LauncherActivityInfo.java b/core/java/android/content/pm/LauncherActivityInfo.java index 82d7b6361738..16e720e3794c 100644 --- a/core/java/android/content/pm/LauncherActivityInfo.java +++ b/core/java/android/content/pm/LauncherActivityInfo.java @@ -17,6 +17,7 @@ package android.content.pm; import android.annotation.FloatRange; +import android.annotation.NonNull; import android.content.ComponentName; import android.content.Context; import android.content.pm.PackageManager.NameNotFoundException; @@ -32,8 +33,6 @@ import android.util.DisplayMetrics; * and badged icon for the activity. */ public class LauncherActivityInfo { - private static final String TAG = "LauncherActivityInfo"; - private final PackageManager mPm; private UserHandle mUser; private final LauncherActivityInfoInternal mInternal; @@ -81,7 +80,7 @@ public class LauncherActivityInfo { */ public CharSequence getLabel() { // TODO: Go through LauncherAppsService - return mInternal.getActivityInfo().loadLabel(mPm); + return getActivityInfo().loadLabel(mPm); } /** @@ -101,20 +100,20 @@ public class LauncherActivityInfo { */ public Drawable getIcon(int density) { // TODO: Go through LauncherAppsService - final int iconRes = mInternal.getActivityInfo().getIconResource(); + final int iconRes = getActivityInfo().getIconResource(); Drawable icon = null; // Get the preferred density icon from the app's resources if (density != 0 && iconRes != 0) { try { final Resources resources = mPm.getResourcesForApplication( - mInternal.getActivityInfo().applicationInfo); + getActivityInfo().applicationInfo); icon = resources.getDrawableForDensity(iconRes, density); } catch (NameNotFoundException | Resources.NotFoundException exc) { } } // Get the default density icon if (icon == null) { - icon = mInternal.getActivityInfo().loadIcon(mPm); + icon = getActivityInfo().loadIcon(mPm); } return icon; } @@ -126,25 +125,25 @@ public class LauncherActivityInfo { * @hide remove before shipping */ public int getApplicationFlags() { - return mInternal.getActivityInfo().flags; + return getActivityInfo().flags; } /** * Returns the ActivityInfo of the activity. * * @return Activity Info - * @hide */ + @NonNull public ActivityInfo getActivityInfo() { return mInternal.getActivityInfo(); } /** - * Returns the application info for the appliction this activity belongs to. + * Returns the application info for the application this activity belongs to. * @return */ public ApplicationInfo getApplicationInfo() { - return mInternal.getActivityInfo().applicationInfo; + return getActivityInfo().applicationInfo; } /** @@ -155,7 +154,7 @@ public class LauncherActivityInfo { public long getFirstInstallTime() { try { // TODO: Go through LauncherAppsService - return mPm.getPackageInfo(mInternal.getActivityInfo().packageName, + return mPm.getPackageInfo(getActivityInfo().packageName, PackageManager.MATCH_UNINSTALLED_PACKAGES).firstInstallTime; } catch (NameNotFoundException nnfe) { // Sorry, can't find package @@ -164,11 +163,11 @@ public class LauncherActivityInfo { } /** - * Returns the name for the acitivty from android:name in the manifest. - * @return the name from android:name for the acitivity. + * Returns the name for the activity from android:name in the manifest. + * @return the name from android:name for the activity. */ public String getName() { - return mInternal.getActivityInfo().name; + return getActivityInfo().name; } /** diff --git a/core/java/android/content/pm/PackageInfo.java b/core/java/android/content/pm/PackageInfo.java index f9913067d238..e8ef077fedc8 100644 --- a/core/java/android/content/pm/PackageInfo.java +++ b/core/java/android/content/pm/PackageInfo.java @@ -222,7 +222,7 @@ public class PackageInfo implements Parcelable { * <attribution>} tags included under <manifest>, or null if there were none. This * is only filled if the flag {@link PackageManager#GET_ATTRIBUTIONS} was set. */ - @SuppressWarnings("ArrayReturn") + @SuppressWarnings({"ArrayReturn", "NullableCollection"}) public @Nullable Attribution[] attributions; /** diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 9ae9c25c8c08..9085ed2be8b1 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -54,6 +54,7 @@ import android.content.pm.parsing.ParsingPackageUtils; import android.content.pm.parsing.result.ParseInput; import android.content.pm.parsing.result.ParseResult; import android.content.pm.parsing.result.ParseTypeImpl; +import android.content.res.Configuration; import android.content.res.Resources; import android.content.res.XmlResourceParser; import android.graphics.Rect; @@ -6703,6 +6704,22 @@ public abstract class PackageManager { throws NameNotFoundException; /** + * Retrieve the resources for an application for the provided configuration. + * + * @param app Information about the desired application. + * @param configuration Overridden configuration when loading the Resources + * + * @return Returns the application's Resources. + * @throws NameNotFoundException Thrown if the resources for the given + * application could not be loaded (most likely because it was uninstalled). + */ + @NonNull + public Resources getResourcesForApplication(@NonNull ApplicationInfo app, @Nullable + Configuration configuration) throws NameNotFoundException { + throw new UnsupportedOperationException(); + } + + /** * Retrieve the resources associated with an application. Given the full * package name of an application, retrieves the information about it and * calls getResources() to return its application's resources. If the diff --git a/core/java/android/content/pm/Signature.java b/core/java/android/content/pm/Signature.java index 02fb06b808a2..bce4b872b8a6 100644 --- a/core/java/android/content/pm/Signature.java +++ b/core/java/android/content/pm/Signature.java @@ -256,6 +256,8 @@ public class Signature implements Parcelable { try { if (obj != null) { Signature other = (Signature)obj; + // Note, some classes, such as PackageParser.SigningDetails, rely on equals + // only comparing the mSignature arrays without the flags. return this == other || Arrays.equals(mSignature, other.mSignature); } } catch (ClassCastException e) { @@ -268,6 +270,8 @@ public class Signature implements Parcelable { if (mHaveHashCode) { return mHashCode; } + // Note, similar to equals some classes rely on the hash code not including + // the flags for Set membership checks. mHashCode = Arrays.hashCode(mSignature); mHaveHashCode = true; return mHashCode; diff --git a/core/java/android/hardware/Battery.java b/core/java/android/hardware/Battery.java new file mode 100644 index 000000000000..24c8d76a9813 --- /dev/null +++ b/core/java/android/hardware/Battery.java @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2021 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; + +import android.annotation.FloatRange; +import android.annotation.IntDef; +import android.os.BatteryManager; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * The Battery class is a representation of a single battery on a device. + */ +public abstract class Battery { + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = { "STATUS_" }, value = { + STATUS_UNKNOWN, + STATUS_CHARGING, + STATUS_DISCHARGING, + STATUS_NOT_CHARGING, + STATUS_FULL + }) + public @interface BatteryStatus { + } + + /** Battery status is unknown. */ + public static final int STATUS_UNKNOWN = BatteryManager.BATTERY_STATUS_UNKNOWN; + /** Battery is charging. */ + public static final int STATUS_CHARGING = BatteryManager.BATTERY_STATUS_CHARGING; + /** Battery is discharging. */ + public static final int STATUS_DISCHARGING = BatteryManager.BATTERY_STATUS_DISCHARGING; + /** Battery is connected to power but not charging. */ + public static final int STATUS_NOT_CHARGING = BatteryManager.BATTERY_STATUS_NOT_CHARGING; + /** Battery is full. */ + public static final int STATUS_FULL = BatteryManager.BATTERY_STATUS_FULL; + + /** + * Check whether the hardware has a battery. + * + * @return True if the hardware has a battery, else false. + */ + public abstract boolean hasBattery(); + + /** + * Get the battery status. + * + * @return the battery status. + */ + public abstract @BatteryStatus int getStatus(); + + /** + * Get remaining battery capacity as float percentage [0.0f, 1.0f] of total capacity + * Returns -1 when battery capacity can't be read. + * + * @return the battery capacity. + */ + public abstract @FloatRange(from = -1.0f, to = 1.0f) float getCapacity(); +} diff --git a/core/java/android/hardware/input/IInputManager.aidl b/core/java/android/hardware/input/IInputManager.aidl index b39df4d2b6bf..c69c47f80d01 100644 --- a/core/java/android/hardware/input/IInputManager.aidl +++ b/core/java/android/hardware/input/IInputManager.aidl @@ -93,6 +93,10 @@ interface IInputManager { int[] getVibratorIds(int deviceId); boolean isVibrating(int deviceId); + // Input device battery query. + int getBatteryStatus(int deviceId); + int getBatteryCapacity(int deviceId); + void setPointerIconType(int typeId); void setCustomPointerIcon(in PointerIcon icon); diff --git a/core/java/android/hardware/input/InputDeviceBattery.java b/core/java/android/hardware/input/InputDeviceBattery.java new file mode 100644 index 000000000000..0fe124e2c0ce --- /dev/null +++ b/core/java/android/hardware/input/InputDeviceBattery.java @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2021 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.input; + +import static android.os.BatteryManager.BATTERY_STATUS_UNKNOWN; +import static android.os.IInputConstants.INVALID_BATTERY_CAPACITY; + +import android.hardware.Battery; + +/** + * Battery implementation for input devices. + * + * @hide + */ +public final class InputDeviceBattery extends Battery { + private static final float NULL_BATTERY_CAPACITY = -1.0f; + + private final InputManager mInputManager; + private final int mDeviceId; + private final boolean mHasBattery; + + InputDeviceBattery(InputManager inputManager, int deviceId, boolean hasBattery) { + mInputManager = inputManager; + mDeviceId = deviceId; + mHasBattery = hasBattery; + } + + @Override + public boolean hasBattery() { + return mHasBattery; + } + + @Override + public int getStatus() { + if (!mHasBattery) { + return BATTERY_STATUS_UNKNOWN; + } + return mInputManager.getBatteryStatus(mDeviceId); + } + + @Override + public float getCapacity() { + if (mHasBattery) { + int capacity = mInputManager.getBatteryCapacity(mDeviceId); + if (capacity != INVALID_BATTERY_CAPACITY) { + return (float) capacity / 100.0f; + } + } + return NULL_BATTERY_CAPACITY; + } +} diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java index 6ab11068aac7..185c59d8ccfc 100644 --- a/core/java/android/hardware/input/InputManager.java +++ b/core/java/android/hardware/input/InputManager.java @@ -25,6 +25,7 @@ import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.annotation.SystemService; import android.annotation.TestApi; +import android.app.ActivityThread; import android.compat.annotation.ChangeId; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; @@ -909,18 +910,17 @@ public final class InputManager { } /** - * Returns the maximum allowed obscuring opacity by UID to propagate touches. + * Returns the maximum allowed obscuring opacity per UID to propagate touches. * - * For certain window types (eg. SAWs), the decision of honoring {@link LayoutParams - * #FLAG_NOT_TOUCHABLE} or not depends on the combined obscuring opacity of the windows - * above the touch-consuming window. - * - * @see #setMaximumObscuringOpacityForTouch(Context, float) + * <p>For certain window types (eg. {@link LayoutParams#TYPE_APPLICATION_OVERLAY}), the decision + * of honoring {@link LayoutParams#FLAG_NOT_TOUCHABLE} or not depends on the combined obscuring + * opacity of the windows above the touch-consuming window, per UID. Check documentation of + * {@link LayoutParams#FLAG_NOT_TOUCHABLE} for more details. * - * @hide + * @see LayoutParams#FLAG_NOT_TOUCHABLE */ - @TestApi - public float getMaximumObscuringOpacityForTouch(@NonNull Context context) { + public float getMaximumObscuringOpacityForTouch() { + Context context = ActivityThread.currentApplication(); return Settings.Global.getFloat(context.getContentResolver(), Settings.Global.MAXIMUM_OBSCURING_OPACITY_FOR_TOUCH, DEFAULT_MAXIMUM_OBSCURING_OPACITY_FOR_TOUCH); @@ -946,17 +946,18 @@ public final class InputManager { * * This value should be between 0 (inclusive) and 1 (inclusive). * - * @see #getMaximumObscuringOpacityForTouch(Context) + * @see #getMaximumObscuringOpacityForTouch() * * @hide */ @TestApi @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS) - public void setMaximumObscuringOpacityForTouch(@NonNull Context context, float opacity) { + public void setMaximumObscuringOpacityForTouch(float opacity) { if (opacity < 0 || opacity > 1) { throw new IllegalArgumentException( "Maximum obscuring opacity for touch should be >= 0 and <= 1"); } + Context context = ActivityThread.currentApplication(); Settings.Global.putFloat(context.getContentResolver(), Settings.Global.MAXIMUM_OBSCURING_OPACITY_FOR_TOUCH, opacity); } @@ -1244,6 +1245,32 @@ public final class InputManager { } /** + * Get the battery status of the input device + * @param deviceId The input device ID + * @hide + */ + public int getBatteryStatus(int deviceId) { + try { + return mIm.getBatteryStatus(deviceId); + } catch (RemoteException ex) { + throw ex.rethrowFromSystemServer(); + } + } + + /** + * Get the remaining battery capacity of the input device + * @param deviceId The input device ID + * @hide + */ + public int getBatteryCapacity(int deviceId) { + try { + return mIm.getBatteryCapacity(deviceId); + } catch (RemoteException ex) { + throw ex.rethrowFromSystemServer(); + } + } + + /** * Add a runtime association between the input port and the display port. This overrides any * static associations. * @param inputPort The port of the input device. @@ -1470,6 +1497,15 @@ public final class InputManager { } /** + * Gets a battery object associated with an input device, assuming it has one. + * @return The battery, never null. + * @hide + */ + public InputDeviceBattery getInputDeviceBattery(int deviceId, boolean hasBattery) { + return new InputDeviceBattery(this, deviceId, hasBattery); + } + + /** * Listens for changes in input devices. */ public interface InputDeviceListener { diff --git a/core/java/android/hardware/location/ContextHubClientCallback.java b/core/java/android/hardware/location/ContextHubClientCallback.java index 20fa7538e2d5..b31b85fdabf6 100644 --- a/core/java/android/hardware/location/ContextHubClientCallback.java +++ b/core/java/android/hardware/location/ContextHubClientCallback.java @@ -15,6 +15,7 @@ */ package android.hardware.location; +import android.annotation.NonNull; import android.annotation.SystemApi; import java.util.concurrent.Executor; @@ -101,4 +102,34 @@ public class ContextHubClientCallback { * @param nanoAppId the ID of the nanoapp that had been disabled */ public void onNanoAppDisabled(ContextHubClient client, long nanoAppId) {} + + /** + * Callback invoked when a {@link ContextHubClient}'s authorization to communicate with a + * nanoapp changes. This typically happens as a result of the app that created the + * {@link ContextHubClient} gaining or losing the permissions required to communicate with a + * nanoapp. + * + * An example of the connection callbacks looks like: + * 1) {@link ContextHubClient} sends message to nanoapp and holds required permissions + * 2) {@link ContextHubClient} loses required permissions + * 3) Callback invoked with the nanoapp ID and + * {@link ContextHubManager#AUTHORIZATION_DENIED_GRACE_PERIOD} + * 4) {@link ContextHubClient} performs any cleanup required with the nanoapp + * 5) Callback invoked with the nanoapp ID and {@link ContextHubManager#AUTHORIZATION_DENIED}. + * At this point, any further attempts of communication between the nanoapp and the + * {@link ContextHubClient} will be dropped by the contexthub along with + * {@link ContextHubManager#AUTHORIZATION_DENIED} being sent. The {@link ContextHubClient} + * should assume no communciation can happen again until + * {@link ContextHubManager#AUTHORIZATION_GRANTED} is received. + * + * @param client the client that is associated with this callback + * @param nanoAppId the ID of the nanoapp associated with the new + * authorization state + * @param authorization the authorization state denoting the ability of the + * client to communicate with the nanoapp + */ + public void onClientAuthorizationChanged( + @NonNull ContextHubClient client, + long nanoAppId, + @ContextHubManager.AuthorizationState int authorization) {} } diff --git a/core/java/android/hardware/location/ContextHubIntentEvent.java b/core/java/android/hardware/location/ContextHubIntentEvent.java index 917f62bc6cbf..3e8f4219a485 100644 --- a/core/java/android/hardware/location/ContextHubIntentEvent.java +++ b/core/java/android/hardware/location/ContextHubIntentEvent.java @@ -43,39 +43,45 @@ public class ContextHubIntentEvent { private final int mNanoAppAbortCode; + private final int mClientAuthorizationState; + private ContextHubIntentEvent( @NonNull ContextHubInfo contextHubInfo, @ContextHubManager.Event int eventType, - long nanoAppId, NanoAppMessage nanoAppMessage, int nanoAppAbortCode) { + long nanoAppId, NanoAppMessage nanoAppMessage, int nanoAppAbortCode, + @ContextHubManager.AuthorizationState int clientAuthorizationState) { mContextHubInfo = contextHubInfo; mEventType = eventType; mNanoAppId = nanoAppId; mNanoAppMessage = nanoAppMessage; mNanoAppAbortCode = nanoAppAbortCode; + mClientAuthorizationState = clientAuthorizationState; } private ContextHubIntentEvent( @NonNull ContextHubInfo contextHubInfo, @ContextHubManager.Event int eventType) { this(contextHubInfo, eventType, -1 /* nanoAppId */, null /* nanoAppMessage */, - -1 /* nanoAppAbortCode */); + -1 /* nanoAppAbortCode */, 0 /* clientAuthorizationState */); } private ContextHubIntentEvent( @NonNull ContextHubInfo contextHubInfo, @ContextHubManager.Event int eventType, long nanoAppId) { this(contextHubInfo, eventType, nanoAppId, null /* nanoAppMessage */, - -1 /* nanoAppAbortCode */); + -1 /* nanoAppAbortCode */, 0 /* clientAuthorizationState */); } private ContextHubIntentEvent( @NonNull ContextHubInfo contextHubInfo, @ContextHubManager.Event int eventType, long nanoAppId, @NonNull NanoAppMessage nanoAppMessage) { - this(contextHubInfo, eventType, nanoAppId, nanoAppMessage, -1 /* nanoAppAbortCode */); + this(contextHubInfo, eventType, nanoAppId, nanoAppMessage, -1 /* nanoAppAbortCode */, + 0 /* clientAuthorizationState */); } private ContextHubIntentEvent( @NonNull ContextHubInfo contextHubInfo, @ContextHubManager.Event int eventType, long nanoAppId, int nanoAppAbortCode) { - this(contextHubInfo, eventType, nanoAppId, null /* nanoAppMessage */, nanoAppAbortCode); + this(contextHubInfo, eventType, nanoAppId, null /* nanoAppMessage */, nanoAppAbortCode, + 0 /* clientAuthorizationState */); } /** @@ -105,7 +111,8 @@ public class ContextHubIntentEvent { case ContextHubManager.EVENT_NANOAPP_ENABLED: case ContextHubManager.EVENT_NANOAPP_DISABLED: case ContextHubManager.EVENT_NANOAPP_ABORTED: - case ContextHubManager.EVENT_NANOAPP_MESSAGE: // fall through + case ContextHubManager.EVENT_NANOAPP_MESSAGE: + case ContextHubManager.EVENT_CLIENT_AUTHORIZATION: // fall through long nanoAppId = getLongExtraOrThrow(intent, ContextHubManager.EXTRA_NANOAPP_ID); if (eventType == ContextHubManager.EVENT_NANOAPP_MESSAGE) { hasExtraOrThrow(intent, ContextHubManager.EXTRA_MESSAGE); @@ -120,6 +127,11 @@ public class ContextHubIntentEvent { int nanoAppAbortCode = getIntExtraOrThrow( intent, ContextHubManager.EXTRA_NANOAPP_ABORT_CODE); event = new ContextHubIntentEvent(info, eventType, nanoAppId, nanoAppAbortCode); + } else if (eventType == ContextHubManager.EVENT_CLIENT_AUTHORIZATION) { + int authState = getIntExtraOrThrow( + intent, ContextHubManager.EXTRA_CLIENT_AUTHORIZATION_STATE); + event = new ContextHubIntentEvent(info, eventType, nanoAppId, + null /* nanoAppMessage */, -1 /* nanoAppAbortCode */, authState); } else { event = new ContextHubIntentEvent(info, eventType, nanoAppId); } @@ -192,6 +204,21 @@ public class ContextHubIntentEvent { return mNanoAppMessage; } + /** + * @return the client authorization state + * + * @throws UnsupportedOperationException if this was not a client authorization state event + */ + @ContextHubManager.AuthorizationState + public int getClientAuthorizationState() { + if (mEventType != ContextHubManager.EVENT_CLIENT_AUTHORIZATION) { + throw new UnsupportedOperationException( + "Cannot invoke getClientAuthorizationState() on non-authorization event: " + + mEventType); + } + return mClientAuthorizationState; + } + @NonNull @Override public String toString() { @@ -207,6 +234,9 @@ public class ContextHubIntentEvent { if (mEventType == ContextHubManager.EVENT_NANOAPP_MESSAGE) { out += ", nanoAppMessage = " + mNanoAppMessage; } + if (mEventType == ContextHubManager.EVENT_CLIENT_AUTHORIZATION) { + out += ", clientAuthState = " + mClientAuthorizationState; + } return out + "]"; } @@ -233,6 +263,9 @@ public class ContextHubIntentEvent { if (mEventType == ContextHubManager.EVENT_NANOAPP_MESSAGE) { isEqual &= other.getNanoAppMessage().equals(mNanoAppMessage); } + if (mEventType == ContextHubManager.EVENT_CLIENT_AUTHORIZATION) { + isEqual &= other.getClientAuthorizationState() == mClientAuthorizationState; + } } catch (UnsupportedOperationException e) { isEqual = false; } diff --git a/core/java/android/hardware/location/ContextHubManager.java b/core/java/android/hardware/location/ContextHubManager.java index d44480796d75..ebb3021bf083 100644 --- a/core/java/android/hardware/location/ContextHubManager.java +++ b/core/java/android/hardware/location/ContextHubManager.java @@ -59,6 +59,12 @@ public final class ContextHubManager { private static final String TAG = "ContextHubManager"; /** + * An extra of type int describing the client's authorization state. + */ + public static final String EXTRA_CLIENT_AUTHORIZATION_STATE = + "android.hardware.location.extra.CLIENT_AUTHORIZATION_STATE"; + + /** * An extra of type {@link ContextHubInfo} describing the source of the event. */ public static final String EXTRA_CONTEXT_HUB_INFO = @@ -86,6 +92,42 @@ public final class ContextHubManager { public static final String EXTRA_MESSAGE = "android.hardware.location.extra.MESSAGE"; /** + * Constants describing if a {@link ContextHubClient} and a {@link NanoApp} are authorized to + * communicate. + * + * @hide + */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = { "AUTHORIZATION_" }, value = { + AUTHORIZATION_DENIED, + AUTHORIZATION_DENIED_GRACE_PERIOD, + AUTHORIZATION_GRANTED, + }) + public @interface AuthorizationState { } + + /** + * Indicates that the {@link ContextHubClient} can no longer communicate with a nanoapp. If the + * {@link ContextHubClient} attempts to send messages to the nanoapp, it will continue to + * receive this authorization state if the connection is still closed. + */ + public static final int AUTHORIZATION_DENIED = 0; + + /** + * Indicates the {@link ContextHubClient} will soon lose its authorization to communicate with a + * nanoapp. The {@link ContextHubClient} must perform any cleanup with the nanoapp as soon as + * possible. + * + * Note that the time between this state event and {@link AUTHORIZATION_DENIED} must be enough + * for the {@link ContextHubClient} to send at least one message to the nanoapp. + */ + public static final int AUTHORIZATION_DENIED_GRACE_PERIOD = 1; + + /** + * The {@link ContextHubClient} is authorized to communicate with the nanoapp. + */ + public static final int AUTHORIZATION_GRANTED = 2; + + /** * Constants describing the type of events from a Context Hub. * {@hide} */ @@ -98,6 +140,7 @@ public final class ContextHubManager { EVENT_NANOAPP_ABORTED, EVENT_NANOAPP_MESSAGE, EVENT_HUB_RESET, + EVENT_CLIENT_AUTHORIZATION, }) public @interface Event { } @@ -138,6 +181,14 @@ public final class ContextHubManager { */ public static final int EVENT_HUB_RESET = 6; + /** + * An event describing a client authorization state change. See + * {@link ContextHubClientCallback#onClientAuthorizationChanged} for more details on when this + * event will be sent. Contains the EXTRA_NANOAPP_ID and EXTRA_CLIENT_AUTHORIZATION_STATE + * extras. + */ + public static final int EVENT_CLIENT_AUTHORIZATION = 7; + private final Looper mMainLooper; private final IContextHubService mService; private Callback mCallback; @@ -747,6 +798,14 @@ public final class ContextHubManager { public void onNanoAppDisabled(long nanoAppId) { executor.execute(() -> callback.onNanoAppDisabled(client, nanoAppId)); } + + @Override + public void onClientAuthorizationChanged( + long nanoAppId, @ContextHubManager.AuthorizationState int authorization) { + executor.execute( + () -> callback.onClientAuthorizationChanged( + client, nanoAppId, authorization)); + } }; } @@ -757,9 +816,10 @@ public final class ContextHubManager { * registration succeeds, the client can send messages to nanoapps through the returned * {@link ContextHubClient} object, and receive notifications through the provided callback. * + * @param context the context of the application * @param hubInfo the hub to attach this client to - * @param callback the notification callback to register * @param executor the executor to invoke the callback + * @param callback the notification callback to register * @return the registered client object * * @throws IllegalArgumentException if hubInfo does not represent a valid hub @@ -773,8 +833,9 @@ public final class ContextHubManager { android.Manifest.permission.ACCESS_CONTEXT_HUB }) @NonNull public ContextHubClient createClient( - @NonNull ContextHubInfo hubInfo, @NonNull ContextHubClientCallback callback, - @NonNull @CallbackExecutor Executor executor) { + @Nullable Context context, @NonNull ContextHubInfo hubInfo, + @NonNull @CallbackExecutor Executor executor, + @NonNull ContextHubClientCallback callback) { Objects.requireNonNull(callback, "Callback cannot be null"); Objects.requireNonNull(hubInfo, "ContextHubInfo cannot be null"); Objects.requireNonNull(executor, "Executor cannot be null"); @@ -783,9 +844,14 @@ public final class ContextHubManager { IContextHubClientCallback clientInterface = createClientCallback( client, callback, executor); + String attributionTag = null; + if (context != null) { + attributionTag = context.getAttributionTag(); + } + IContextHubClient clientProxy; try { - clientProxy = mService.createClient(hubInfo.getId(), clientInterface); + clientProxy = mService.createClient(hubInfo.getId(), clientInterface, attributionTag); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -794,19 +860,25 @@ public final class ContextHubManager { return client; } + + /** + * Equivalent to + * {@link #createClient(ContextHubInfo, Executor, String, ContextHubClientCallback)} + * with the {@link Context} being set to null. + */ + @RequiresPermission(anyOf = { + android.Manifest.permission.LOCATION_HARDWARE, + android.Manifest.permission.ACCESS_CONTEXT_HUB + }) + @NonNull public ContextHubClient createClient( + @NonNull ContextHubInfo hubInfo, @NonNull ContextHubClientCallback callback, + @NonNull @CallbackExecutor Executor executor) { + return createClient(null /* context */, hubInfo, executor, callback); + } + /** * Equivalent to {@link #createClient(ContextHubInfo, ContextHubClientCallback, Executor)} * with the executor using the main thread's Looper. - * - * @param hubInfo the hub to attach this client to - * @param callback the notification callback to register - * @return the registered client object - * - * @throws IllegalArgumentException if hubInfo does not represent a valid hub - * @throws IllegalStateException if there were too many registered clients at the service - * @throws NullPointerException if callback or hubInfo is null - * - * @see ContextHubClientCallback */ @RequiresPermission(anyOf = { android.Manifest.permission.LOCATION_HARDWARE, @@ -814,7 +886,8 @@ public final class ContextHubManager { }) @NonNull public ContextHubClient createClient( @NonNull ContextHubInfo hubInfo, @NonNull ContextHubClientCallback callback) { - return createClient(hubInfo, callback, new HandlerExecutor(Handler.getMain())); + return createClient(null /* context */, hubInfo, new HandlerExecutor(Handler.getMain()), + callback); } /** @@ -848,6 +921,8 @@ public final class ContextHubManager { * on the provided PendingIntent, then the client will be automatically unregistered by the * service. * + * @param context the context of the application. If a PendingIntent client is recreated, + * the latest state in the context will be used and old state will be discarded * @param hubInfo the hub to attach this client to * @param pendingIntent the PendingIntent to register to the client * @param nanoAppId the ID of the nanoapp that Intent events will be generated for @@ -862,16 +937,22 @@ public final class ContextHubManager { android.Manifest.permission.ACCESS_CONTEXT_HUB }) @NonNull public ContextHubClient createClient( - @NonNull ContextHubInfo hubInfo, @NonNull PendingIntent pendingIntent, long nanoAppId) { + @Nullable Context context, @NonNull ContextHubInfo hubInfo, + @NonNull PendingIntent pendingIntent, long nanoAppId) { Objects.requireNonNull(pendingIntent); Objects.requireNonNull(hubInfo); ContextHubClient client = new ContextHubClient(hubInfo, true /* persistent */); + String attributionTag = null; + if (context != null) { + attributionTag = context.getAttributionTag(); + } + IContextHubClient clientProxy; try { clientProxy = mService.createPendingIntentClient( - hubInfo.getId(), pendingIntent, nanoAppId); + hubInfo.getId(), pendingIntent, nanoAppId, attributionTag); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -881,6 +962,19 @@ public final class ContextHubManager { } /** + * Equivalent to {@link #createClient(ContextHubInfo, PendingIntent, long, String)} + * with {@link Context} being set to null. + */ + @RequiresPermission(anyOf = { + android.Manifest.permission.LOCATION_HARDWARE, + android.Manifest.permission.ACCESS_CONTEXT_HUB + }) + @NonNull public ContextHubClient createClient( + @NonNull ContextHubInfo hubInfo, @NonNull PendingIntent pendingIntent, long nanoAppId) { + return createClient(null /* context */, hubInfo, pendingIntent, nanoAppId); + } + + /** * Unregister a callback for receive messages from the context hub. * * @see Callback diff --git a/core/java/android/hardware/location/IContextHubClientCallback.aidl b/core/java/android/hardware/location/IContextHubClientCallback.aidl index 1c76bcbe18ce..bcd6b087a276 100644 --- a/core/java/android/hardware/location/IContextHubClientCallback.aidl +++ b/core/java/android/hardware/location/IContextHubClientCallback.aidl @@ -46,4 +46,7 @@ oneway interface IContextHubClientCallback { // Callback invoked when a nanoapp is disabled at the attached Context Hub. void onNanoAppDisabled(long nanoAppId); + + // Callback invoked when the authorization state of a client changes. + void onClientAuthorizationChanged(long nanoAppId, int authorization); } diff --git a/core/java/android/hardware/location/IContextHubService.aidl b/core/java/android/hardware/location/IContextHubService.aidl index 04cc5634bf2c..4961195a3017 100644 --- a/core/java/android/hardware/location/IContextHubService.aidl +++ b/core/java/android/hardware/location/IContextHubService.aidl @@ -59,11 +59,13 @@ interface IContextHubService { int sendMessage(int contextHubHandle, int nanoAppHandle, in ContextHubMessage msg); // Creates a client to send and receive messages - IContextHubClient createClient(int contextHubId, in IContextHubClientCallback client); + IContextHubClient createClient( + int contextHubId, in IContextHubClientCallback client, in String attributionTag); // Creates a PendingIntent-based client to send and receive messages IContextHubClient createPendingIntentClient( - int contextHubId, in PendingIntent pendingIntent, long nanoAppId); + int contextHubId, in PendingIntent pendingIntent, long nanoAppId, + in String attributionTag); // Returns a list of ContextHub objects of available hubs List<ContextHubInfo> getContextHubs(); diff --git a/core/java/android/hardware/location/NanoAppState.java b/core/java/android/hardware/location/NanoAppState.java index 8de7ecd6b2b3..96b1f19a9cd5 100644 --- a/core/java/android/hardware/location/NanoAppState.java +++ b/core/java/android/hardware/location/NanoAppState.java @@ -15,10 +15,14 @@ */ package android.hardware.location; +import android.annotation.NonNull; import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; +import java.util.ArrayList; +import java.util.List; + /** * A class describing the nanoapp state information resulting from a query to a Context Hub. * @@ -29,11 +33,21 @@ public final class NanoAppState implements Parcelable { private long mNanoAppId; private int mNanoAppVersion; private boolean mIsEnabled; + private List<String> mNanoAppPermissions; public NanoAppState(long nanoAppId, int appVersion, boolean enabled) { mNanoAppId = nanoAppId; mNanoAppVersion = appVersion; mIsEnabled = enabled; + mNanoAppPermissions = new ArrayList<String>(); + } + + public NanoAppState(long nanoAppId, int appVersion, boolean enabled, + @NonNull List<String> nanoAppPermissions) { + mNanoAppId = nanoAppId; + mNanoAppVersion = appVersion; + mIsEnabled = enabled; + mNanoAppPermissions = nanoAppPermissions; } /** @@ -57,10 +71,19 @@ public final class NanoAppState implements Parcelable { return mIsEnabled; } + /** + * @return List of Android permissions that are required to communicate with this app. + */ + public @NonNull List<String> getNanoAppPermissions() { + return mNanoAppPermissions; + } + private NanoAppState(Parcel in) { mNanoAppId = in.readLong(); mNanoAppVersion = in.readInt(); mIsEnabled = (in.readInt() == 1); + mNanoAppPermissions = new ArrayList<String>(); + in.readStringList(mNanoAppPermissions); } @Override @@ -73,6 +96,7 @@ public final class NanoAppState implements Parcelable { out.writeLong(mNanoAppId); out.writeInt(mNanoAppVersion); out.writeInt(mIsEnabled ? 1 : 0); + out.writeStringList(mNanoAppPermissions); } public static final @android.annotation.NonNull Creator<NanoAppState> CREATOR = diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java index c28bab7f643f..5bac481fb23e 100644 --- a/core/java/android/hardware/usb/UsbManager.java +++ b/core/java/android/hardware/usb/UsbManager.java @@ -1198,7 +1198,10 @@ public class UsbManager { /** * Returns whether the given functions are valid inputs to UsbManager. - * Currently the empty functions or any of MTP, PTP, RNDIS, MIDI are accepted. + * Currently the empty functions or any of MTP, PTP, RNDIS, MIDI, NCM are accepted. + * + * Only one function may be set at a time, except for RNDIS and NCM, which can be set together + * because from a user perspective they are the same function (tethering). * * @return Whether the mask is settable. * @@ -1206,7 +1209,9 @@ public class UsbManager { */ public static boolean areSettableFunctions(long functions) { return functions == FUNCTION_NONE - || ((~SETTABLE_FUNCTIONS & functions) == 0 && Long.bitCount(functions) == 1); + || ((~SETTABLE_FUNCTIONS & functions) == 0 + && ((Long.bitCount(functions) == 1) + || (functions == (FUNCTION_RNDIS | FUNCTION_NCM)))); } /** diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index 60923f5ea8c6..70bca3019818 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -707,7 +707,7 @@ public final class IpSecManager { } /** - * This class represents an IpSecTunnelInterface. + * This class represents an IpSecTunnelInterface * * <p>IpSecTunnelInterface objects track tunnel interfaces that serve as * local endpoints for IPsec tunnels. @@ -716,7 +716,9 @@ public final class IpSecManager { * applied to provide IPsec security to packets sent through the tunnel. While a tunnel * cannot be used in standalone mode within Android, the higher layers may use the tunnel * to create Network objects which are accessible to the Android system. + * @hide */ + @SystemApi public static final class IpSecTunnelInterface implements AutoCloseable { private final String mOpPackageName; private final IIpSecService mService; @@ -727,26 +729,23 @@ public final class IpSecManager { private String mInterfaceName; private int mResourceId = INVALID_RESOURCE_ID; - /** - * Get the underlying SPI held by this object. - * - * @hide - */ - @SystemApi + /** Get the underlying SPI held by this object. */ @NonNull public String getInterfaceName() { return mInterfaceName; } /** - * Add an address to the IpSecTunnelInterface. + * Add an address to the IpSecTunnelInterface * * <p>Add an address which may be used as the local inner address for * tunneled traffic. * * @param address the local address for traffic inside the tunnel * @param prefixLen length of the InetAddress prefix + * @hide */ + @SystemApi @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS) @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public void addAddress(@NonNull InetAddress address, int prefixLen) throws IOException { @@ -761,13 +760,15 @@ public final class IpSecManager { } /** - * Remove an address from the IpSecTunnelInterface. + * Remove an address from the IpSecTunnelInterface * - * <p>Remove an address which was previously added to the IpSecTunnelInterface. + * <p>Remove an address which was previously added to the IpSecTunnelInterface * * @param address to be removed * @param prefixLen length of the InetAddress prefix + * @hide */ + @SystemApi @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS) @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public void removeAddress(@NonNull InetAddress address, int prefixLen) throws IOException { @@ -818,7 +819,7 @@ public final class IpSecManager { } /** - * Delete an IpSecTunnelInterface. + * Delete an IpSecTunnelInterface * * <p>Calling close will deallocate the IpSecTunnelInterface and all of its system * resources. Any packets bound for this interface either inbound or outbound will @@ -840,12 +841,7 @@ public final class IpSecManager { } } - - /** - * Check that the Interface was closed properly. - * - * @hide - */ + /** Check that the Interface was closed properly. */ @Override protected void finalize() throws Throwable { if (mCloseGuard != null) { @@ -877,52 +873,17 @@ public final class IpSecManager { * Create a new IpSecTunnelInterface as a local endpoint for tunneled IPsec traffic. * * <p>An application that creates tunnels is responsible for cleaning up the tunnel when the - * underlying network disconnects, and the {@link - * ConnectivityManager.NetworkCallback#onLost(Network)} callback is received. - * - * @param underlyingNetwork the {@link Network} that will carry traffic for this tunnel. Packets - * that go through the tunnel will need a underlying network to transit to the IPsec peer. - * This network should almost certainly be a physical network such as WiFi. - * @return a new {@link IpSecTunnelInterface} with the specified properties - * @throws IOException indicating that the tunnel could not be created due to a lower-layer - * error - * @throws ResourceUnavailableException indicating that the number of opening tunnels has - * reached the limit. - */ - @NonNull - @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS) - @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) - public IpSecTunnelInterface createIpSecTunnelInterface(@NonNull Network underlyingNetwork) - throws ResourceUnavailableException, IOException { - - // TODO: Remove the need for adding two unused addresses with IPsec tunnels when {@link - // #createIpSecTunnelInterface(localAddress, remoteAddress, underlyingNetwork)} can be - // safely removed. - final InetAddress address = InetAddress.getLocalHost(); - return createIpSecTunnelInterface(address, address, underlyingNetwork); - } - - /** - * Create a new IpSecTunnelInterface as a local endpoint for tunneled IPsec traffic. + * underlying network goes away, and the onLost() callback is received. * - * <p>An application that creates tunnels is responsible for cleaning up the tunnel when the - * underlying network disconnects, and the {@link - * ConnectivityManager.NetworkCallback#onLost(Network)} callback is received. - * - * @param localAddress The local address of the tunnel - * @param remoteAddress The local address of the tunnel - * @param underlyingNetwork the {@link Network} that will carry traffic for this tunnel. Packets - * that go through the tunnel will need a underlying network to transit to the IPsec peer. - * This network should almost certainly be a physical network such as WiFi. - * @return a new {@link IpSecTunnelInterface} with the specified properties - * @throws IOException indicating that the tunnel could not be created due to a lower-layer - * error - * @throws ResourceUnavailableException indicating that the number of opening tunnels has - * reached the limit. + * @param localAddress The local addres of the tunnel + * @param remoteAddress The local addres of the tunnel + * @param underlyingNetwork the {@link Network} that will carry traffic for this tunnel. + * This network should almost certainly be a network such as WiFi with an L2 address. + * @return a new {@link IpSecManager#IpSecTunnelInterface} with the specified properties + * @throws IOException indicating that the socket could not be opened or bound + * @throws ResourceUnavailableException indicating that too many encapsulation sockets are open * @hide - * @deprecated Callers should use {@link #createIpSecTunnelInterface(Network)} */ - @Deprecated @SystemApi @NonNull @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS) @@ -946,14 +907,16 @@ public final class IpSecManager { * <p>Applications should probably not use this API directly. * * - * @param tunnel The {@link IpSecTunnelInterface} that will use the supplied + * @param tunnel The {@link IpSecManager#IpSecTunnelInterface} that will use the supplied * transform. - * @param direction the direction, {@link #DIRECTION_OUT} or {@link #DIRECTION_IN} in which + * @param direction the direction, {@link DIRECTION_OUT} or {@link #DIRECTION_IN} in which * the transform will be used. * @param transform an {@link IpSecTransform} created in tunnel mode - * @throws IOException indicating that the transform could not be applied due to a lower-layer - * error + * @throws IOException indicating that the transform could not be applied due to a lower + * layer failure. + * @hide */ + @SystemApi @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS) @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public void applyTunnelModeTransform(@NonNull IpSecTunnelInterface tunnel, diff --git a/core/java/android/net/NetworkState.java b/core/java/android/net/NetworkState.java index 713b6888376e..e1ef8b5ea5c9 100644 --- a/core/java/android/net/NetworkState.java +++ b/core/java/android/net/NetworkState.java @@ -16,6 +16,7 @@ package android.net; +import android.annotation.NonNull; import android.compat.annotation.UnsupportedAppUsage; import android.os.Build; import android.os.Parcel; @@ -30,7 +31,8 @@ import android.util.Slog; public class NetworkState implements Parcelable { private static final boolean VALIDATE_ROAMING_STATE = false; - public static final NetworkState EMPTY = new NetworkState(null, null, null, null, null, null); + // TODO: remove and make members @NonNull. + public static final NetworkState EMPTY = new NetworkState(); public final NetworkInfo networkInfo; public final LinkProperties linkProperties; @@ -40,9 +42,18 @@ public class NetworkState implements Parcelable { public final String subscriberId; public final String networkId; - public NetworkState(NetworkInfo networkInfo, LinkProperties linkProperties, - NetworkCapabilities networkCapabilities, Network network, String subscriberId, - String networkId) { + private NetworkState() { + networkInfo = null; + linkProperties = null; + networkCapabilities = null; + network = null; + subscriberId = null; + networkId = null; + } + + public NetworkState(@NonNull NetworkInfo networkInfo, @NonNull LinkProperties linkProperties, + @NonNull NetworkCapabilities networkCapabilities, @NonNull Network network, + String subscriberId, String networkId) { this.networkInfo = networkInfo; this.linkProperties = linkProperties; this.networkCapabilities = networkCapabilities; diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java index 9a102a7c4b00..059e932a9da9 100644 --- a/core/java/android/os/PowerManager.java +++ b/core/java/android/os/PowerManager.java @@ -416,9 +416,21 @@ public final class PowerManager { public static final int GO_TO_SLEEP_REASON_QUIESCENT = 10; /** + * Go to sleep reason code: The last powered on display group has been removed. * @hide */ - public static final int GO_TO_SLEEP_REASON_MAX = GO_TO_SLEEP_REASON_QUIESCENT; + public static final int GO_TO_SLEEP_REASON_DISPLAY_GROUP_REMOVED = 11; + + /** + * Go to sleep reason code: Every display group has been turned off. + * @hide + */ + public static final int GO_TO_SLEEP_REASON_DISPLAY_GROUPS_TURNED_OFF = 12; + + /** + * @hide + */ + public static final int GO_TO_SLEEP_REASON_MAX = GO_TO_SLEEP_REASON_DISPLAY_GROUPS_TURNED_OFF; /** * @hide @@ -435,6 +447,8 @@ public final class PowerManager { case GO_TO_SLEEP_REASON_ACCESSIBILITY: return "accessibility"; case GO_TO_SLEEP_REASON_FORCE_SUSPEND: return "force_suspend"; case GO_TO_SLEEP_REASON_INATTENTIVE: return "inattentive"; + case GO_TO_SLEEP_REASON_DISPLAY_GROUP_REMOVED: return "display_group_removed"; + case GO_TO_SLEEP_REASON_DISPLAY_GROUPS_TURNED_OFF: return "display_groups_turned_off"; default: return Integer.toString(sleepReason); } } @@ -521,6 +535,8 @@ public final class PowerManager { WAKE_REASON_WAKE_KEY, WAKE_REASON_WAKE_MOTION, WAKE_REASON_HDMI, + WAKE_REASON_DISPLAY_GROUP_ADDED, + WAKE_REASON_DISPLAY_GROUP_TURNED_ON, }) @Retention(RetentionPolicy.SOURCE) public @interface WakeReason{} @@ -608,6 +624,18 @@ public final class PowerManager { public static final int WAKE_REASON_LID = 9; /** + * Wake up reason code: Waking due to display group being added. + * @hide + */ + public static final int WAKE_REASON_DISPLAY_GROUP_ADDED = 10; + + /** + * Wake up reason code: Waking due to display group being powered on. + * @hide + */ + public static final int WAKE_REASON_DISPLAY_GROUP_TURNED_ON = 11; + + /** * Convert the wake reason to a string for debugging purposes. * @hide */ @@ -623,6 +651,8 @@ public final class PowerManager { case WAKE_REASON_WAKE_MOTION: return "WAKE_REASON_WAKE_MOTION"; case WAKE_REASON_HDMI: return "WAKE_REASON_HDMI"; case WAKE_REASON_LID: return "WAKE_REASON_LID"; + case WAKE_REASON_DISPLAY_GROUP_ADDED: return "WAKE_REASON_DISPLAY_GROUP_ADDED"; + case WAKE_REASON_DISPLAY_GROUP_TURNED_ON: return "WAKE_REASON_DISPLAY_GROUP_TURNED_ON"; default: return Integer.toString(wakeReason); } } @@ -1253,8 +1283,15 @@ public final class PowerManager { } } - /** - * Forces the device to go to sleep. + /** + * Forces the {@link com.android.server.display.DisplayGroup#DEFAULT default display group} + * to turn off. + * + * <p>If the {@link com.android.server.display.DisplayGroup#DEFAULT default display group} is + * turned on it will be turned off. If all displays are off as a result of this action the + * device will be put to sleep. If the {@link com.android.server.display.DisplayGroup#DEFAULT + * default display group} is already off then nothing will happen. + * * <p> * Overrides all the wake locks that are held. * This is what happens when the power key is pressed to turn off the screen. @@ -1277,7 +1314,14 @@ public final class PowerManager { } /** - * Forces the device to go to sleep. + * Forces the {@link com.android.server.display.DisplayGroup#DEFAULT default display group} + * to turn off. + * + * <p>If the {@link com.android.server.display.DisplayGroup#DEFAULT default display group} is + * turned on it will be turned off. If all displays are off as a result of this action the + * device will be put to sleep. If the {@link com.android.server.display.DisplayGroup#DEFAULT + * default display group} is already off then nothing will happen. + * * <p> * Overrides all the wake locks that are held. * This is what happens when the power key is pressed to turn off the screen. @@ -1307,9 +1351,15 @@ public final class PowerManager { } /** - * Forces the device to wake up from sleep. + * Forces the {@link com.android.server.display.DisplayGroup#DEFAULT default display group} + * to turn on. + * + * <p>If the {@link com.android.server.display.DisplayGroup#DEFAULT default display group} is + * turned off it will be turned on. Additionally, if the device is asleep it will be awoken. If + * the {@link com.android.server.display.DisplayGroup#DEFAULT default display group} is already + * on then nothing will happen. + * * <p> - * If the device is currently asleep, wakes it up, otherwise does nothing. * This is what happens when the power key is pressed to turn on the screen. * </p><p> * Requires the {@link android.Manifest.permission#DEVICE_POWER} permission. @@ -1332,9 +1382,15 @@ public final class PowerManager { } /** - * Forces the device to wake up from sleep. + * Forces the {@link com.android.server.display.DisplayGroup#DEFAULT default display group} + * to turn on. + * + * <p>If the {@link com.android.server.display.DisplayGroup#DEFAULT default display group} is + * turned off it will be turned on. Additionally, if the device is asleep it will be awoken. If + * the {@link com.android.server.display.DisplayGroup#DEFAULT default display group} is already + * on then nothing will happen. + * * <p> - * If the device is currently asleep, wakes it up, otherwise does nothing. * This is what happens when the power key is pressed to turn on the screen. * </p><p> * Requires the {@link android.Manifest.permission#DEVICE_POWER} permission. @@ -1361,9 +1417,13 @@ public final class PowerManager { } /** - * Forces the device to wake up from sleep. + * Forces the {@link android.view.Display#DEFAULT_DISPLAY default display} to turn on. + * + * <p>If the {@link android.view.Display#DEFAULT_DISPLAY default display} is turned off it will + * be turned on. Additionally, if the device is asleep it will be awoken. If the {@link + * android.view.Display#DEFAULT_DISPLAY default display} is already on then nothing will happen. + * * <p> - * If the device is currently asleep, wakes it up, otherwise does nothing. * This is what happens when the power key is pressed to turn on the screen. * </p><p> * Requires the {@link android.Manifest.permission#DEVICE_POWER} permission. diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java index a29b4b9adbb2..91e091c50532 100644 --- a/core/java/android/provider/DeviceConfig.java +++ b/core/java/android/provider/DeviceConfig.java @@ -368,6 +368,14 @@ public final class DeviceConfig { public static final String NAMESPACE_SYSTEMUI = "systemui"; /** + * Namespace for system time and time zone detection related features / behavior. + * + * @hide + */ + @SystemApi + public static final String NAMESPACE_SYSTEM_TIME = "system_time"; + + /** * Telephony related properties. * * @hide diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 79f055e882aa..f6ef8a3d8dae 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -13393,6 +13393,24 @@ public final class Settings { "euicc_factory_reset_timeout_millis"; /** + * Flag to set the waiting time for euicc slot switch. + * Type: long + * + * @hide + */ + public static final String EUICC_SWITCH_SLOT_TIMEOUT_MILLIS = + "euicc_switch_slot_timeout_millis"; + + /** + * Flag to set the waiting time for enabling multi SIM slot. + * Type: long + * + * @hide + */ + public static final String ENABLE_MULTI_SLOT_TIMEOUT_MILLIS = + "enable_multi_slot_timeout_millis"; + + /** * Flag to set the timeout for when to refresh the storage settings cached data. * Type: long * @@ -14721,9 +14739,8 @@ public final class Settings { * touch, allow the UID to propagate the touch. * </ul> * - * @see android.hardware.input.InputManager#getMaximumObscuringOpacityForTouch(Context) - * @see android.hardware.input.InputManager#setMaximumObscuringOpacityForTouch(Context, - * float) + * @see android.hardware.input.InputManager#getMaximumObscuringOpacityForTouch() + * @see android.hardware.input.InputManager#setMaximumObscuringOpacityForTouch(float) * * @hide */ diff --git a/core/java/android/service/autofill/Dataset.java b/core/java/android/service/autofill/Dataset.java index 4679c56de612..e3d0741b4603 100644 --- a/core/java/android/service/autofill/Dataset.java +++ b/core/java/android/service/autofill/Dataset.java @@ -129,14 +129,14 @@ public final class Dataset implements Parcelable { /** @hide */ @TestApi - @SuppressLint("ConcreteCollection") + @SuppressLint({"ConcreteCollection", "NullableCollection"}) public @Nullable ArrayList<AutofillId> getFieldIds() { return mFieldIds; } /** @hide */ @TestApi - @SuppressLint("ConcreteCollection") + @SuppressLint({"ConcreteCollection", "NullableCollection"}) public @Nullable ArrayList<AutofillValue> getFieldValues() { return mFieldValues; } diff --git a/core/java/android/service/dataloader/OWNERS b/core/java/android/service/dataloader/OWNERS new file mode 100644 index 000000000000..7f3906baed2e --- /dev/null +++ b/core/java/android/service/dataloader/OWNERS @@ -0,0 +1 @@ +include /core/java/android/os/incremental/OWNERS
\ No newline at end of file diff --git a/core/java/android/service/notification/INotificationListener.aidl b/core/java/android/service/notification/INotificationListener.aidl index e0f3018e3d0e..44daeff76997 100644 --- a/core/java/android/service/notification/INotificationListener.aidl +++ b/core/java/android/service/notification/INotificationListener.aidl @@ -46,7 +46,7 @@ oneway interface INotificationListener void onNotificationChannelGroupModification(String pkgName, in UserHandle user, in NotificationChannelGroup group, int modificationType); // assistants only - void onNotificationEnqueuedWithChannel(in IStatusBarNotificationHolder notificationHolder, in NotificationChannel channel); + void onNotificationEnqueuedWithChannel(in IStatusBarNotificationHolder notificationHolder, in NotificationChannel channel, in NotificationRankingUpdate update); void onNotificationSnoozedUntilContext(in IStatusBarNotificationHolder notificationHolder, String snoozeCriterionId); void onNotificationsSeen(in List<String> keys); void onPanelRevealed(int items); diff --git a/core/java/android/service/notification/NotificationAssistantService.java b/core/java/android/service/notification/NotificationAssistantService.java index cf2152cc3ad4..1d49a7206023 100644 --- a/core/java/android/service/notification/NotificationAssistantService.java +++ b/core/java/android/service/notification/NotificationAssistantService.java @@ -126,7 +126,7 @@ public abstract class NotificationAssistantService extends NotificationListenerS * {@link #onNotificationEnqueued(StatusBarNotification, NotificationChannel)}.</p> * * @param sbn the new notification - * @return an adjustment or null to take no action, within 100ms. + * @return an adjustment or null to take no action, within 200ms. */ abstract public @Nullable Adjustment onNotificationEnqueued(@NonNull StatusBarNotification sbn); @@ -135,7 +135,7 @@ public abstract class NotificationAssistantService extends NotificationListenerS * * @param sbn the new notification * @param channel the channel the notification was posted to - * @return an adjustment or null to take no action, within 100ms. + * @return an adjustment or null to take no action, within 200ms. */ public @Nullable Adjustment onNotificationEnqueued(@NonNull StatusBarNotification sbn, @NonNull NotificationChannel channel) { @@ -143,6 +143,20 @@ public abstract class NotificationAssistantService extends NotificationListenerS } /** + * A notification was posted by an app. Called before post. + * + * @param sbn the new notification + * @param channel the channel the notification was posted to + * @param rankingMap The current ranking map that can be used to retrieve ranking information + * for active notifications. + * @return an adjustment or null to take no action, within 200ms. + */ + public @Nullable Adjustment onNotificationEnqueued(@NonNull StatusBarNotification sbn, + @NonNull NotificationChannel channel, @NonNull RankingMap rankingMap) { + return onNotificationEnqueued(sbn, channel); + } + + /** * Implement this method to learn when notifications are removed, how they were interacted with * before removal, and why they were removed. * <p> @@ -316,7 +330,7 @@ public abstract class NotificationAssistantService extends NotificationListenerS private class NotificationAssistantServiceWrapper extends NotificationListenerWrapper { @Override public void onNotificationEnqueuedWithChannel(IStatusBarNotificationHolder sbnHolder, - NotificationChannel channel) { + NotificationChannel channel, NotificationRankingUpdate update) { StatusBarNotification sbn; try { sbn = sbnHolder.get(); @@ -330,9 +344,11 @@ public abstract class NotificationAssistantService extends NotificationListenerS return; } + applyUpdateLocked(update); SomeArgs args = SomeArgs.obtain(); args.arg1 = sbn; args.arg2 = channel; + args.arg3 = getCurrentRanking(); mHandler.obtainMessage(MyHandler.MSG_ON_NOTIFICATION_ENQUEUED, args).sendToTarget(); } @@ -472,8 +488,9 @@ public abstract class NotificationAssistantService extends NotificationListenerS SomeArgs args = (SomeArgs) msg.obj; StatusBarNotification sbn = (StatusBarNotification) args.arg1; NotificationChannel channel = (NotificationChannel) args.arg2; + RankingMap ranking = (RankingMap) args.arg3; args.recycle(); - Adjustment adjustment = onNotificationEnqueued(sbn, channel); + Adjustment adjustment = onNotificationEnqueued(sbn, channel, ranking); setAdjustmentIssuer(adjustment); if (adjustment != null) { if (!isBound()) { diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java index c41e599d5cae..64cddc35d2bb 100644 --- a/core/java/android/service/notification/NotificationListenerService.java +++ b/core/java/android/service/notification/NotificationListenerService.java @@ -1431,7 +1431,8 @@ public abstract class NotificationListenerService extends Service { @Override public void onNotificationEnqueuedWithChannel( - IStatusBarNotificationHolder notificationHolder, NotificationChannel channel) + IStatusBarNotificationHolder notificationHolder, NotificationChannel channel, + NotificationRankingUpdate update) throws RemoteException { // no-op in the listener } diff --git a/core/java/android/service/smartspace/ISmartspaceService.aidl b/core/java/android/service/smartspace/ISmartspaceService.aidl new file mode 100644 index 000000000000..c9c6807058af --- /dev/null +++ b/core/java/android/service/smartspace/ISmartspaceService.aidl @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2021 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.service.smartspace; + +import android.app.smartspace.SmartspaceTarget; +import android.app.smartspace.SmartspaceTargetEvent; +import android.app.smartspace.SmartspaceSessionId; +import android.app.smartspace.SmartspaceConfig; +import android.app.smartspace.ISmartspaceCallback; +import android.content.pm.ParceledListSlice; + +/** + * Interface from the system to Smartspace service. + * + * @hide + */ +oneway interface ISmartspaceService { + + void onCreateSmartspaceSession(in SmartspaceConfig context, in SmartspaceSessionId sessionId); + + void notifySmartspaceEvent(in SmartspaceSessionId sessionId, in SmartspaceTargetEvent event); + + void requestSmartspaceUpdate(in SmartspaceSessionId sessionId); + + void registerSmartspaceUpdates(in SmartspaceSessionId sessionId, + in ISmartspaceCallback callback); + + void unregisterSmartspaceUpdates(in SmartspaceSessionId sessionId, + in ISmartspaceCallback callback); + + void onDestroySmartspaceSession(in SmartspaceSessionId sessionId); +} diff --git a/core/java/android/service/smartspace/SmartspaceService.java b/core/java/android/service/smartspace/SmartspaceService.java new file mode 100644 index 000000000000..09b731091bfd --- /dev/null +++ b/core/java/android/service/smartspace/SmartspaceService.java @@ -0,0 +1,313 @@ +/* + * Copyright (C) 2021 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.service.smartspace; + +import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage; + +import android.annotation.CallSuper; +import android.annotation.MainThread; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SystemApi; +import android.app.Service; +import android.app.smartspace.ISmartspaceCallback; +import android.app.smartspace.SmartspaceConfig; +import android.app.smartspace.SmartspaceSessionId; +import android.app.smartspace.SmartspaceTarget; +import android.app.smartspace.SmartspaceTargetEvent; +import android.content.Intent; +import android.content.pm.ParceledListSlice; +import android.os.Handler; +import android.os.IBinder; +import android.os.Looper; +import android.os.RemoteException; +import android.service.smartspace.ISmartspaceService.Stub; +import android.util.ArrayMap; +import android.util.Log; +import android.util.Slog; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; + +/** + * A service used to share the lifecycle of smartspace UI (open, close, interaction) + * and also to return smartspace result on a query. + * + * @hide + */ +@SystemApi +public abstract class SmartspaceService extends Service { + + /** + * The {@link Intent} that must be declared as handled by the service. + * + * <p>The service must also require the {@link android.permission#MANAGE_SMARTSPACE} + * permission. + * + * @hide + */ + public static final String SERVICE_INTERFACE = + "android.service.smartspace.SmartspaceService"; + private static final boolean DEBUG = false; + private static final String TAG = "SmartspaceService"; + private final ArrayMap<SmartspaceSessionId, ArrayList<CallbackWrapper>> mSessionCallbacks = + new ArrayMap<>(); + private Handler mHandler; + + private final android.service.smartspace.ISmartspaceService mInterface = new Stub() { + + @Override + public void onCreateSmartspaceSession(SmartspaceConfig smartspaceConfig, + SmartspaceSessionId sessionId) { + mHandler.sendMessage( + obtainMessage(SmartspaceService::doCreateSmartspaceSession, + SmartspaceService.this, smartspaceConfig, sessionId)); + } + + @Override + public void notifySmartspaceEvent(SmartspaceSessionId sessionId, + SmartspaceTargetEvent event) { + mHandler.sendMessage( + obtainMessage(SmartspaceService::notifySmartspaceEvent, + SmartspaceService.this, sessionId, event)); + } + + @Override + public void requestSmartspaceUpdate(SmartspaceSessionId sessionId) { + mHandler.sendMessage( + obtainMessage(SmartspaceService::doRequestPredictionUpdate, + SmartspaceService.this, sessionId)); + } + + @Override + public void registerSmartspaceUpdates(SmartspaceSessionId sessionId, + ISmartspaceCallback callback) { + mHandler.sendMessage( + obtainMessage(SmartspaceService::doRegisterSmartspaceUpdates, + SmartspaceService.this, sessionId, callback)); + } + + @Override + public void unregisterSmartspaceUpdates(SmartspaceSessionId sessionId, + ISmartspaceCallback callback) { + mHandler.sendMessage( + obtainMessage(SmartspaceService::doUnregisterSmartspaceUpdates, + SmartspaceService.this, sessionId, callback)); + } + + @Override + public void onDestroySmartspaceSession(SmartspaceSessionId sessionId) { + + mHandler.sendMessage( + obtainMessage(SmartspaceService::doDestroy, + SmartspaceService.this, sessionId)); + } + }; + + @CallSuper + @Override + public void onCreate() { + super.onCreate(); + Log.d(TAG, "onCreate mSessionCallbacks: " + mSessionCallbacks); + mHandler = new Handler(Looper.getMainLooper(), null, true); + } + + @Override + @NonNull + public final IBinder onBind(@NonNull Intent intent) { + Log.d(TAG, "onBind mSessionCallbacks: " + mSessionCallbacks); + if (SERVICE_INTERFACE.equals(intent.getAction())) { + return mInterface.asBinder(); + } + Slog.w(TAG, "Tried to bind to wrong intent (should be " + + SERVICE_INTERFACE + ": " + intent); + return null; + } + + private void doCreateSmartspaceSession(@NonNull SmartspaceConfig config, + @NonNull SmartspaceSessionId sessionId) { + Log.d(TAG, "doCreateSmartspaceSession mSessionCallbacks: " + mSessionCallbacks); + mSessionCallbacks.put(sessionId, new ArrayList<>()); + onCreateSmartspaceSession(config, sessionId); + } + + /** + * Gets called when the client calls <code> SmartspaceManager#createSmartspaceSession </code>. + */ + public abstract void onCreateSmartspaceSession(@NonNull SmartspaceConfig config, + @NonNull SmartspaceSessionId sessionId); + + /** + * Gets called when the client calls <code> SmartspaceSession#notifySmartspaceEvent </code>. + */ + @MainThread + public abstract void notifySmartspaceEvent(@NonNull SmartspaceSessionId sessionId, + @NonNull SmartspaceTargetEvent event); + + /** + * Gets called when the client calls <code> SmartspaceSession#requestSmartspaceUpdate </code>. + */ + @MainThread + public abstract void onRequestSmartspaceUpdate(@NonNull SmartspaceSessionId sessionId); + + private void doRegisterSmartspaceUpdates(@NonNull SmartspaceSessionId sessionId, + @NonNull ISmartspaceCallback callback) { + Log.d(TAG, "doRegisterSmartspaceUpdates mSessionCallbacks: " + mSessionCallbacks); + final ArrayList<CallbackWrapper> callbacks = mSessionCallbacks.get(sessionId); + if (callbacks == null) { + Slog.e(TAG, "Failed to register for updates for unknown session: " + sessionId); + return; + } + + final CallbackWrapper wrapper = findCallbackWrapper(callbacks, callback); + if (wrapper == null) { + callbacks.add(new CallbackWrapper(callback, + callbackWrapper -> + mHandler.post( + () -> removeCallbackWrapper(callbacks, callbackWrapper)))); + } + } + + private void doUnregisterSmartspaceUpdates(@NonNull SmartspaceSessionId sessionId, + @NonNull ISmartspaceCallback callback) { + Log.d(TAG, "doUnregisterSmartspaceUpdates mSessionCallbacks: " + mSessionCallbacks); + final ArrayList<CallbackWrapper> callbacks = mSessionCallbacks.get(sessionId); + if (callbacks == null) { + Slog.e(TAG, "Failed to unregister for updates for unknown session: " + sessionId); + return; + } + + final CallbackWrapper wrapper = findCallbackWrapper(callbacks, callback); + if (wrapper != null) { + removeCallbackWrapper(callbacks, wrapper); + } + } + + private void doRequestPredictionUpdate(@NonNull SmartspaceSessionId sessionId) { + Log.d(TAG, "doRequestPredictionUpdate mSessionCallbacks: " + mSessionCallbacks); + // Just an optimization, if there are no callbacks, then don't bother notifying the service + final ArrayList<CallbackWrapper> callbacks = mSessionCallbacks.get(sessionId); + if (callbacks != null && !callbacks.isEmpty()) { + onRequestSmartspaceUpdate(sessionId); + } + } + + /** + * Finds the callback wrapper for the given callback. + */ + private CallbackWrapper findCallbackWrapper(ArrayList<CallbackWrapper> callbacks, + ISmartspaceCallback callback) { + for (int i = callbacks.size() - 1; i >= 0; i--) { + if (callbacks.get(i).isCallback(callback)) { + return callbacks.get(i); + } + } + return null; + } + + private void removeCallbackWrapper( + ArrayList<CallbackWrapper> callbacks, CallbackWrapper wrapper) { + if (callbacks == null) { + return; + } + callbacks.remove(wrapper); + } + + /** + * Gets called when the client calls <code> SmartspaceManager#destroy() </code>. + */ + public abstract void onDestroySmartspaceSession(@NonNull SmartspaceSessionId sessionId); + + private void doDestroy(@NonNull SmartspaceSessionId sessionId) { + Log.d(TAG, "doDestroy mSessionCallbacks: " + mSessionCallbacks); + super.onDestroy(); + mSessionCallbacks.remove(sessionId); + onDestroySmartspaceSession(sessionId); + } + + /** + * Used by the prediction factory to send back results the client app. The can be called + * in response to {@link #onRequestSmartspaceUpdate(SmartspaceSessionId)} or proactively as + * a result of changes in predictions. + */ + public final void updateSmartspaceTargets(@NonNull SmartspaceSessionId sessionId, + @NonNull List<SmartspaceTarget> targets) { + Log.d(TAG, "updateSmartspaceTargets mSessionCallbacks: " + mSessionCallbacks); + List<CallbackWrapper> callbacks = mSessionCallbacks.get(sessionId); + if (callbacks != null) { + for (CallbackWrapper callback : callbacks) { + callback.accept(targets); + } + } + } + + /** + * Destroys a smartspace session. + */ + @MainThread + public abstract void onDestroy(@NonNull SmartspaceSessionId sessionId); + + private static final class CallbackWrapper implements Consumer<List<SmartspaceTarget>>, + IBinder.DeathRecipient { + + private final Consumer<CallbackWrapper> mOnBinderDied; + private ISmartspaceCallback mCallback; + + CallbackWrapper(ISmartspaceCallback callback, + @Nullable Consumer<CallbackWrapper> onBinderDied) { + mCallback = callback; + mOnBinderDied = onBinderDied; + try { + mCallback.asBinder().linkToDeath(this, 0); + } catch (RemoteException e) { + Slog.e(TAG, "Failed to link to death: " + e); + } + } + + public boolean isCallback(@NonNull ISmartspaceCallback callback) { + if (mCallback == null) { + Slog.e(TAG, "Callback is null, likely the binder has died."); + return false; + } + return mCallback.equals(callback); + } + + @Override + public void accept(List<SmartspaceTarget> smartspaceTargets) { + try { + if (mCallback != null) { + if (DEBUG) { + Slog.d(TAG, + "CallbackWrapper.accept smartspaceTargets=" + smartspaceTargets); + } + mCallback.onResult(new ParceledListSlice(smartspaceTargets)); + } + } catch (RemoteException e) { + Slog.e(TAG, "Error sending result:" + e); + } + } + + @Override + public void binderDied() { + mCallback.asBinder().unlinkToDeath(this, 0); + mCallback = null; + if (mOnBinderDied != null) { + mOnBinderDied.accept(this); + } + } + } +} diff --git a/core/java/android/service/voice/VoiceInteractionService.java b/core/java/android/service/voice/VoiceInteractionService.java index 68d6f3fe3743..25f80900f1cf 100644 --- a/core/java/android/service/voice/VoiceInteractionService.java +++ b/core/java/android/service/voice/VoiceInteractionService.java @@ -345,7 +345,8 @@ public class VoiceInteractionService extends Service { */ @SystemApi @HotwordConfigResult - public final int setHotwordDetectionConfig(@Nullable Bundle options) { + public final int setHotwordDetectionConfig( + @SuppressLint("NullableCollection") @Nullable Bundle options) { if (mSystemService == null) { throw new IllegalStateException("Not available until onReady() is called"); } diff --git a/core/java/android/util/imetracing/ImeTracing.java b/core/java/android/util/imetracing/ImeTracing.java index 723f1dd15e23..49ff237403b2 100644 --- a/core/java/android/util/imetracing/ImeTracing.java +++ b/core/java/android/util/imetracing/ImeTracing.java @@ -28,6 +28,8 @@ import android.util.Log; import android.util.proto.ProtoOutputStream; import android.view.inputmethod.InputMethodManager; +import com.android.internal.inputmethod.Completable; +import com.android.internal.inputmethod.ResultCallbacks; import com.android.internal.view.IInputMethodManager; import java.io.PrintWriter; @@ -91,7 +93,9 @@ public abstract class ImeTracing { * @param where */ public void sendToService(byte[] protoDump, int source, String where) throws RemoteException { - mService.startProtoDump(protoDump, source, where); + final Completable.Void value = Completable.createVoid(); + mService.startProtoDump(protoDump, source, where, ResultCallbacks.of(value)); + Completable.getResult(value); } /** diff --git a/core/java/android/util/imetracing/OWNERS b/core/java/android/util/imetracing/OWNERS new file mode 100644 index 000000000000..885fd0ab9a45 --- /dev/null +++ b/core/java/android/util/imetracing/OWNERS @@ -0,0 +1,3 @@ +set noparent + +include /services/core/java/com/android/server/inputmethod/OWNERS diff --git a/core/java/android/view/ContentInfo.java b/core/java/android/view/ContentInfo.java index bc66ea16bb72..547bc9d49380 100644 --- a/core/java/android/view/ContentInfo.java +++ b/core/java/android/view/ContentInfo.java @@ -19,6 +19,7 @@ package android.view; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SuppressLint; import android.annotation.TestApi; import android.content.ClipData; import android.content.ClipDescription; @@ -204,6 +205,7 @@ public final class ContentInfo { * the IME. */ @Nullable + @SuppressLint("NullableCollection") public Bundle getExtras() { return mExtras; } @@ -347,7 +349,7 @@ public final class ContentInfo { * @return this builder */ @NonNull - public Builder setExtras(@Nullable Bundle extras) { + public Builder setExtras(@SuppressLint("NullableCollection") @Nullable Bundle extras) { mExtras = extras; return this; } diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java index f4b90e1f7b44..bc03222f390d 100644 --- a/core/java/android/view/InputDevice.java +++ b/core/java/android/view/InputDevice.java @@ -22,6 +22,7 @@ import android.annotation.RequiresPermission; import android.annotation.TestApi; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; +import android.hardware.Battery; import android.hardware.SensorManager; import android.hardware.input.InputDeviceIdentifier; import android.hardware.input.InputManager; @@ -73,6 +74,7 @@ public final class InputDevice implements Parcelable { private final boolean mHasMicrophone; private final boolean mHasButtonUnderPad; private final boolean mHasSensor; + private final boolean mHasBattery; private final ArrayList<MotionRange> mMotionRanges = new ArrayList<MotionRange>(); @GuardedBy("mMotionRanges") @@ -84,6 +86,9 @@ public final class InputDevice implements Parcelable { @GuardedBy("mMotionRanges") private SensorManager mSensorManager; + @GuardedBy("mMotionRanges") + private Battery mBattery; + /** * A mask for input source classes. * @@ -323,6 +328,13 @@ public final class InputDevice implements Parcelable { public static final int SOURCE_HDMI = 0x02000000 | SOURCE_CLASS_BUTTON; /** + * The input source is a sensor associated with the input device. + * + * @see #SOURCE_CLASS_NONE + */ + public static final int SOURCE_SENSOR = 0x04000000 | SOURCE_CLASS_NONE; + + /** * A special input source constant that is used when filtering input devices * to match devices that provide any type of input source. */ @@ -448,7 +460,7 @@ public final class InputDevice implements Parcelable { public InputDevice(int id, int generation, int controllerNumber, String name, int vendorId, int productId, String descriptor, boolean isExternal, int sources, int keyboardType, KeyCharacterMap keyCharacterMap, boolean hasVibrator, boolean hasMicrophone, - boolean hasButtonUnderPad, boolean hasSensor) { + boolean hasButtonUnderPad, boolean hasSensor, boolean hasBattery) { mId = id; mGeneration = generation; mControllerNumber = controllerNumber; @@ -464,6 +476,7 @@ public final class InputDevice implements Parcelable { mHasMicrophone = hasMicrophone; mHasButtonUnderPad = hasButtonUnderPad; mHasSensor = hasSensor; + mHasBattery = hasBattery; mIdentifier = new InputDeviceIdentifier(descriptor, vendorId, productId); } @@ -483,6 +496,7 @@ public final class InputDevice implements Parcelable { mHasMicrophone = in.readInt() != 0; mHasButtonUnderPad = in.readInt() != 0; mHasSensor = in.readInt() != 0; + mHasBattery = in.readInt() != 0; mIdentifier = new InputDeviceIdentifier(mDescriptor, mVendorId, mProductId); int numRanges = in.readInt(); @@ -830,6 +844,22 @@ public final class InputDevice implements Parcelable { } /** + * Gets the battery object associated with the device, if there is one. + * Even if the device does not have a battery, the result is never null. + * Use {@link Battery#hasBattery} to determine whether a battery is + * present. + * + * @return The battery object associated with the device, never null. + */ + @NonNull + public Battery getBattery() { + if (mBattery == null) { + mBattery = InputManager.getInstance().getInputDeviceBattery(mId, mHasBattery); + } + return mBattery; + } + + /** * Gets the sensor manager service associated with the input device. * Even if the device does not have a sensor, the result is never null. * Use {@link SensorManager#getSensorList} to get a full list of all supported sensors. @@ -1051,6 +1081,7 @@ public final class InputDevice implements Parcelable { out.writeInt(mHasMicrophone ? 1 : 0); out.writeInt(mHasButtonUnderPad ? 1 : 0); out.writeInt(mHasSensor ? 1 : 0); + out.writeInt(mHasBattery ? 1 : 0); final int numRanges = mMotionRanges.size(); out.writeInt(numRanges); @@ -1097,6 +1128,8 @@ public final class InputDevice implements Parcelable { description.append(" Has Sensor: ").append(mHasSensor).append("\n"); + description.append(" Has battery: ").append(mHasBattery).append("\n"); + description.append(" Has mic: ").append(mHasMicrophone).append("\n"); description.append(" Sources: 0x").append(Integer.toHexString(mSources)).append(" ("); diff --git a/core/java/android/view/InsetsFlags.java b/core/java/android/view/InsetsFlags.java index a334907c04bc..3355252c4372 100644 --- a/core/java/android/view/InsetsFlags.java +++ b/core/java/android/view/InsetsFlags.java @@ -21,6 +21,8 @@ import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS; import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS; import static android.view.WindowInsetsController.APPEARANCE_OPAQUE_NAVIGATION_BARS; import static android.view.WindowInsetsController.APPEARANCE_OPAQUE_STATUS_BARS; +import static android.view.WindowInsetsController.APPEARANCE_SEMI_TRANSPARENT_NAVIGATION_BARS; +import static android.view.WindowInsetsController.APPEARANCE_SEMI_TRANSPARENT_STATUS_BARS; import static android.view.WindowInsetsController.BEHAVIOR_DEFAULT; import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE; @@ -54,7 +56,15 @@ public class InsetsFlags { @ViewDebug.FlagToString( mask = APPEARANCE_LIGHT_NAVIGATION_BARS, equals = APPEARANCE_LIGHT_NAVIGATION_BARS, - name = "LIGHT_NAVIGATION_BARS") + name = "LIGHT_NAVIGATION_BARS"), + @ViewDebug.FlagToString( + mask = APPEARANCE_SEMI_TRANSPARENT_STATUS_BARS, + equals = APPEARANCE_SEMI_TRANSPARENT_STATUS_BARS, + name = "SEMI_TRANSPARENT_STATUS_BARS"), + @ViewDebug.FlagToString( + mask = APPEARANCE_SEMI_TRANSPARENT_NAVIGATION_BARS, + equals = APPEARANCE_SEMI_TRANSPARENT_NAVIGATION_BARS, + name = "SEMI_TRANSPARENT_NAVIGATION_BARS") }) public @Appearance int appearance; diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java index bf377b0bcfd7..d68e9032c19d 100644 --- a/core/java/android/view/InsetsState.java +++ b/core/java/android/view/InsetsState.java @@ -106,7 +106,9 @@ public class InsetsState implements Parcelable { public static final int ITYPE_NAVIGATION_BAR = 1; public static final int ITYPE_CAPTION_BAR = 2; - public static final int ITYPE_TOP_GESTURES = 3; + // The always visible types are visible to all windows regardless of the z-order. + public static final int FIRST_ALWAYS_VISIBLE_TYPE = 3; + public static final int ITYPE_TOP_GESTURES = FIRST_ALWAYS_VISIBLE_TYPE; public static final int ITYPE_BOTTOM_GESTURES = 4; public static final int ITYPE_LEFT_GESTURES = 5; public static final int ITYPE_RIGHT_GESTURES = 6; @@ -117,15 +119,16 @@ public class InsetsState implements Parcelable { public static final int ITYPE_LEFT_MANDATORY_GESTURES = 9; public static final int ITYPE_RIGHT_MANDATORY_GESTURES = 10; - public static final int ITYPE_LEFT_TAPPABLE_ELEMENT = 11; - public static final int ITYPE_TOP_TAPPABLE_ELEMENT = 12; - public static final int ITYPE_RIGHT_TAPPABLE_ELEMENT = 13; - public static final int ITYPE_BOTTOM_TAPPABLE_ELEMENT = 14; + public static final int ITYPE_LEFT_DISPLAY_CUTOUT = 11; + public static final int ITYPE_TOP_DISPLAY_CUTOUT = 12; + public static final int ITYPE_RIGHT_DISPLAY_CUTOUT = 13; + public static final int ITYPE_BOTTOM_DISPLAY_CUTOUT = 14; + public static final int LAST_ALWAYS_VISIBLE_TYPE = ITYPE_BOTTOM_DISPLAY_CUTOUT; - public static final int ITYPE_LEFT_DISPLAY_CUTOUT = 15; - public static final int ITYPE_TOP_DISPLAY_CUTOUT = 16; - public static final int ITYPE_RIGHT_DISPLAY_CUTOUT = 17; - public static final int ITYPE_BOTTOM_DISPLAY_CUTOUT = 18; + public static final int ITYPE_LEFT_TAPPABLE_ELEMENT = 15; + public static final int ITYPE_TOP_TAPPABLE_ELEMENT = 16; + public static final int ITYPE_RIGHT_TAPPABLE_ELEMENT = 17; + public static final int ITYPE_BOTTOM_TAPPABLE_ELEMENT = 18; /** Input method window. */ public static final int ITYPE_IME = 19; @@ -182,6 +185,18 @@ public class InsetsState implements Parcelable { } /** + * Mirror the always visible sources from the other state. They will share the same object for + * the always visible types. + * + * @param other the state to mirror the mirrored sources from. + */ + public void mirrorAlwaysVisibleInsetsSources(InsetsState other) { + for (int type = FIRST_ALWAYS_VISIBLE_TYPE; type <= LAST_ALWAYS_VISIBLE_TYPE; type++) { + mSources[type] = other.mSources[type]; + } + } + + /** * Calculates {@link WindowInsets} based on the current source configuration. * * @param frame The frame to calculate the insets relative to. diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index 0a1a23116941..acd25077fb5a 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -750,18 +750,22 @@ public final class SurfaceControl implements Parcelable { private abstract static class CaptureArgs { private final int mPixelFormat; private final Rect mSourceCrop = new Rect(); - private final float mFrameScale; + private final float mFrameScaleX; + private final float mFrameScaleY; private final boolean mCaptureSecureLayers; private final boolean mAllowProtected; private final long mUid; + private final boolean mGrayscale; private CaptureArgs(Builder<? extends Builder<?>> builder) { mPixelFormat = builder.mPixelFormat; mSourceCrop.set(builder.mSourceCrop); - mFrameScale = builder.mFrameScale; + mFrameScaleX = builder.mFrameScaleX; + mFrameScaleY = builder.mFrameScaleY; mCaptureSecureLayers = builder.mCaptureSecureLayers; mAllowProtected = builder.mAllowProtected; mUid = builder.mUid; + mGrayscale = builder.mGrayscale; } /** @@ -772,10 +776,12 @@ public final class SurfaceControl implements Parcelable { abstract static class Builder<T extends Builder<T>> { private int mPixelFormat = PixelFormat.RGBA_8888; private final Rect mSourceCrop = new Rect(); - private float mFrameScale = 1; + private float mFrameScaleX = 1; + private float mFrameScaleY = 1; private boolean mCaptureSecureLayers; private boolean mAllowProtected; private long mUid = -1; + private boolean mGrayscale; /** * The desired pixel format of the returned buffer. @@ -798,7 +804,18 @@ public final class SurfaceControl implements Parcelable { * The desired scale of the returned buffer. The raw screen will be scaled up/down. */ public T setFrameScale(float frameScale) { - mFrameScale = frameScale; + mFrameScaleX = frameScale; + mFrameScaleY = frameScale; + return getThis(); + } + + /** + * The desired scale of the returned buffer, allowing separate values for x and y scale. + * The raw screen will be scaled up/down. + */ + public T setFrameScale(float frameScaleX, float frameScaleY) { + mFrameScaleX = frameScaleX; + mFrameScaleY = frameScaleY; return getThis(); } @@ -834,6 +851,14 @@ public final class SurfaceControl implements Parcelable { } /** + * Set whether the screenshot should use grayscale or not. + */ + public T setGrayscale(boolean grayscale) { + mGrayscale = grayscale; + return getThis(); + } + + /** * Each sub class should return itself to allow the builder to chain properly */ abstract T getThis(); @@ -929,7 +954,7 @@ public final class SurfaceControl implements Parcelable { /** * The arguments class used to make layer capture requests. * - * @see #nativeCaptureLayers(LayerCaptureArgs) + * @see #nativeCaptureLayers(LayerCaptureArgs, ScreenCaptureListener) * @hide */ public static class LayerCaptureArgs extends CaptureArgs { diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 5c0e15639491..9a412fcd436a 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -41,6 +41,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.Size; import android.annotation.StyleRes; +import android.annotation.SuppressLint; import android.annotation.TestApi; import android.annotation.UiContext; import android.annotation.UiThread; @@ -9030,7 +9031,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * not be null or empty if a non-null listener is passed in. * @param listener The listener to use. This can be null to reset to the default behavior. */ - public void setOnReceiveContentListener(@Nullable String[] mimeTypes, + public void setOnReceiveContentListener( + @SuppressLint("NullableCollection") @Nullable String[] mimeTypes, @Nullable OnReceiveContentListener listener) { if (listener != null) { Preconditions.checkArgument(mimeTypes != null && mimeTypes.length > 0, @@ -9106,6 +9108,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @return The MIME types accepted by {@link #performReceiveContent} for this view (may * include patterns such as "image/*"). */ + @SuppressLint("NullableCollection") @Nullable public String[] getOnReceiveContentMimeTypes() { return mOnReceiveContentMimeTypes; @@ -21367,6 +21370,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback, int height = mBottom - mTop; int layerType = getLayerType(); + // Hacky hack: Reset any stretch effects as those are applied during the draw pass + // instead of being "stateful" like other RenderNode properties + renderNode.clearStretch(); + final RecordingCanvas canvas = renderNode.beginRecording(width, height); try { @@ -22793,6 +22800,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, final Rect bounds = drawable.getBounds(); final int width = bounds.width(); final int height = bounds.height(); + + // Hacky hack: Reset any stretch effects as those are applied during the draw pass + // instead of being "stateful" like other RenderNode properties + renderNode.clearStretch(); + final RecordingCanvas canvas = renderNode.beginRecording(width, height); // Reverse left/top translation done by drawable canvas, which will diff --git a/core/java/android/view/ViewStructure.java b/core/java/android/view/ViewStructure.java index f5aa97a88608..8b3fb2e9e751 100644 --- a/core/java/android/view/ViewStructure.java +++ b/core/java/android/view/ViewStructure.java @@ -18,6 +18,7 @@ package android.view; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SuppressLint; import android.graphics.Matrix; import android.graphics.Rect; import android.os.Bundle; @@ -377,7 +378,8 @@ public abstract class ViewStructure { * <p>Should only be set when the node is used for Autofill or Content Capture purposes - it * will be ignored when used for Assist. */ - public void setOnReceiveContentMimeTypes(@Nullable String[] mimeTypes) {} + public void setOnReceiveContentMimeTypes( + @SuppressLint("NullableCollection") @Nullable String[] mimeTypes) {} /** * Sets the {@link android.text.InputType} bits of this node. diff --git a/core/java/android/view/WindowInsetsController.java b/core/java/android/view/WindowInsetsController.java index 991ed5518003..227b9f402bba 100644 --- a/core/java/android/view/WindowInsetsController.java +++ b/core/java/android/view/WindowInsetsController.java @@ -67,13 +67,26 @@ public interface WindowInsetsController { int APPEARANCE_LIGHT_NAVIGATION_BARS = 1 << 4; /** + * Makes status bars semi-transparent with dark background and light foreground. + * @hide + */ + int APPEARANCE_SEMI_TRANSPARENT_STATUS_BARS = 1 << 5; + + /** + * Makes navigation bars semi-transparent with dark background and light foreground. + * @hide + */ + int APPEARANCE_SEMI_TRANSPARENT_NAVIGATION_BARS = 1 << 6; + + /** * Determines the appearance of system bars. * @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef(flag = true, value = {APPEARANCE_OPAQUE_STATUS_BARS, APPEARANCE_OPAQUE_NAVIGATION_BARS, APPEARANCE_LOW_PROFILE_BARS, APPEARANCE_LIGHT_STATUS_BARS, - APPEARANCE_LIGHT_NAVIGATION_BARS}) + APPEARANCE_LIGHT_NAVIGATION_BARS, APPEARANCE_SEMI_TRANSPARENT_STATUS_BARS, + APPEARANCE_SEMI_TRANSPARENT_NAVIGATION_BARS}) @interface Appearance { } diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index 7faa222dd51f..fa471fa28c7f 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -1555,17 +1555,26 @@ public interface WindowManager extends ViewManager { * <li><b>Fully transparent windows</b>: This window has {@link LayoutParams#alpha} equal * to 0. * <li><b>One SAW window with enough transparency</b>: This window is of type {@link - * #TYPE_APPLICATION_OVERLAY}, has {@link LayoutParams#alpha} below or equal to <b>0.8</b> - * and it's the <b>only</b> window of type {@link #TYPE_APPLICATION_OVERLAY} from this UID - * in the touch path. + * #TYPE_APPLICATION_OVERLAY}, has {@link LayoutParams#alpha} below or equal to the + * <a href="#MaximumOpacity">maximum obscuring opacity</a> (see below) and it's the + * <b>only</b> window of type {@link #TYPE_APPLICATION_OVERLAY} from this UID in the touch + * path. * <li><b>Multiple SAW windows with enough transparency</b>: The multiple overlapping * {@link #TYPE_APPLICATION_OVERLAY} windows in the * touch path from this UID have a <b>combined obscuring opacity</b> below or equal to - * <b>0.8</b>. See section below on how to compute this value. + * the <a href="#MaximumOpacity">maximum obscuring opacity</a>. See section + * <a href="#ObscuringOpacity">Combined obscuring opacity</a> below on how to compute this + * value. * </ol> * <p>If none of these cases hold, the touch will not be delivered and a message will be * logged to logcat.</p> * + * <a name="MaximumOpacity"></a> + * <h3>Maximum obscuring opacity</h3> + * <p>This value is <b>0.8</b>. Apps that want to gather this value from the system rather + * than hard-coding it might want to use {@link + * android.hardware.input.InputManager#getMaximumObscuringOpacityForTouch()}.</p> + * * <a name="ObscuringOpacity"></a> * <h3>Combined obscuring opacity</h3> * diff --git a/core/java/android/view/inputmethod/InputConnection.java b/core/java/android/view/inputmethod/InputConnection.java index a76d46d1c00f..f3111bdc7471 100644 --- a/core/java/android/view/inputmethod/InputConnection.java +++ b/core/java/android/view/inputmethod/InputConnection.java @@ -858,7 +858,7 @@ public interface InputConnection { boolean reportFullscreenMode(boolean enabled); /** - * Have the editor perform spell checking around the current selection. + * Have the editor perform spell checking for the full content. * * <p>The editor can ignore this method call if it does not support spell checking. * diff --git a/core/java/android/view/textservice/TextServicesManager.java b/core/java/android/view/textservice/TextServicesManager.java index 0a1aea38dd58..5980cb6c3671 100644 --- a/core/java/android/view/textservice/TextServicesManager.java +++ b/core/java/android/view/textservice/TextServicesManager.java @@ -187,7 +187,8 @@ public final class TextServicesManager { * @return The spell checker session of the spell checker. */ @Nullable - public SpellCheckerSession newSpellCheckerSession(@Nullable Bundle bundle, + public SpellCheckerSession newSpellCheckerSession( + @SuppressLint("NullableCollection") @Nullable Bundle bundle, @SuppressLint("UseIcu") @Nullable Locale locale, @NonNull SpellCheckerSessionListener listener, @SuppressLint("ListenerLast") boolean referToSpellCheckerLanguageSettings, @@ -277,6 +278,7 @@ public final class TextServicesManager { * @return The list of currently enabled spell checkers. */ @Nullable + @SuppressLint("NullableCollection") public List<SpellCheckerInfo> getEnabledSpellCheckersList() { final SpellCheckerInfo[] enabledSpellCheckers = getEnabledSpellCheckers(); return enabledSpellCheckers != null ? Arrays.asList(enabledSpellCheckers) : null; diff --git a/core/java/android/widget/SpellChecker.java b/core/java/android/widget/SpellChecker.java index 97d98fd8ec59..794b642135d0 100644 --- a/core/java/android/widget/SpellChecker.java +++ b/core/java/android/widget/SpellChecker.java @@ -220,29 +220,26 @@ public class SpellChecker implements SpellCheckerSessionListener { } void onPerformSpellCheck() { - final int selectionStart = mTextView.getSelectionStart(); - final int selectionEnd = mTextView.getSelectionEnd(); - final int selectionRangeStart; - final int selectionRangeEnd; - if (selectionStart < selectionEnd) { - selectionRangeStart = selectionStart; - selectionRangeEnd = selectionEnd; - } else { - selectionRangeStart = selectionEnd; - selectionRangeEnd = selectionStart; - } - // Expand the range so that it (hopefully) includes the current sentence. - final int start = Math.max(0, selectionRangeStart - MIN_SENTENCE_LENGTH); - final int end = Math.min(mTextView.length(), selectionRangeEnd + MIN_SENTENCE_LENGTH); + // Triggers full content spell check. + final int start = 0; + final int end = mTextView.length(); if (DBG) { Log.d(TAG, "performSpellCheckAroundSelection: " + start + ", " + end); } - spellCheck(start, end); + spellCheck(start, end, /* forceCheckWhenEditingWord= */ true); } public void spellCheck(int start, int end) { + spellCheck(start, end, /* forceCheckWhenEditingWord= */ false); + } + + /** + * Requests to do spell check for text in the range (start, end). + */ + public void spellCheck(int start, int end, boolean forceCheckWhenEditingWord) { if (DBG) { - Log.d(TAG, "Start spell-checking: " + start + ", " + end); + Log.d(TAG, "Start spell-checking: " + start + ", " + end + ", " + + forceCheckWhenEditingWord); } final Locale locale = mTextView.getSpellCheckerLocale(); final boolean isSessionActive = isSessionActive(); @@ -267,7 +264,7 @@ public class SpellChecker implements SpellCheckerSessionListener { for (int i = 0; i < length; i++) { final SpellParser spellParser = mSpellParsers[i]; if (spellParser.isFinished()) { - spellParser.parse(start, end); + spellParser.parse(start, end, forceCheckWhenEditingWord); return; } } @@ -282,10 +279,14 @@ public class SpellChecker implements SpellCheckerSessionListener { SpellParser spellParser = new SpellParser(); mSpellParsers[length] = spellParser; - spellParser.parse(start, end); + spellParser.parse(start, end, forceCheckWhenEditingWord); } private void spellCheck() { + spellCheck(/* forceCheckWhenEditingWord= */ false); + } + + private void spellCheck(boolean forceCheckWhenEditingWord) { if (mSpellCheckerSession == null) return; Editable editable = (Editable) mTextView.getText(); @@ -295,6 +296,12 @@ public class SpellChecker implements SpellCheckerSessionListener { TextInfo[] textInfos = new TextInfo[mLength]; int textInfosCount = 0; + if (DBG) { + Log.d(TAG, "forceCheckWhenEditingWord=" + forceCheckWhenEditingWord + + ", mLength=" + mLength + ", cookie = " + mCookie + + ", sel start = " + selectionStart + ", sel end = " + selectionEnd); + } + for (int i = 0; i < mLength; i++) { final SpellCheckSpan spellCheckSpan = mSpellCheckSpans[i]; if (mIds[i] < 0 || spellCheckSpan.isSpellCheckInProgress()) continue; @@ -319,7 +326,7 @@ public class SpellChecker implements SpellCheckerSessionListener { } else { isEditing = selectionEnd < start || selectionStart > end; } - if (start >= 0 && end > start && isEditing) { + if (start >= 0 && end > start && (forceCheckWhenEditingWord || isEditing)) { spellCheckSpan.setSpellCheckInProgress(true); final TextInfo textInfo = new TextInfo(editable, start, end, mCookie, mIds[i]); textInfos[textInfosCount++] = textInfo; @@ -546,7 +553,11 @@ public class SpellChecker implements SpellCheckerSessionListener { private class SpellParser { private Object mRange = new Object(); - public void parse(int start, int end) { + // Forces to do spell checker even user is editing the word. + private boolean mForceCheckWhenEditingWord; + + public void parse(int start, int end, boolean forceCheckWhenEditingWord) { + mForceCheckWhenEditingWord = forceCheckWhenEditingWord; final int max = mTextView.length(); final int parseEnd; if (end > max) { @@ -567,6 +578,7 @@ public class SpellChecker implements SpellCheckerSessionListener { public void stop() { removeRangeSpan((Editable) mTextView.getText()); + mForceCheckWhenEditingWord = false; } private void setRangeSpan(Editable editable, int start, int end) { @@ -617,7 +629,7 @@ public class SpellChecker implements SpellCheckerSessionListener { if (DBG) { Log.i(TAG, "No more spell check."); } - removeRangeSpan(editable); + stop(); return; } @@ -649,7 +661,7 @@ public class SpellChecker implements SpellCheckerSessionListener { if (DBG) { Log.i(TAG, "Incorrect range span."); } - removeRangeSpan(editable); + stop(); return; } do { @@ -778,7 +790,7 @@ public class SpellChecker implements SpellCheckerSessionListener { removeRangeSpan(editable); } - spellCheck(); + spellCheck(mForceCheckWhenEditingWord); } private <T> void removeSpansAt(Editable editable, int offset, T[] spans) { diff --git a/core/java/android/window/TaskOrganizer.java b/core/java/android/window/TaskOrganizer.java index f29eb39045ae..cdb4762a4f0a 100644 --- a/core/java/android/window/TaskOrganizer.java +++ b/core/java/android/window/TaskOrganizer.java @@ -21,6 +21,7 @@ import android.annotation.CallSuper; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; +import android.annotation.SuppressLint; import android.annotation.TestApi; import android.app.ActivityManager; import android.os.IBinder; @@ -151,6 +152,7 @@ public class TaskOrganizer extends WindowOrganizer { /** Gets direct child tasks (ordered from top-to-bottom) */ @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) @Nullable + @SuppressLint("NullableCollection") public List<ActivityManager.RunningTaskInfo> getChildTasks( @NonNull WindowContainerToken parent, @NonNull int[] activityTypes) { try { @@ -163,6 +165,7 @@ public class TaskOrganizer extends WindowOrganizer { /** Gets all root tasks on a display (ordered from top-to-bottom) */ @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) @Nullable + @SuppressLint("NullableCollection") public List<ActivityManager.RunningTaskInfo> getRootTasks( int displayId, @NonNull int[] activityTypes) { try { diff --git a/core/java/com/android/internal/app/OWNERS b/core/java/com/android/internal/app/OWNERS index 99692d0736c2..7ade05cc6de1 100644 --- a/core/java/com/android/internal/app/OWNERS +++ b/core/java/com/android/internal/app/OWNERS @@ -5,3 +5,4 @@ per-file SimpleIconFactory.java = file:/packages/SystemUI/OWNERS per-file NetInitiatedActivity.java = file:/location/java/android/location/OWNERS per-file IVoice* = file:/core/java/android/service/voice/OWNERS per-file *Hotword* = file:/core/java/android/service/voice/OWNERS +per-file *BatteryStats* = file:/BATTERY_STATS_OWNERS diff --git a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java index 13358daf05a1..1f09489b3f1f 100644 --- a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java +++ b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java @@ -62,6 +62,11 @@ public final class SystemUiDeviceConfigFlags { */ public static final String ENABLE_NAS_FEEDBACK = "enable_nas_feedback"; + /** + * Whether the Notification Assistant can label a notification not a conversation + */ + public static final String ENABLE_NAS_NOT_CONVERSATION = "enable_nas_not_conversation"; + // Flags related to screenshot intelligence /** diff --git a/core/java/com/android/internal/os/BatteryUsageStatsProvider.java b/core/java/com/android/internal/os/BatteryUsageStatsProvider.java index b8c066db29af..ea2fb88a3fc7 100644 --- a/core/java/com/android/internal/os/BatteryUsageStatsProvider.java +++ b/core/java/com/android/internal/os/BatteryUsageStatsProvider.java @@ -18,7 +18,6 @@ package com.android.internal.os; import android.content.Context; import android.hardware.SensorManager; -import android.net.ConnectivityManager; import android.os.BatteryStats; import android.os.BatteryUsageStats; import android.os.BatteryUsageStatsQuery; @@ -57,7 +56,7 @@ public class BatteryUsageStatsProvider { mPowerCalculators.add(new CpuPowerCalculator(mPowerProfile)); mPowerCalculators.add(new MemoryPowerCalculator(mPowerProfile)); mPowerCalculators.add(new WakelockPowerCalculator(mPowerProfile)); - if (!isWifiOnlyDevice(mContext)) { + if (!BatteryStatsHelper.checkWifiOnly(mContext)) { mPowerCalculators.add(new MobileRadioPowerCalculator(mPowerProfile)); } mPowerCalculators.add(new WifiPowerCalculator(mPowerProfile)); @@ -81,14 +80,6 @@ public class BatteryUsageStatsProvider { return mPowerCalculators; } - private static boolean isWifiOnlyDevice(Context context) { - ConnectivityManager cm = context.getSystemService(ConnectivityManager.class); - if (cm == null) { - return false; - } - return !cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE); - } - /** * Returns a snapshot of battery attribution data. */ diff --git a/services/core/java/com/android/server/AttributeCache.java b/core/java/com/android/internal/policy/AttributeCache.java index 58ec836547a7..1bdad25d25bb 100644 --- a/services/core/java/com/android/server/AttributeCache.java +++ b/core/java/com/android/internal/policy/AttributeCache.java @@ -1,21 +1,20 @@ /* -** -** Copyright 2007, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -package com.android.server; + * Copyright (C) 2007 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; import android.content.Context; import android.content.pm.ActivityInfo; @@ -34,6 +33,7 @@ import com.android.internal.annotations.GuardedBy; * TODO: This should be better integrated into the system so it doesn't need * special calls from the activity manager to clear it. */ +/** @hide */ public final class AttributeCache { private static final int CACHE_SIZE = 4; private static AttributeCache sInstance = null; @@ -54,11 +54,11 @@ public final class AttributeCache { context = c; } } - + public final static class Entry { public final Context context; public final TypedArray array; - + public Entry(Context c, TypedArray ta) { context = c; array = ta; @@ -70,17 +70,17 @@ public final class AttributeCache { } } } - + public static void init(Context context) { if (sInstance == null) { sInstance = new AttributeCache(context); } } - + public static AttributeCache instance() { return sInstance; } - + public AttributeCache(Context context) { mContext = context; } @@ -115,7 +115,11 @@ public final class AttributeCache { } } } - + + public Entry get(String packageName, int resId, int[] styleable) { + return get(packageName, resId, styleable, UserHandle.USER_CURRENT); + } + public Entry get(String packageName, int resId, int[] styleable, int userId) { synchronized (this) { Package pkg = mPackages.get(packageName); @@ -143,12 +147,12 @@ public final class AttributeCache { pkg = new Package(context); mPackages.put(packageName, pkg); } - + if (map == null) { map = new ArrayMap<>(); pkg.mMap.put(resId, map); } - + try { ent = new Entry(pkg.context, pkg.context.obtainStyledAttributes(resId, styleable)); @@ -156,7 +160,7 @@ public final class AttributeCache { } catch (Resources.NotFoundException e) { return null; } - + return ent; } } diff --git a/services/core/java/com/android/server/wm/animation/ClipRectLRAnimation.java b/core/java/com/android/internal/policy/ClipRectLRAnimation.java index 0db4c70e2761..4dc3cd31ac20 100644 --- a/services/core/java/com/android/server/wm/animation/ClipRectLRAnimation.java +++ b/core/java/com/android/internal/policy/ClipRectLRAnimation.java @@ -11,10 +11,10 @@ * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and - * limitations under the License + * limitations under the License. */ -package com.android.server.wm.animation; +package com.android.internal.policy; import android.graphics.Rect; import android.view.animation.ClipRectAnimation; diff --git a/services/core/java/com/android/server/wm/animation/ClipRectTBAnimation.java b/core/java/com/android/internal/policy/ClipRectTBAnimation.java index 1f5b1a3f9660..24913cf7fca2 100644 --- a/services/core/java/com/android/server/wm/animation/ClipRectTBAnimation.java +++ b/core/java/com/android/internal/policy/ClipRectTBAnimation.java @@ -11,16 +11,15 @@ * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and - * limitations under the License + * limitations under the License. */ -package com.android.server.wm.animation; +package com.android.internal.policy; import android.graphics.Rect; import android.view.animation.ClipRectAnimation; import android.view.animation.Interpolator; import android.view.animation.Transformation; -import android.view.animation.TranslateAnimation; /** * Special case of ClipRectAnimation that animates only the top/bottom diff --git a/services/core/java/com/android/server/policy/LogDecelerateInterpolator.java b/core/java/com/android/internal/policy/LogDecelerateInterpolator.java index ed5dc6fa7a51..dee77aae01fe 100644 --- a/services/core/java/com/android/server/policy/LogDecelerateInterpolator.java +++ b/core/java/com/android/internal/policy/LogDecelerateInterpolator.java @@ -11,13 +11,14 @@ * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and - * limitations under the License + * limitations under the License. */ -package com.android.server.policy; +package com.android.internal.policy; import android.view.animation.Interpolator; +/** @hide */ public class LogDecelerateInterpolator implements Interpolator { private int mBase; diff --git a/core/java/com/android/internal/policy/TransitionAnimation.java b/core/java/com/android/internal/policy/TransitionAnimation.java new file mode 100644 index 000000000000..56b25b2060ea --- /dev/null +++ b/core/java/com/android/internal/policy/TransitionAnimation.java @@ -0,0 +1,960 @@ +/* + * Copyright (C) 2021 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; + +import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION; +import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_SUBTLE_ANIMATION; +import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE; +import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_CLOSE; +import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_OPEN; +import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER; +import static android.view.WindowManager.TRANSIT_OLD_TRANSLUCENT_ACTIVITY_CLOSE; +import static android.view.WindowManager.TRANSIT_OLD_TRANSLUCENT_ACTIVITY_OPEN; +import static android.view.WindowManager.TRANSIT_OLD_WALLPAPER_INTRA_CLOSE; +import static android.view.WindowManager.TRANSIT_OLD_WALLPAPER_INTRA_OPEN; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.app.ActivityManager; +import android.content.Context; +import android.content.res.Configuration; +import android.content.res.ResourceId; +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.graphics.Rect; +import android.hardware.HardwareBuffer; +import android.os.SystemProperties; +import android.util.Slog; +import android.view.WindowManager.LayoutParams; +import android.view.WindowManager.TransitionOldType; +import android.view.animation.AlphaAnimation; +import android.view.animation.Animation; +import android.view.animation.AnimationSet; +import android.view.animation.AnimationUtils; +import android.view.animation.ClipRectAnimation; +import android.view.animation.Interpolator; +import android.view.animation.PathInterpolator; +import android.view.animation.ScaleAnimation; +import android.view.animation.TranslateAnimation; + +import com.android.internal.R; + +import java.util.List; + +/** @hide */ +public class TransitionAnimation { + // These are the possible states for the enter/exit activities during a thumbnail transition + public static final int THUMBNAIL_TRANSITION_ENTER_SCALE_UP = 0; + public static final int THUMBNAIL_TRANSITION_EXIT_SCALE_UP = 1; + public static final int THUMBNAIL_TRANSITION_ENTER_SCALE_DOWN = 2; + public static final int THUMBNAIL_TRANSITION_EXIT_SCALE_DOWN = 3; + + /** + * Maximum duration for the clip reveal animation. This is used when there is a lot of movement + * involved, to make it more understandable. + */ + private static final int MAX_CLIP_REVEAL_TRANSITION_DURATION = 420; + private static final int CLIP_REVEAL_TRANSLATION_Y_DP = 8; + private static final int THUMBNAIL_APP_TRANSITION_DURATION = 336; + + public static final int DEFAULT_APP_TRANSITION_DURATION = 336; + + /** Fraction of animation at which the recents thumbnail becomes completely transparent */ + private static final float RECENTS_THUMBNAIL_FADEOUT_FRACTION = 0.5f; + + private final Context mContext; + private final String mTag; + + private final LogDecelerateInterpolator mInterpolator = new LogDecelerateInterpolator(100, 0); + /** Interpolator to be used for animations that respond directly to a touch */ + private final Interpolator mTouchResponseInterpolator = + new PathInterpolator(0.3f, 0f, 0.1f, 1f); + private final Interpolator mClipHorizontalInterpolator = new PathInterpolator(0, 0, 0.4f, 1f); + private final Interpolator mDecelerateInterpolator; + private final Interpolator mLinearOutSlowInInterpolator; + private final Interpolator mThumbnailFadeOutInterpolator; + private final Rect mTmpFromClipRect = new Rect(); + private final Rect mTmpToClipRect = new Rect(); + private final Rect mTmpRect = new Rect(); + + private final int mClipRevealTranslationY; + private final int mConfigShortAnimTime; + private final int mDefaultWindowAnimationStyleResId; + + private final boolean mDebug; + private final boolean mGridLayoutRecentsEnabled; + private final boolean mLowRamRecentsEnabled; + + public TransitionAnimation(Context context, boolean debug, String tag) { + mContext = context; + mDebug = debug; + mTag = tag; + + mDecelerateInterpolator = AnimationUtils.loadInterpolator(context, + com.android.internal.R.interpolator.decelerate_cubic); + mLinearOutSlowInInterpolator = AnimationUtils.loadInterpolator(context, + com.android.internal.R.interpolator.linear_out_slow_in); + mThumbnailFadeOutInterpolator = input -> { + // Linear response for first fraction, then complete after that. + if (input < RECENTS_THUMBNAIL_FADEOUT_FRACTION) { + float t = input / RECENTS_THUMBNAIL_FADEOUT_FRACTION; + return mLinearOutSlowInInterpolator.getInterpolation(t); + } + return 1f; + }; + + mClipRevealTranslationY = (int) (CLIP_REVEAL_TRANSLATION_Y_DP + * mContext.getResources().getDisplayMetrics().density); + mConfigShortAnimTime = context.getResources().getInteger( + com.android.internal.R.integer.config_shortAnimTime); + + mGridLayoutRecentsEnabled = SystemProperties.getBoolean("ro.recents.grid", false); + mLowRamRecentsEnabled = ActivityManager.isLowRamDeviceStatic(); + + final TypedArray windowStyle = mContext.getTheme().obtainStyledAttributes( + com.android.internal.R.styleable.Window); + mDefaultWindowAnimationStyleResId = windowStyle.getResourceId( + com.android.internal.R.styleable.Window_windowAnimationStyle, 0); + windowStyle.recycle(); + } + + public Animation loadKeyguardExitAnimation(int transit, int transitionFlags) { + if ((transitionFlags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION) != 0) { + return null; + } + final boolean toShade = + (transitionFlags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE) != 0; + final boolean subtle = + (transitionFlags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_SUBTLE_ANIMATION) != 0; + return createHiddenByKeyguardExit(mContext, mInterpolator, + transit == TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER, toShade, subtle); + } + + @Nullable + public Animation loadKeyguardUnoccludeAnimation(LayoutParams lp) { + return loadAnimationRes(lp, com.android.internal.R.anim.wallpaper_open_exit); + } + + @Nullable + public Animation loadVoiceActivityOpenAnimation(LayoutParams lp, boolean enter) { + return loadAnimationRes(lp, enter + ? com.android.internal.R.anim.voice_activity_open_enter + : com.android.internal.R.anim.voice_activity_open_exit); + } + + @Nullable + public Animation loadVoiceActivityExitAnimation(LayoutParams lp, boolean enter) { + return loadAnimationRes(lp, enter + ? com.android.internal.R.anim.voice_activity_close_enter + : com.android.internal.R.anim.voice_activity_close_exit); + } + + @Nullable + public Animation loadAppTransitionAnimation(String packageName, int resId) { + return loadAnimationRes(packageName, resId); + } + + @Nullable + public Animation loadCrossProfileAppEnterAnimation() { + return loadAnimationRes("android", + com.android.internal.R.anim.task_open_enter_cross_profile_apps); + } + + @Nullable + public Animation loadCrossProfileAppThumbnailEnterAnimation() { + return loadAnimationRes( + "android", com.android.internal.R.anim.cross_profile_apps_thumbnail_enter); + } + + @Nullable + private Animation loadAnimationRes(LayoutParams lp, int resId) { + Context context = mContext; + if (ResourceId.isValid(resId)) { + AttributeCache.Entry ent = getCachedAnimations(lp); + if (ent != null) { + context = ent.context; + } + return loadAnimationSafely(context, resId, mTag); + } + return null; + } + + @Nullable + private Animation loadAnimationRes(String packageName, int resId) { + if (ResourceId.isValid(resId)) { + AttributeCache.Entry ent = getCachedAnimations(packageName, resId); + if (ent != null) { + return loadAnimationSafely(ent.context, resId, mTag); + } + } + return null; + } + + @Nullable + public Animation loadAnimationAttr(LayoutParams lp, int animAttr, int transit) { + int resId = Resources.ID_NULL; + Context context = mContext; + if (animAttr >= 0) { + AttributeCache.Entry ent = getCachedAnimations(lp); + if (ent != null) { + context = ent.context; + resId = ent.array.getResourceId(animAttr, 0); + } + } + resId = updateToTranslucentAnimIfNeeded(resId, transit); + if (ResourceId.isValid(resId)) { + return loadAnimationSafely(context, resId, mTag); + } + return null; + } + + @Nullable + private AttributeCache.Entry getCachedAnimations(LayoutParams lp) { + if (mDebug) { + Slog.v(mTag, "Loading animations: layout params pkg=" + + (lp != null ? lp.packageName : null) + + " resId=0x" + (lp != null ? Integer.toHexString(lp.windowAnimations) : null)); + } + if (lp != null && lp.windowAnimations != 0) { + // If this is a system resource, don't try to load it from the + // application resources. It is nice to avoid loading application + // resources if we can. + String packageName = lp.packageName != null ? lp.packageName : "android"; + int resId = getAnimationStyleResId(lp); + if ((resId & 0xFF000000) == 0x01000000) { + packageName = "android"; + } + if (mDebug) { + Slog.v(mTag, "Loading animations: picked package=" + packageName); + } + return AttributeCache.instance().get(packageName, resId, + com.android.internal.R.styleable.WindowAnimation); + } + return null; + } + + @Nullable + private AttributeCache.Entry getCachedAnimations(String packageName, int resId) { + if (mDebug) { + Slog.v(mTag, "Loading animations: package=" + + packageName + " resId=0x" + Integer.toHexString(resId)); + } + if (packageName != null) { + if ((resId & 0xFF000000) == 0x01000000) { + packageName = "android"; + } + if (mDebug) { + Slog.v(mTag, "Loading animations: picked package=" + + packageName); + } + return AttributeCache.instance().get(packageName, resId, + com.android.internal.R.styleable.WindowAnimation); + } + return null; + } + + /** Returns window animation style ID from {@link LayoutParams} or from system in some cases */ + public int getAnimationStyleResId(@NonNull LayoutParams lp) { + int resId = lp.windowAnimations; + if (lp.type == LayoutParams.TYPE_APPLICATION_STARTING) { + // Note that we don't want application to customize starting window animation. + // Since this window is specific for displaying while app starting, + // application should not change its animation directly. + // In this case, it will use system resource to get default animation. + resId = mDefaultWindowAnimationStyleResId; + } + return resId; + } + + public Animation createRelaunchAnimation(Rect containingFrame, Rect contentInsets, + Rect startRect) { + setupDefaultNextAppTransitionStartRect(startRect, mTmpFromClipRect); + final int left = mTmpFromClipRect.left; + final int top = mTmpFromClipRect.top; + mTmpFromClipRect.offset(-left, -top); + // TODO: Isn't that strange that we ignore exact position of the containingFrame? + mTmpToClipRect.set(0, 0, containingFrame.width(), containingFrame.height()); + AnimationSet set = new AnimationSet(true); + float fromWidth = mTmpFromClipRect.width(); + float toWidth = mTmpToClipRect.width(); + float fromHeight = mTmpFromClipRect.height(); + // While the window might span the whole display, the actual content will be cropped to the + // system decoration frame, for example when the window is docked. We need to take into + // account the visible height when constructing the animation. + float toHeight = mTmpToClipRect.height() - contentInsets.top - contentInsets.bottom; + int translateAdjustment = 0; + if (fromWidth <= toWidth && fromHeight <= toHeight) { + // The final window is larger in both dimensions than current window (e.g. we are + // maximizing), so we can simply unclip the new window and there will be no disappearing + // frame. + set.addAnimation(new ClipRectAnimation(mTmpFromClipRect, mTmpToClipRect)); + } else { + // The disappearing window has one larger dimension. We need to apply scaling, so the + // first frame of the entry animation matches the old window. + set.addAnimation(new ScaleAnimation(fromWidth / toWidth, 1, fromHeight / toHeight, 1)); + // We might not be going exactly full screen, but instead be aligned under the status + // bar using cropping. We still need to account for the cropped part, which will also + // be scaled. + translateAdjustment = (int) (contentInsets.top * fromHeight / toHeight); + } + + // We animate the translation from the old position of the removed window, to the new + // position of the added window. The latter might not be full screen, for example docked for + // docked windows. + TranslateAnimation translate = new TranslateAnimation(left - containingFrame.left, + 0, top - containingFrame.top - translateAdjustment, 0); + set.addAnimation(translate); + set.setDuration(DEFAULT_APP_TRANSITION_DURATION); + set.setZAdjustment(Animation.ZORDER_TOP); + return set; + } + + private void setupDefaultNextAppTransitionStartRect(Rect startRect, Rect rect) { + if (startRect == null) { + Slog.e(mTag, "Starting rect for app requested, but none available", new Throwable()); + rect.setEmpty(); + } else { + rect.set(startRect); + } + } + + public Animation createClipRevealAnimationLocked(int transit, boolean enter, Rect appFrame, + Rect displayFrame, Rect startRect) { + final Animation anim; + if (enter) { + final int appWidth = appFrame.width(); + final int appHeight = appFrame.height(); + + // mTmpRect will contain an area around the launcher icon that was pressed. We will + // clip reveal from that area in the final area of the app. + setupDefaultNextAppTransitionStartRect(startRect, mTmpRect); + + float t = 0f; + if (appHeight > 0) { + t = (float) mTmpRect.top / displayFrame.height(); + } + int translationY = mClipRevealTranslationY + (int) (displayFrame.height() / 7f * t); + int translationX = 0; + int translationYCorrection = translationY; + int centerX = mTmpRect.centerX(); + int centerY = mTmpRect.centerY(); + int halfWidth = mTmpRect.width() / 2; + int halfHeight = mTmpRect.height() / 2; + int clipStartX = centerX - halfWidth - appFrame.left; + int clipStartY = centerY - halfHeight - appFrame.top; + boolean cutOff = false; + + // If the starting rectangle is fully or partially outside of the target rectangle, we + // need to start the clipping at the edge and then achieve the rest with translation + // and extending the clip rect from that edge. + if (appFrame.top > centerY - halfHeight) { + translationY = (centerY - halfHeight) - appFrame.top; + translationYCorrection = 0; + clipStartY = 0; + cutOff = true; + } + if (appFrame.left > centerX - halfWidth) { + translationX = (centerX - halfWidth) - appFrame.left; + clipStartX = 0; + cutOff = true; + } + if (appFrame.right < centerX + halfWidth) { + translationX = (centerX + halfWidth) - appFrame.right; + clipStartX = appWidth - mTmpRect.width(); + cutOff = true; + } + final long duration = calculateClipRevealTransitionDuration(cutOff, translationX, + translationY, displayFrame); + + // Clip third of the from size of launch icon, expand to full width/height + Animation clipAnimLR = new ClipRectLRAnimation( + clipStartX, clipStartX + mTmpRect.width(), 0, appWidth); + clipAnimLR.setInterpolator(mClipHorizontalInterpolator); + clipAnimLR.setDuration((long) (duration / 2.5f)); + + TranslateAnimation translate = new TranslateAnimation(translationX, 0, translationY, 0); + translate.setInterpolator(cutOff ? mTouchResponseInterpolator + : mLinearOutSlowInInterpolator); + translate.setDuration(duration); + + Animation clipAnimTB = new ClipRectTBAnimation( + clipStartY, clipStartY + mTmpRect.height(), + 0, appHeight, + translationYCorrection, 0, + mLinearOutSlowInInterpolator); + clipAnimTB.setInterpolator(mTouchResponseInterpolator); + clipAnimTB.setDuration(duration); + + // Quick fade-in from icon to app window + final long alphaDuration = duration / 4; + AlphaAnimation alpha = new AlphaAnimation(0.5f, 1); + alpha.setDuration(alphaDuration); + alpha.setInterpolator(mLinearOutSlowInInterpolator); + + AnimationSet set = new AnimationSet(false); + set.addAnimation(clipAnimLR); + set.addAnimation(clipAnimTB); + set.addAnimation(translate); + set.addAnimation(alpha); + set.setZAdjustment(Animation.ZORDER_TOP); + set.initialize(appWidth, appHeight, appWidth, appHeight); + anim = set; + } else { + final long duration; + switch (transit) { + case TRANSIT_OLD_ACTIVITY_OPEN: + case TRANSIT_OLD_ACTIVITY_CLOSE: + duration = mConfigShortAnimTime; + break; + default: + duration = DEFAULT_APP_TRANSITION_DURATION; + break; + } + if (transit == TRANSIT_OLD_WALLPAPER_INTRA_OPEN + || transit == TRANSIT_OLD_WALLPAPER_INTRA_CLOSE) { + // If we are on top of the wallpaper, we need an animation that + // correctly handles the wallpaper staying static behind all of + // the animated elements. To do this, will just have the existing + // element fade out. + anim = new AlphaAnimation(1, 0); + anim.setDetachWallpaper(true); + } else { + // For normal animations, the exiting element just holds in place. + anim = new AlphaAnimation(1, 1); + } + anim.setInterpolator(mDecelerateInterpolator); + anim.setDuration(duration); + anim.setFillAfter(true); + } + return anim; + } + + public Animation createScaleUpAnimationLocked(int transit, boolean enter, + Rect containingFrame, Rect startRect) { + Animation a; + setupDefaultNextAppTransitionStartRect(startRect, mTmpRect); + final int appWidth = containingFrame.width(); + final int appHeight = containingFrame.height(); + if (enter) { + // Entering app zooms out from the center of the initial rect. + float scaleW = mTmpRect.width() / (float) appWidth; + float scaleH = mTmpRect.height() / (float) appHeight; + Animation scale = new ScaleAnimation(scaleW, 1, scaleH, 1, + computePivot(mTmpRect.left, scaleW), + computePivot(mTmpRect.top, scaleH)); + scale.setInterpolator(mDecelerateInterpolator); + + Animation alpha = new AlphaAnimation(0, 1); + alpha.setInterpolator(mThumbnailFadeOutInterpolator); + + AnimationSet set = new AnimationSet(false); + set.addAnimation(scale); + set.addAnimation(alpha); + set.setDetachWallpaper(true); + a = set; + } else if (transit == TRANSIT_OLD_WALLPAPER_INTRA_OPEN + || transit == TRANSIT_OLD_WALLPAPER_INTRA_CLOSE) { + // If we are on top of the wallpaper, we need an animation that + // correctly handles the wallpaper staying static behind all of + // the animated elements. To do this, will just have the existing + // element fade out. + a = new AlphaAnimation(1, 0); + a.setDetachWallpaper(true); + } else { + // For normal animations, the exiting element just holds in place. + a = new AlphaAnimation(1, 1); + } + + // Pick the desired duration. If this is an inter-activity transition, + // it is the standard duration for that. Otherwise we use the longer + // task transition duration. + final long duration; + switch (transit) { + case TRANSIT_OLD_ACTIVITY_OPEN: + case TRANSIT_OLD_ACTIVITY_CLOSE: + duration = mConfigShortAnimTime; + break; + default: + duration = DEFAULT_APP_TRANSITION_DURATION; + break; + } + a.setDuration(duration); + a.setFillAfter(true); + a.setInterpolator(mDecelerateInterpolator); + a.initialize(appWidth, appHeight, appWidth, appHeight); + return a; + } + + /** + * This animation is created when we are doing a thumbnail transition, for the activity that is + * leaving, and the activity that is entering. + */ + public Animation createThumbnailEnterExitAnimationLocked(int thumbTransitState, + Rect containingFrame, int transit, HardwareBuffer thumbnailHeader, + Rect startRect) { + final int appWidth = containingFrame.width(); + final int appHeight = containingFrame.height(); + Animation a; + setupDefaultNextAppTransitionStartRect(startRect, mTmpRect); + final int thumbWidthI = thumbnailHeader != null ? thumbnailHeader.getWidth() : appWidth; + final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1; + final int thumbHeightI = thumbnailHeader != null ? thumbnailHeader.getHeight() : appHeight; + final float thumbHeight = thumbHeightI > 0 ? thumbHeightI : 1; + + switch (thumbTransitState) { + case THUMBNAIL_TRANSITION_ENTER_SCALE_UP: { + // Entering app scales up with the thumbnail + float scaleW = thumbWidth / appWidth; + float scaleH = thumbHeight / appHeight; + a = new ScaleAnimation(scaleW, 1, scaleH, 1, + computePivot(mTmpRect.left, scaleW), + computePivot(mTmpRect.top, scaleH)); + break; + } + case THUMBNAIL_TRANSITION_EXIT_SCALE_UP: { + // Exiting app while the thumbnail is scaling up should fade or stay in place + if (transit == TRANSIT_OLD_WALLPAPER_INTRA_OPEN) { + // Fade out while bringing up selected activity. This keeps the + // current activity from showing through a launching wallpaper + // activity. + a = new AlphaAnimation(1, 0); + } else { + // noop animation + a = new AlphaAnimation(1, 1); + } + break; + } + case THUMBNAIL_TRANSITION_ENTER_SCALE_DOWN: { + // Entering the other app, it should just be visible while we scale the thumbnail + // down above it + a = new AlphaAnimation(1, 1); + break; + } + case THUMBNAIL_TRANSITION_EXIT_SCALE_DOWN: { + // Exiting the current app, the app should scale down with the thumbnail + float scaleW = thumbWidth / appWidth; + float scaleH = thumbHeight / appHeight; + Animation scale = new ScaleAnimation(1, scaleW, 1, scaleH, + computePivot(mTmpRect.left, scaleW), + computePivot(mTmpRect.top, scaleH)); + + Animation alpha = new AlphaAnimation(1, 0); + + AnimationSet set = new AnimationSet(true); + set.addAnimation(scale); + set.addAnimation(alpha); + set.setZAdjustment(Animation.ZORDER_TOP); + a = set; + break; + } + default: + throw new RuntimeException("Invalid thumbnail transition state"); + } + + return prepareThumbnailAnimation(a, appWidth, appHeight, transit); + } + + /** + * This alternate animation is created when we are doing a thumbnail transition, for the + * activity that is leaving, and the activity that is entering. + */ + public Animation createAspectScaledThumbnailEnterExitAnimationLocked(int thumbTransitState, + int orientation, int transit, Rect containingFrame, Rect contentInsets, + @Nullable Rect surfaceInsets, @Nullable Rect stableInsets, boolean freeform, + Rect startRect, Rect defaultStartRect) { + Animation a; + final int appWidth = containingFrame.width(); + final int appHeight = containingFrame.height(); + setupDefaultNextAppTransitionStartRect(defaultStartRect, mTmpRect); + final int thumbWidthI = mTmpRect.width(); + final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1; + final int thumbHeightI = mTmpRect.height(); + final float thumbHeight = thumbHeightI > 0 ? thumbHeightI : 1; + final int thumbStartX = mTmpRect.left - containingFrame.left - contentInsets.left; + final int thumbStartY = mTmpRect.top - containingFrame.top; + + switch (thumbTransitState) { + case THUMBNAIL_TRANSITION_ENTER_SCALE_UP: + case THUMBNAIL_TRANSITION_EXIT_SCALE_DOWN: { + final boolean scaleUp = thumbTransitState == THUMBNAIL_TRANSITION_ENTER_SCALE_UP; + if (freeform && scaleUp) { + a = createAspectScaledThumbnailEnterFreeformAnimationLocked( + containingFrame, surfaceInsets, startRect, defaultStartRect); + } else if (freeform) { + a = createAspectScaledThumbnailExitFreeformAnimationLocked( + containingFrame, surfaceInsets, startRect, defaultStartRect); + } else { + AnimationSet set = new AnimationSet(true); + + // In portrait, we scale to fit the width + mTmpFromClipRect.set(containingFrame); + mTmpToClipRect.set(containingFrame); + + // Containing frame is in screen space, but we need the clip rect in the + // app space. + mTmpFromClipRect.offsetTo(0, 0); + mTmpToClipRect.offsetTo(0, 0); + + // Exclude insets region from the source clip. + mTmpFromClipRect.inset(contentInsets); + + if (shouldScaleDownThumbnailTransition(orientation)) { + // We scale the width and clip to the top/left square + float scale = + thumbWidth / (appWidth - contentInsets.left - contentInsets.right); + if (!mGridLayoutRecentsEnabled) { + int unscaledThumbHeight = (int) (thumbHeight / scale); + mTmpFromClipRect.bottom = mTmpFromClipRect.top + unscaledThumbHeight; + } + + Animation scaleAnim = new ScaleAnimation( + scaleUp ? scale : 1, scaleUp ? 1 : scale, + scaleUp ? scale : 1, scaleUp ? 1 : scale, + containingFrame.width() / 2f, + containingFrame.height() / 2f + contentInsets.top); + final float targetX = (mTmpRect.left - containingFrame.left); + final float x = containingFrame.width() / 2f + - containingFrame.width() / 2f * scale; + final float targetY = (mTmpRect.top - containingFrame.top); + float y = containingFrame.height() / 2f + - containingFrame.height() / 2f * scale; + + // During transition may require clipping offset from any top stable insets + // such as the statusbar height when statusbar is hidden + if (mLowRamRecentsEnabled && contentInsets.top == 0 && scaleUp) { + mTmpFromClipRect.top += stableInsets.top; + y += stableInsets.top; + } + final float startX = targetX - x; + final float startY = targetY - y; + Animation clipAnim = scaleUp + ? new ClipRectAnimation(mTmpFromClipRect, mTmpToClipRect) + : new ClipRectAnimation(mTmpToClipRect, mTmpFromClipRect); + Animation translateAnim = scaleUp + ? createCurvedMotion(startX, 0, startY - contentInsets.top, 0) + : createCurvedMotion(0, startX, 0, startY - contentInsets.top); + + set.addAnimation(clipAnim); + set.addAnimation(scaleAnim); + set.addAnimation(translateAnim); + + } else { + // In landscape, we don't scale at all and only crop + mTmpFromClipRect.bottom = mTmpFromClipRect.top + thumbHeightI; + mTmpFromClipRect.right = mTmpFromClipRect.left + thumbWidthI; + + Animation clipAnim = scaleUp + ? new ClipRectAnimation(mTmpFromClipRect, mTmpToClipRect) + : new ClipRectAnimation(mTmpToClipRect, mTmpFromClipRect); + Animation translateAnim = scaleUp + ? createCurvedMotion(thumbStartX, 0, + thumbStartY - contentInsets.top, 0) + : createCurvedMotion(0, thumbStartX, 0, + thumbStartY - contentInsets.top); + + set.addAnimation(clipAnim); + set.addAnimation(translateAnim); + } + a = set; + a.setZAdjustment(Animation.ZORDER_TOP); + } + break; + } + case THUMBNAIL_TRANSITION_EXIT_SCALE_UP: { + // Previous app window during the scale up + if (transit == TRANSIT_OLD_WALLPAPER_INTRA_OPEN) { + // Fade out the source activity if we are animating to a wallpaper + // activity. + a = new AlphaAnimation(1, 0); + } else { + a = new AlphaAnimation(1, 1); + } + break; + } + case THUMBNAIL_TRANSITION_ENTER_SCALE_DOWN: { + // Target app window during the scale down + if (transit == TRANSIT_OLD_WALLPAPER_INTRA_OPEN) { + // Fade in the destination activity if we are animating from a wallpaper + // activity. + a = new AlphaAnimation(0, 1); + } else { + a = new AlphaAnimation(1, 1); + } + break; + } + default: + throw new RuntimeException("Invalid thumbnail transition state"); + } + + return prepareThumbnailAnimationWithDuration(a, appWidth, appHeight, + THUMBNAIL_APP_TRANSITION_DURATION, mTouchResponseInterpolator); + } + + /** + * Prepares the specified animation with a standard duration, interpolator, etc. + */ + private Animation prepareThumbnailAnimation(Animation a, int appWidth, int appHeight, + int transit) { + // Pick the desired duration. If this is an inter-activity transition, + // it is the standard duration for that. Otherwise we use the longer + // task transition duration. + final int duration; + switch (transit) { + case TRANSIT_OLD_ACTIVITY_OPEN: + case TRANSIT_OLD_ACTIVITY_CLOSE: + duration = mConfigShortAnimTime; + break; + default: + duration = DEFAULT_APP_TRANSITION_DURATION; + break; + } + return prepareThumbnailAnimationWithDuration(a, appWidth, appHeight, duration, + mDecelerateInterpolator); + } + + + private Animation createAspectScaledThumbnailEnterFreeformAnimationLocked(Rect frame, + @Nullable Rect surfaceInsets, @Nullable Rect startRect, + @Nullable Rect defaultStartRect) { + getNextAppTransitionStartRect(startRect, defaultStartRect, mTmpRect); + return createAspectScaledThumbnailFreeformAnimationLocked(mTmpRect, frame, surfaceInsets, + true); + } + + private Animation createAspectScaledThumbnailExitFreeformAnimationLocked(Rect frame, + @Nullable Rect surfaceInsets, @Nullable Rect startRect, + @Nullable Rect defaultStartRect) { + getNextAppTransitionStartRect(startRect, defaultStartRect, mTmpRect); + return createAspectScaledThumbnailFreeformAnimationLocked(frame, mTmpRect, surfaceInsets, + false); + } + + private void getNextAppTransitionStartRect(Rect startRect, Rect defaultStartRect, Rect rect) { + if (startRect == null && defaultStartRect == null) { + Slog.e(mTag, "Starting rect for container not available", new Throwable()); + rect.setEmpty(); + } else { + rect.set(startRect != null ? startRect : defaultStartRect); + } + } + + private AnimationSet createAspectScaledThumbnailFreeformAnimationLocked(Rect sourceFrame, + Rect destFrame, @Nullable Rect surfaceInsets, boolean enter) { + final float sourceWidth = sourceFrame.width(); + final float sourceHeight = sourceFrame.height(); + final float destWidth = destFrame.width(); + final float destHeight = destFrame.height(); + final float scaleH = enter ? sourceWidth / destWidth : destWidth / sourceWidth; + final float scaleV = enter ? sourceHeight / destHeight : destHeight / sourceHeight; + AnimationSet set = new AnimationSet(true); + final int surfaceInsetsH = surfaceInsets == null + ? 0 : surfaceInsets.left + surfaceInsets.right; + final int surfaceInsetsV = surfaceInsets == null + ? 0 : surfaceInsets.top + surfaceInsets.bottom; + // We want the scaling to happen from the center of the surface. In order to achieve that, + // we need to account for surface insets that will be used to enlarge the surface. + final float scaleHCenter = ((enter ? destWidth : sourceWidth) + surfaceInsetsH) / 2; + final float scaleVCenter = ((enter ? destHeight : sourceHeight) + surfaceInsetsV) / 2; + final ScaleAnimation scale = enter + ? new ScaleAnimation(scaleH, 1, scaleV, 1, scaleHCenter, scaleVCenter) + : new ScaleAnimation(1, scaleH, 1, scaleV, scaleHCenter, scaleVCenter); + final int sourceHCenter = sourceFrame.left + sourceFrame.width() / 2; + final int sourceVCenter = sourceFrame.top + sourceFrame.height() / 2; + final int destHCenter = destFrame.left + destFrame.width() / 2; + final int destVCenter = destFrame.top + destFrame.height() / 2; + final int fromX = enter ? sourceHCenter - destHCenter : destHCenter - sourceHCenter; + final int fromY = enter ? sourceVCenter - destVCenter : destVCenter - sourceVCenter; + final TranslateAnimation translation = enter ? new TranslateAnimation(fromX, 0, fromY, 0) + : new TranslateAnimation(0, fromX, 0, fromY); + set.addAnimation(scale); + set.addAnimation(translation); + return set; + } + + /** + * @return whether the transition should show the thumbnail being scaled down. + */ + private boolean shouldScaleDownThumbnailTransition(int orientation) { + return mGridLayoutRecentsEnabled + || orientation == Configuration.ORIENTATION_PORTRAIT; + } + + private static int updateToTranslucentAnimIfNeeded(int anim, @TransitionOldType int transit) { + if (transit == TRANSIT_OLD_TRANSLUCENT_ACTIVITY_OPEN + && anim == R.anim.activity_open_enter) { + return R.anim.activity_translucent_open_enter; + } + if (transit == TRANSIT_OLD_TRANSLUCENT_ACTIVITY_CLOSE + && anim == R.anim.activity_close_exit) { + return R.anim.activity_translucent_close_exit; + } + return anim; + } + + /** + * Calculates the duration for the clip reveal animation. If the clip is "cut off", meaning that + * the start rect is outside of the target rect, and there is a lot of movement going on. + * + * @param cutOff whether the start rect was not fully contained by the end rect + * @param translationX the total translation the surface moves in x direction + * @param translationY the total translation the surfaces moves in y direction + * @param displayFrame our display frame + * + * @return the duration of the clip reveal animation, in milliseconds + */ + private static long calculateClipRevealTransitionDuration(boolean cutOff, float translationX, + float translationY, Rect displayFrame) { + if (!cutOff) { + return DEFAULT_APP_TRANSITION_DURATION; + } + final float fraction = Math.max(Math.abs(translationX) / displayFrame.width(), + Math.abs(translationY) / displayFrame.height()); + return (long) (DEFAULT_APP_TRANSITION_DURATION + fraction + * (MAX_CLIP_REVEAL_TRANSITION_DURATION - DEFAULT_APP_TRANSITION_DURATION)); + } + + /** + * Prepares the specified animation with a standard duration, interpolator, etc. + */ + private static Animation prepareThumbnailAnimationWithDuration(Animation a, int appWidth, + int appHeight, long duration, Interpolator interpolator) { + if (duration > 0) { + a.setDuration(duration); + } + a.setFillAfter(true); + if (interpolator != null) { + a.setInterpolator(interpolator); + } + a.initialize(appWidth, appHeight, appWidth, appHeight); + return a; + } + + private static Animation createCurvedMotion(float fromX, float toX, float fromY, float toY) { + return new TranslateAnimation(fromX, toX, fromY, toY); + } + + /** + * Compute the pivot point for an animation that is scaling from a small + * rect on screen to a larger rect. The pivot point varies depending on + * the distance between the inner and outer edges on both sides. This + * function computes the pivot point for one dimension. + * @param startPos Offset from left/top edge of outer rectangle to + * left/top edge of inner rectangle. + * @param finalScale The scaling factor between the size of the outer + * and inner rectangles. + */ + public static float computePivot(int startPos, float finalScale) { + + /* + Theorem of intercepting lines: + + + + +-----------------------------------------------+ + | | | | + | | | | + | | | | + | | | | + x | y | | | + | | | | + | | | | + | | | | + | | | | + | + | +--------------------+ | + | | | | | + | | | | | + | | | | | + | | | | | + | | | | | + | | | | | + | | | | | + | | | | | + | | | | | + | | | | | + | | | | | + | | | | | + | | | | | + | | | | | + | | | | | + | | | | | + | | | | | + | | +--------------------+ | + | | | + | | | + | | | + | | | + | | | + | | | + | | | + | +-----------------------------------------------+ + | + | + | + | + | + | + | + | + | + + ++ + p ++ + + scale = (x - y) / x + <=> x = -y / (scale - 1) + */ + final float denom = finalScale - 1; + if (Math.abs(denom) < .0001f) { + return startPos; + } + return -startPos / denom; + } + + @Nullable + public static Animation loadAnimationSafely(Context context, int resId, String tag) { + try { + return AnimationUtils.loadAnimation(context, resId); + } catch (Resources.NotFoundException e) { + Slog.w(tag, "Unable to load animation resource", e); + return null; + } + } + + public static Animation createHiddenByKeyguardExit(Context context, + LogDecelerateInterpolator interpolator, boolean onWallpaper, + boolean goingToNotificationShade, boolean subtleAnimation) { + if (goingToNotificationShade) { + return AnimationUtils.loadAnimation(context, R.anim.lock_screen_behind_enter_fade_in); + } + + final int resource; + if (subtleAnimation) { + resource = R.anim.lock_screen_behind_enter_subtle; + } else if (onWallpaper) { + resource = R.anim.lock_screen_behind_enter_wallpaper; + } else { + resource = R.anim.lock_screen_behind_enter; + } + + AnimationSet set = (AnimationSet) AnimationUtils.loadAnimation(context, resource); + + // TODO: Use XML interpolators when we have log interpolators available in XML. + final List<Animation> animations = set.getAnimations(); + for (int i = animations.size() - 1; i >= 0; --i) { + animations.get(i).setInterpolator(interpolator); + } + + return set; + } +} diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl index 892c5a53527b..50bbfc5ccb08 100644 --- a/core/java/com/android/internal/view/IInputMethodManager.aidl +++ b/core/java/com/android/internal/view/IInputMethodManager.aidl @@ -91,11 +91,12 @@ interface IInputMethodManager { /** Remove the IME surface. Requires passing the currently focused window. */ oneway void removeImeSurfaceFromWindow(in IBinder windowToken, in IVoidResultCallback resultCallback); - void startProtoDump(in byte[] protoDump, int source, String where); + oneway void startProtoDump(in byte[] protoDump, int source, String where, + in IVoidResultCallback resultCallback); oneway void isImeTraceEnabled(in IBooleanResultCallback resultCallback); // Starts an ime trace. - void startImeTrace(); + oneway void startImeTrace(in IVoidResultCallback resultCallback); // Stops an ime trace. - void stopImeTrace(); + oneway void stopImeTrace(in IVoidResultCallback resultCallback); } diff --git a/core/jni/android_view_InputDevice.cpp b/core/jni/android_view_InputDevice.cpp index 4eaa016df6f2..9cc72437a023 100644 --- a/core/jni/android_view_InputDevice.cpp +++ b/core/jni/android_view_InputDevice.cpp @@ -70,7 +70,8 @@ jobject android_view_InputDevice_create(JNIEnv* env, const InputDeviceInfo& devi deviceInfo.isExternal(), deviceInfo.getSources(), deviceInfo.getKeyboardType(), kcmObj.get(), deviceInfo.hasVibrator(), hasMic, - deviceInfo.hasButtonUnderPad(), deviceInfo.hasSensor())); + deviceInfo.hasButtonUnderPad(), deviceInfo.hasSensor(), + deviceInfo.hasBattery())); const std::vector<InputDeviceInfo::MotionRange>& ranges = deviceInfo.getMotionRanges(); for (const InputDeviceInfo::MotionRange& range: ranges) { @@ -90,9 +91,10 @@ int register_android_view_InputDevice(JNIEnv* env) gInputDeviceClassInfo.clazz = FindClassOrDie(env, "android/view/InputDevice"); gInputDeviceClassInfo.clazz = MakeGlobalRefOrDie(env, gInputDeviceClassInfo.clazz); - gInputDeviceClassInfo.ctor = GetMethodIDOrDie(env, gInputDeviceClassInfo.clazz, "<init>", - "(IIILjava/lang/String;IILjava/lang/" - "String;ZIILandroid/view/KeyCharacterMap;ZZZZ)V"); + gInputDeviceClassInfo.ctor = + GetMethodIDOrDie(env, gInputDeviceClassInfo.clazz, "<init>", + "(IIILjava/lang/String;IILjava/lang/" + "String;ZIILandroid/view/KeyCharacterMap;ZZZZZ)V"); gInputDeviceClassInfo.addMotionRange = GetMethodIDOrDie(env, gInputDeviceClassInfo.clazz, "addMotionRange", "(IIFFFFF)V"); diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp index 4ef63ae93016..05fcaec82f84 100644 --- a/core/jni/android_view_SurfaceControl.cpp +++ b/core/jni/android_view_SurfaceControl.cpp @@ -27,6 +27,7 @@ #include <android-base/chrono_utils.h> #include <android/graphics/region.h> #include <android/gui/BnScreenCaptureListener.h> +#include <android/os/IInputConstants.h> #include <android_runtime/AndroidRuntime.h> #include <android_runtime/android_hardware_HardwareBuffer.h> #include <android_runtime/android_view_Surface.h> @@ -110,10 +111,12 @@ static struct { static struct { jfieldID pixelFormat; jfieldID sourceCrop; - jfieldID frameScale; + jfieldID frameScaleX; + jfieldID frameScaleY; jfieldID captureSecureLayers; jfieldID allowProtected; jfieldID uid; + jfieldID grayscale; } gCaptureArgsClassInfo; static struct { @@ -380,13 +383,17 @@ static void getCaptureArgs(JNIEnv* env, jobject captureArgsObject, CaptureArgs& captureArgs.sourceCrop = rectFromObj(env, env->GetObjectField(captureArgsObject, gCaptureArgsClassInfo.sourceCrop)); - captureArgs.frameScale = - env->GetFloatField(captureArgsObject, gCaptureArgsClassInfo.frameScale); + captureArgs.frameScaleX = + env->GetFloatField(captureArgsObject, gCaptureArgsClassInfo.frameScaleX); + captureArgs.frameScaleY = + env->GetFloatField(captureArgsObject, gCaptureArgsClassInfo.frameScaleY); captureArgs.captureSecureLayers = env->GetBooleanField(captureArgsObject, gCaptureArgsClassInfo.captureSecureLayers); captureArgs.allowProtected = env->GetBooleanField(captureArgsObject, gCaptureArgsClassInfo.allowProtected); captureArgs.uid = env->GetLongField(captureArgsObject, gCaptureArgsClassInfo.uid); + captureArgs.grayscale = + env->GetBooleanField(captureArgsObject, gCaptureArgsClassInfo.grayscale); } static DisplayCaptureArgs displayCaptureArgsFromObject(JNIEnv* env, @@ -1619,7 +1626,8 @@ static void nativeSetFrameTimelineVsync(JNIEnv* env, jclass clazz, jlong transac jlong frameTimelineVsyncId) { auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj); - transaction->setFrameTimelineVsync(frameTimelineVsyncId); + transaction->setFrameTimelineInfo( + {frameTimelineVsyncId, android::os::IInputConstants::INVALID_INPUT_EVENT_ID}); } class JankDataListenerWrapper : public JankDataListener { @@ -2032,12 +2040,14 @@ int register_android_view_SurfaceControl(JNIEnv* env) gCaptureArgsClassInfo.pixelFormat = GetFieldIDOrDie(env, captureArgsClazz, "mPixelFormat", "I"); gCaptureArgsClassInfo.sourceCrop = GetFieldIDOrDie(env, captureArgsClazz, "mSourceCrop", "Landroid/graphics/Rect;"); - gCaptureArgsClassInfo.frameScale = GetFieldIDOrDie(env, captureArgsClazz, "mFrameScale", "F"); + gCaptureArgsClassInfo.frameScaleX = GetFieldIDOrDie(env, captureArgsClazz, "mFrameScaleX", "F"); + gCaptureArgsClassInfo.frameScaleY = GetFieldIDOrDie(env, captureArgsClazz, "mFrameScaleY", "F"); gCaptureArgsClassInfo.captureSecureLayers = GetFieldIDOrDie(env, captureArgsClazz, "mCaptureSecureLayers", "Z"); gCaptureArgsClassInfo.allowProtected = GetFieldIDOrDie(env, captureArgsClazz, "mAllowProtected", "Z"); gCaptureArgsClassInfo.uid = GetFieldIDOrDie(env, captureArgsClazz, "mUid", "J"); + gCaptureArgsClassInfo.grayscale = GetFieldIDOrDie(env, captureArgsClazz, "mGrayscale", "Z"); jclass displayCaptureArgsClazz = FindClassOrDie(env, "android/view/SurfaceControl$DisplayCaptureArgs"); diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp index c76a5d3dd9fa..c5a955976867 100644 --- a/core/jni/com_android_internal_os_Zygote.cpp +++ b/core/jni/com_android_internal_os_Zygote.cpp @@ -70,7 +70,6 @@ #include <bionic/malloc.h> #include <bionic/mte.h> #include <cutils/fs.h> -#include <cutils/memory.h> #include <cutils/multiuser.h> #include <cutils/sockets.h> #include <private/android_filesystem_config.h> @@ -621,13 +620,6 @@ static void PreApplicationInit() { // Set the jemalloc decay time to 1. mallopt(M_DECAY_TIME, 1); - - // Avoid potentially expensive memory mitigations, mostly meant for system - // processes, in apps. These may cause app compat problems, use more memory, - // or reduce performance. While it would be nice to have them for apps, - // we will have to wait until they are proven out, have more efficient - // hardware, and/or apply them only to new applications. - process_disable_memory_mitigations(); } static void SetUpSeccompFilter(uid_t uid, bool is_child_zygote) { @@ -1785,6 +1777,14 @@ static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray gids, break; } mallopt(M_BIONIC_SET_HEAP_TAGGING_LEVEL, heap_tagging_level); + + // Avoid heap zero initialization for applications without MTE. Zero init may + // cause app compat problems, use more memory, or reduce performance. While it + // would be nice to have them for apps, we will have to wait until they are + // proven out, have more efficient hardware, and/or apply them only to new + // applications. + mallopt(M_BIONIC_ZERO_INIT, 0); + // Now that we've used the flag, clear it so that we don't pass unknown flags to the ART runtime. runtime_flags &= ~RuntimeFlags::MEMORY_TAG_LEVEL_MASK; diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 4acdb1663403..f447cd205516 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -5168,6 +5168,11 @@ <permission android:name="android.permission.MANAGE_SEARCH_UI" android:protectionLevel="signature" /> + <!-- @SystemApi Allows an application to manage the smartspace service. + @hide <p>Not for use by third-party applications.</p> --> + <permission android:name="android.permission.MANAGE_SMARTSPACE" + android:protectionLevel="signature" /> + <!-- Allows an app to set the theme overlay in /vendor/overlay being used. @hide <p>Not for use by third-party applications.</p> --> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 5e0cda69911b..01b8efafa2fd 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -3800,6 +3800,15 @@ --> <string name="config_defaultSearchUiService" translatable="false"></string> + <!-- The package name for the system's smartspace service. + This service returns smartspace results. + + This service must be trusted, as it can be activated without explicit consent of the user. + If no service with the specified name exists on the device, smartspace will be disabled. + Example: "com.android.intelligence/.SmartspaceService" +--> + <string name="config_defaultSmartspaceService" translatable="false"></string> + <!-- The package name for the system's speech recognition service. This service must be trusted, as it can be activated without explicit consent of the user. Example: "com.android.speech/.RecognitionService" diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index dfccdf4bd9a5..815330ff1851 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -3498,6 +3498,7 @@ <java-symbol type="string" name="config_defaultAppPredictionService" /> <java-symbol type="string" name="config_defaultContentSuggestionsService" /> <java-symbol type="string" name="config_defaultSearchUiService" /> + <java-symbol type="string" name="config_defaultSmartspaceService" /> <java-symbol type="string" name="config_defaultMusicRecognitionService" /> <java-symbol type="string" name="config_defaultAttentionService" /> <java-symbol type="string" name="config_defaultRotationResolverService" /> diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml index bb826deb4eff..151a320494b4 100644 --- a/core/tests/coretests/AndroidManifest.xml +++ b/core/tests/coretests/AndroidManifest.xml @@ -35,6 +35,8 @@ android:label="@string/permlab_testDenied" android:description="@string/permdesc_testDenied" /> + <uses-permission android:name="com.android.frameworks.coretests.permission.TEST_GRANTED" /> + <uses-permission android:name="android.permission.ACCESS_CACHE_FILESYSTEM" /> <uses-permission android:name="android.permission.ACCESS_DOWNLOAD_MANAGER" /> <uses-permission android:name="android.permission.ACCESS_DOWNLOAD_MANAGER_ADVANCED" /> @@ -76,7 +78,6 @@ <uses-permission android:name="android.permission.WRITE_SETTINGS" /> <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" /> <uses-permission android:name="android.permission.WRITE_SMS"/> - <uses-permission android:name="android.permission.TEST_GRANTED" /> <uses-permission android:name="android.permission.CHANGE_COMPONENT_ENABLED_STATE" /> <uses-permission android:name="com.google.android.googleapps.permission.ACCESS_GOOGLE_PASSWORD" /> <uses-permission android:name="com.google.android.googleapps.permission.GOOGLE_AUTH" /> @@ -1455,6 +1456,7 @@ </intent-filter> </receiver> <receiver android:name="android.app.activity.RemoteGrantedReceiver" + android:process=":remoteReceiver" android:permission="com.android.frameworks.coretests.permission.TEST_GRANTED" android:exported="true"> <intent-filter android:priority="2"> @@ -1462,6 +1464,7 @@ </intent-filter> </receiver> <receiver android:name="android.app.activity.RemoteDeniedReceiver" + android:process=":remoteReceiver" android:permission="com.android.frameworks.coretests.permission.TEST_DENIED" android:exported="true"> <intent-filter android:priority="2"> diff --git a/core/tests/coretests/src/android/app/activity/BroadcastTest.java b/core/tests/coretests/src/android/app/activity/BroadcastTest.java index 0f81896692c0..d79c2fe19ce2 100644 --- a/core/tests/coretests/src/android/app/activity/BroadcastTest.java +++ b/core/tests/coretests/src/android/app/activity/BroadcastTest.java @@ -56,6 +56,8 @@ public class BroadcastTest extends ActivityTestsBase { "com.android.frameworks.coretests.activity.BROADCAST_MULTI"; public static final String BROADCAST_ABORT = "com.android.frameworks.coretests.activity.BROADCAST_ABORT"; + public static final String BROADCAST_RESULT = + "com.android.frameworks.coretests.activity.BROADCAST_RESULT"; public static final String BROADCAST_STICKY1 = "com.android.frameworks.coretests.activity.BROADCAST_STICKY1"; @@ -106,7 +108,14 @@ public class BroadcastTest extends ActivityTestsBase { } public Intent makeBroadcastIntent(String action) { + return makeBroadcastIntent(action, false); + } + + public Intent makeBroadcastIntent(String action, boolean makeImplicit) { Intent intent = new Intent(action, null); + if (makeImplicit) { + intent.addFlags(intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); + } intent.putExtra("caller", mCallTarget); return intent; } @@ -277,7 +286,7 @@ public class BroadcastTest extends ActivityTestsBase { map.putString("foo", "you"); map.putString("remove", "me"); getContext().sendOrderedBroadcast( - new Intent("com.android.frameworks.coretests.activity.BROADCAST_RESULT"), + makeBroadcastIntent(BROADCAST_RESULT, true), null, broadcastReceiver, null, 1, "foo", map); while (!broadcastReceiver.mHaveResult) { try { @@ -424,10 +433,13 @@ public class BroadcastTest extends ActivityTestsBase { public void testLocalReceivePermissionGranted() throws Exception { setExpectedReceivers(new String[]{RECEIVER_LOCAL}); - getContext().sendBroadcast(makeBroadcastIntent(BROADCAST_LOCAL_GRANTED)); + getContext().sendBroadcast(makeBroadcastIntent(BROADCAST_LOCAL_GRANTED, true)); waitForResultOrThrow(BROADCAST_TIMEOUT); } + /* + // TODO: multi-package test b/c self-target broadcasts are always allowed + // even when gated on ungranted permissions public void testLocalReceivePermissionDenied() throws Exception { setExpectedReceivers(new String[]{RECEIVER_RESULTS}); @@ -438,16 +450,17 @@ public class BroadcastTest extends ActivityTestsBase { }; getContext().sendOrderedBroadcast( - makeBroadcastIntent(BROADCAST_LOCAL_DENIED), + makeBroadcastIntent(BROADCAST_LOCAL_DENIED, true), null, finish, null, Activity.RESULT_CANCELED, null, null); waitForResultOrThrow(BROADCAST_TIMEOUT); } + */ public void testLocalBroadcastPermissionGranted() throws Exception { setExpectedReceivers(new String[]{RECEIVER_LOCAL}); getContext().sendBroadcast( - makeBroadcastIntent(BROADCAST_LOCAL), + makeBroadcastIntent(BROADCAST_LOCAL, true), PERMISSION_GRANTED); waitForResultOrThrow(BROADCAST_TIMEOUT); } @@ -462,7 +475,7 @@ public class BroadcastTest extends ActivityTestsBase { }; getContext().sendOrderedBroadcast( - makeBroadcastIntent(BROADCAST_LOCAL), + makeBroadcastIntent(BROADCAST_LOCAL, true), PERMISSION_DENIED, finish, null, Activity.RESULT_CANCELED, null, null); waitForResultOrThrow(BROADCAST_TIMEOUT); @@ -470,10 +483,13 @@ public class BroadcastTest extends ActivityTestsBase { public void testRemoteReceivePermissionGranted() throws Exception { setExpectedReceivers(new String[]{RECEIVER_REMOTE}); - getContext().sendBroadcast(makeBroadcastIntent(BROADCAST_REMOTE_GRANTED)); + getContext().sendBroadcast(makeBroadcastIntent(BROADCAST_REMOTE_GRANTED, true)); waitForResultOrThrow(BROADCAST_TIMEOUT); } + /* + // TODO: multi-package test b/c self-target broadcasts are always allowed + // even when gated on ungranted permissions public void testRemoteReceivePermissionDenied() throws Exception { setExpectedReceivers(new String[]{RECEIVER_RESULTS}); @@ -484,16 +500,17 @@ public class BroadcastTest extends ActivityTestsBase { }; getContext().sendOrderedBroadcast( - makeBroadcastIntent(BROADCAST_REMOTE_DENIED), + makeBroadcastIntent(BROADCAST_REMOTE_DENIED, true), null, finish, null, Activity.RESULT_CANCELED, null, null); waitForResultOrThrow(BROADCAST_TIMEOUT); } + */ public void testRemoteBroadcastPermissionGranted() throws Exception { setExpectedReceivers(new String[]{RECEIVER_REMOTE}); getContext().sendBroadcast( - makeBroadcastIntent(BROADCAST_REMOTE), + makeBroadcastIntent(BROADCAST_REMOTE, true), PERMISSION_GRANTED); waitForResultOrThrow(BROADCAST_TIMEOUT); } @@ -508,7 +525,7 @@ public class BroadcastTest extends ActivityTestsBase { }; getContext().sendOrderedBroadcast( - makeBroadcastIntent(BROADCAST_REMOTE), + makeBroadcastIntent(BROADCAST_REMOTE, true), PERMISSION_DENIED, finish, null, Activity.RESULT_CANCELED, null, null); waitForResultOrThrow(BROADCAST_TIMEOUT); @@ -516,13 +533,13 @@ public class BroadcastTest extends ActivityTestsBase { public void testReceiverCanNotRegister() throws Exception { setExpectedReceivers(new String[]{RECEIVER_LOCAL}); - getContext().sendBroadcast(makeBroadcastIntent(BROADCAST_FAIL_REGISTER)); + getContext().sendBroadcast(makeBroadcastIntent(BROADCAST_FAIL_REGISTER, true)); waitForResultOrThrow(BROADCAST_TIMEOUT); } public void testReceiverCanNotBind() throws Exception { setExpectedReceivers(new String[]{RECEIVER_LOCAL}); - getContext().sendBroadcast(makeBroadcastIntent(BROADCAST_FAIL_BIND)); + getContext().sendBroadcast(makeBroadcastIntent(BROADCAST_FAIL_BIND, true)); waitForResultOrThrow(BROADCAST_TIMEOUT); } diff --git a/core/tests/coretests/src/android/app/activity/LaunchpadActivity.java b/core/tests/coretests/src/android/app/activity/LaunchpadActivity.java index 766245600d13..0b21fa90c1c4 100644 --- a/core/tests/coretests/src/android/app/activity/LaunchpadActivity.java +++ b/core/tests/coretests/src/android/app/activity/LaunchpadActivity.java @@ -253,16 +253,16 @@ public class LaunchpadActivity extends Activity { sendBroadcast(makeBroadcastIntent(BROADCAST_REGISTERED)); } else if (BROADCAST_LOCAL.equals(action)) { setExpectedReceivers(new String[]{RECEIVER_LOCAL}); - sendBroadcast(makeBroadcastIntent(BROADCAST_LOCAL)); + sendBroadcast(makeBroadcastIntent(BROADCAST_LOCAL, true)); } else if (BROADCAST_REMOTE.equals(action)) { setExpectedReceivers(new String[]{RECEIVER_REMOTE}); - sendBroadcast(makeBroadcastIntent(BROADCAST_REMOTE)); + sendBroadcast(makeBroadcastIntent(BROADCAST_REMOTE, true)); } else if (BROADCAST_ALL.equals(action)) { setExpectedReceivers(new String[]{ RECEIVER_REMOTE, RECEIVER_REG, RECEIVER_LOCAL}); registerMyReceiver(new IntentFilter(BROADCAST_ALL)); sCallingTest.addIntermediate("after-register"); - sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_ALL), null); + sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_ALL, true), null); } else if (BROADCAST_MULTI.equals(action)) { setExpectedReceivers(new String[]{ RECEIVER_REMOTE, RECEIVER_REG, RECEIVER_LOCAL, @@ -277,23 +277,26 @@ public class LaunchpadActivity extends Activity { RECEIVER_REMOTE, RECEIVER_LOCAL}); registerMyReceiver(new IntentFilter(BROADCAST_ALL)); sCallingTest.addIntermediate("after-register"); - sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_ALL), null); - sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_ALL), null); - sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_ALL), null); - sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_LOCAL), null); - sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_REMOTE), null); - sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_LOCAL), null); - sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_REMOTE), null); - sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_ALL), null); - sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_ALL), null); - sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_ALL), null); - sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_REPEAT), null); + final Intent allIntent = makeBroadcastIntent(BROADCAST_ALL, true); + final Intent localIntent = makeBroadcastIntent(BROADCAST_LOCAL, true); + final Intent remoteIntent = makeBroadcastIntent(BROADCAST_REMOTE, true); + sendOrderedBroadcast(allIntent, null); + sendOrderedBroadcast(allIntent, null); + sendOrderedBroadcast(allIntent, null); + sendOrderedBroadcast(localIntent, null); + sendOrderedBroadcast(remoteIntent, null); + sendOrderedBroadcast(localIntent, null); + sendOrderedBroadcast(remoteIntent, null); + sendOrderedBroadcast(allIntent, null); + sendOrderedBroadcast(allIntent, null); + sendOrderedBroadcast(allIntent, null); + sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_REPEAT, true), null); } else if (BROADCAST_ABORT.equals(action)) { setExpectedReceivers(new String[]{ RECEIVER_REMOTE, RECEIVER_ABORT}); registerMyReceiver(new IntentFilter(BROADCAST_ABORT)); sCallingTest.addIntermediate("after-register"); - sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_ABORT), null); + sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_ABORT, true), null); } else if (BROADCAST_STICKY1.equals(action)) { setExpectedReceivers(new String[]{RECEIVER_REG}); setExpectedData(new String[]{DATA_1}); @@ -436,7 +439,14 @@ public class LaunchpadActivity extends Activity { } private Intent makeBroadcastIntent(String action) { + return makeBroadcastIntent(action, false); + } + + private Intent makeBroadcastIntent(String action, boolean makeImplicit) { Intent intent = new Intent(action, null); + if (makeImplicit) { + intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); + } intent.putExtra("caller", mCallTarget); return intent; } diff --git a/core/tests/coretests/src/android/app/activity/LocalDeniedReceiver.java b/core/tests/coretests/src/android/app/activity/LocalDeniedReceiver.java index 2120a1db463c..16ea73f30937 100644 --- a/core/tests/coretests/src/android/app/activity/LocalDeniedReceiver.java +++ b/core/tests/coretests/src/android/app/activity/LocalDeniedReceiver.java @@ -23,7 +23,7 @@ import android.os.RemoteException; import android.os.IBinder; import android.os.Parcel; -class LocalDeniedReceiver extends BroadcastReceiver { +public class LocalDeniedReceiver extends BroadcastReceiver { public LocalDeniedReceiver() { } diff --git a/core/tests/coretests/src/android/app/activity/RemoteDeniedReceiver.java b/core/tests/coretests/src/android/app/activity/RemoteDeniedReceiver.java index 7c89346e820d..5c1ded93e1c3 100644 --- a/core/tests/coretests/src/android/app/activity/RemoteDeniedReceiver.java +++ b/core/tests/coretests/src/android/app/activity/RemoteDeniedReceiver.java @@ -23,7 +23,7 @@ import android.os.RemoteException; import android.os.IBinder; import android.os.Parcel; -class RemoteDeniedReceiver extends BroadcastReceiver { +public class RemoteDeniedReceiver extends BroadcastReceiver { public RemoteDeniedReceiver() { } diff --git a/core/tests/coretests/src/android/content/pm/SignatureTest.java b/core/tests/coretests/src/android/content/pm/SignatureTest.java index f0b4af6fc44f..19458da796e8 100644 --- a/core/tests/coretests/src/android/content/pm/SignatureTest.java +++ b/core/tests/coretests/src/android/content/pm/SignatureTest.java @@ -54,6 +54,32 @@ public class SignatureTest extends TestCase { assertFalse(Signature.areEffectiveMatch(asArray(A, M), asArray(A, B))); } + public void testHashCode_doesNotIncludeFlags() throws Exception { + // Some classes rely on the hash code not including the flags / capabilities for the signer + // to verify Set membership. This test verifies two signers with the same signature but + // different flags have the same hash code. + Signature signatureAWithAllCaps = new Signature(A.toCharsString()); + // There are currently 5 capabilities that can be assigned to a previous signer, although + // for the purposes of this test all that matters is that the two flag values are distinct. + signatureAWithAllCaps.setFlags(31); + Signature signatureAWithNoCaps = new Signature(A.toCharsString()); + signatureAWithNoCaps.setFlags(0); + + assertEquals(signatureAWithAllCaps.hashCode(), signatureAWithNoCaps.hashCode()); + } + + public void testEquals_doesNotIncludeFlags() throws Exception { + // Similar to above some classes rely on equals only comparing the signature arrays + // for equality without including the flags. This test verifies two signers with the + // same signature but different flags are still considered equal. + Signature signatureAWithAllCaps = new Signature(A.toCharsString()); + signatureAWithAllCaps.setFlags(31); + Signature signatureAWithNoCaps = new Signature(A.toCharsString()); + signatureAWithNoCaps.setFlags(0); + + assertEquals(signatureAWithAllCaps, signatureAWithNoCaps); + } + private static Signature[] asArray(Signature... s) { return s; } diff --git a/core/tests/coretests/src/android/hardware/input/InputDeviceSensorManagerTest.java b/core/tests/coretests/src/android/hardware/input/InputDeviceSensorManagerTest.java index b319886ae466..341ee37aee39 100644 --- a/core/tests/coretests/src/android/hardware/input/InputDeviceSensorManagerTest.java +++ b/core/tests/coretests/src/android/hardware/input/InputDeviceSensorManagerTest.java @@ -149,7 +149,7 @@ public class InputDeviceSensorManagerTest { 0 /* vendorId */, 0 /* productId */, "descriptor", true /* isExternal */, 0 /* sources */, 0 /* keyboardType */, null /* keyCharacterMap */, false /* hasVibrator */, false /* hasMicrophone */, false /* hasButtonUnderpad */, - true /* hasSensor */); + true /* hasSensor */, false /* hasBattery */); assertTrue(d.hasSensor()); return d; } diff --git a/core/tests/overlaytests/device/AndroidTest.xml b/core/tests/overlaytests/device/AndroidTest.xml index ebbdda559ed2..2d7d9b450c8c 100644 --- a/core/tests/overlaytests/device/AndroidTest.xml +++ b/core/tests/overlaytests/device/AndroidTest.xml @@ -19,17 +19,13 @@ <option name="test-suite-tag" value="apct" /> <option name="test-suite-tag" value="apct-instrumentation" /> + <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" /> <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher"> <option name="cleanup" value="true" /> <option name="remount-system" value="true" /> <option name="push" value="OverlayDeviceTests.apk->/system/app/OverlayDeviceTests.apk" /> </target_preparer> - - <!-- Reboot to have the test APK scanned by PM and reboot after to remove the test APK. --> - <target_preparer class="com.android.tradefed.targetprep.RebootTargetPreparer"> - <option name="pre-reboot" value="true" /> - <option name="post-reboot" value="true" /> - </target_preparer> + <target_preparer class="com.android.tradefed.targetprep.RebootTargetPreparer" /> <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup"> <option name="cleanup-apks" value="true" /> diff --git a/graphics/java/android/graphics/RenderNode.java b/graphics/java/android/graphics/RenderNode.java index c1310a9214e0..4a92cf11fa5c 100644 --- a/graphics/java/android/graphics/RenderNode.java +++ b/graphics/java/android/graphics/RenderNode.java @@ -693,6 +693,32 @@ public final class RenderNode { throw new IllegalArgumentException("Unrecognized outline?"); } + /** @hide */ + public boolean clearStretch() { + return nClearStretch(mNativeRenderNode); + } + + /** @hide */ + public boolean stretch(float left, float top, float right, float bottom, + float vecX, float vecY, float maxStretchAmount) { + if (1.0 < vecX || vecX < -1.0) { + throw new IllegalArgumentException("vecX must be in the range [-1, 1], was " + vecX); + } + if (1.0 < vecY || vecY < -1.0) { + throw new IllegalArgumentException("vecY must be in the range [-1, 1], was " + vecY); + } + if (top <= bottom || right <= left) { + throw new IllegalArgumentException( + "Stretch region must not be empty, got " + + new RectF(left, top, right, bottom).toString()); + } + if (maxStretchAmount <= 0.0f) { + throw new IllegalArgumentException( + "The max stretch amount must be >0, got " + maxStretchAmount); + } + return nStretch(mNativeRenderNode, left, top, right, bottom, vecX, vecY, maxStretchAmount); + } + /** * Checks if the RenderNode has a shadow. That is, if the combination of {@link #getElevation()} * and {@link #getTranslationZ()} is greater than zero, there is an {@link Outline} set with @@ -1638,6 +1664,13 @@ public final class RenderNode { private static native boolean nSetOutlineNone(long renderNode); @CriticalNative + private static native boolean nClearStretch(long renderNode); + + @CriticalNative + private static native boolean nStretch(long renderNode, float left, float top, float right, + float bottom, float vecX, float vecY, float maxStretch); + + @CriticalNative private static native boolean nHasShadow(long renderNode); @CriticalNative diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java b/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java index 164bc8669525..75ac61a22cab 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java @@ -363,6 +363,11 @@ public class AndroidKeyStoreProvider extends Provider { } } + if (response.iSecurityLevel == null) { + // This seems to be a pure certificate entry, nothing to return here. + return null; + } + Integer keymasterAlgorithm = null; // We just need one digest for the algorithm name int keymasterDigest = -1; diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java index 5e7f6482ebed..07169cedc1d9 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java @@ -490,7 +490,7 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi { int[] keymasterEncryptionPaddings = KeyProperties.EncryptionPadding.allToKeymaster( spec.getEncryptionPaddings()); - if (((spec.getPurposes() & KeyProperties.PURPOSE_DECRYPT) != 0) + if (((spec.getPurposes() & KeyProperties.PURPOSE_ENCRYPT) != 0) && (spec.isRandomizedEncryptionRequired())) { for (int keymasterPadding : keymasterEncryptionPaddings) { if (!KeymasterUtils diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java index 122f91720bbd..ffeabd876b81 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java @@ -49,6 +49,7 @@ import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.List; import java.util.Objects; +import java.util.concurrent.Executor; /** * Encapsulates the data and UI elements of a bubble. @@ -58,6 +59,7 @@ public class Bubble implements BubbleViewProvider { private static final String TAG = "Bubble"; private final String mKey; + private final Executor mMainExecutor; private long mLastUpdated; private long mLastAccessed; @@ -156,7 +158,8 @@ public class Bubble implements BubbleViewProvider { * Note: Currently this is only being used when the bubble is persisted to disk. */ Bubble(@NonNull final String key, @NonNull final ShortcutInfo shortcutInfo, - final int desiredHeight, final int desiredHeightResId, @Nullable final String title) { + final int desiredHeight, final int desiredHeightResId, @Nullable final String title, + Executor mainExecutor) { Objects.requireNonNull(key); Objects.requireNonNull(shortcutInfo); mMetadataShortcutId = shortcutInfo.getId(); @@ -170,20 +173,25 @@ public class Bubble implements BubbleViewProvider { mDesiredHeightResId = desiredHeightResId; mTitle = title; mShowBubbleUpdateDot = false; + mMainExecutor = mainExecutor; } @VisibleForTesting(visibility = PRIVATE) Bubble(@NonNull final BubbleEntry entry, @Nullable final Bubbles.NotificationSuppressionChangedListener listener, - final Bubbles.PendingIntentCanceledListener intentCancelListener) { + final Bubbles.PendingIntentCanceledListener intentCancelListener, + Executor mainExecutor) { mKey = entry.getKey(); mSuppressionListener = listener; mIntentCancelListener = intent -> { if (mIntent != null) { mIntent.unregisterCancelListener(mIntentCancelListener); } - intentCancelListener.onPendingIntentCanceled(this); + mainExecutor.execute(() -> { + intentCancelListener.onPendingIntentCanceled(this); + }); }; + mMainExecutor = mainExecutor; setEntry(entry); } @@ -329,7 +337,8 @@ public class Bubble implements BubbleViewProvider { stackView, iconFactory, skipInflation, - callback); + callback, + mMainExecutor); if (mInflateSynchronously) { mInflationTask.onPostExecute(mInflationTask.doInBackground()); } else { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java index 9419b9c6d344..7538c8b7ffad 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java @@ -28,6 +28,16 @@ import static com.android.wm.shell.bubbles.BubblePositioner.TASKBAR_POSITION_BOT import static com.android.wm.shell.bubbles.BubblePositioner.TASKBAR_POSITION_LEFT; import static com.android.wm.shell.bubbles.BubblePositioner.TASKBAR_POSITION_NONE; import static com.android.wm.shell.bubbles.BubblePositioner.TASKBAR_POSITION_RIGHT; +import static com.android.wm.shell.bubbles.Bubbles.DISMISS_AGED; +import static com.android.wm.shell.bubbles.Bubbles.DISMISS_BLOCKED; +import static com.android.wm.shell.bubbles.Bubbles.DISMISS_GROUP_CANCELLED; +import static com.android.wm.shell.bubbles.Bubbles.DISMISS_INVALID_INTENT; +import static com.android.wm.shell.bubbles.Bubbles.DISMISS_NOTIF_CANCEL; +import static com.android.wm.shell.bubbles.Bubbles.DISMISS_NO_BUBBLE_UP; +import static com.android.wm.shell.bubbles.Bubbles.DISMISS_NO_LONGER_BUBBLE; +import static com.android.wm.shell.bubbles.Bubbles.DISMISS_PACKAGE_REMOVED; +import static com.android.wm.shell.bubbles.Bubbles.DISMISS_SHORTCUT_REMOVED; +import static com.android.wm.shell.bubbles.Bubbles.DISMISS_USER_CHANGED; import android.annotation.NonNull; import android.annotation.UserIdInt; @@ -45,6 +55,8 @@ import android.graphics.PixelFormat; import android.graphics.PointF; import android.os.Binder; import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; import android.os.RemoteException; import android.os.ServiceManager; import android.os.UserHandle; @@ -53,6 +65,7 @@ import android.service.notification.NotificationListenerService.RankingMap; import android.util.ArraySet; import android.util.Log; import android.util.Pair; +import android.util.Slog; import android.util.SparseSetArray; import android.view.View; import android.view.ViewGroup; @@ -75,6 +88,9 @@ import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; import java.util.Objects; +import java.util.concurrent.Executor; +import java.util.function.BiConsumer; +import java.util.function.Consumer; import java.util.function.IntConsumer; /** @@ -83,7 +99,7 @@ import java.util.function.IntConsumer; * * The controller manages addition, removal, and visible state of bubbles on screen. */ -public class BubbleController implements Bubbles { +public class BubbleController { private static final String TAG = TAG_WITH_CLASS_NAME ? "BubbleController" : TAG_BUBBLES; @@ -101,7 +117,8 @@ public class BubbleController implements Bubbles { public static final String BOTTOM_POSITION = "Bottom"; private final Context mContext; - private BubbleExpandListener mExpandListener; + private final BubblesImpl mImpl = new BubblesImpl(); + private Bubbles.BubbleExpandListener mExpandListener; @Nullable private BubbleStackView.SurfaceSynchronizer mSurfaceSynchronizer; private final FloatingContentCoordinator mFloatingContentCoordinator; private final BubbleDataRepository mDataRepository; @@ -111,7 +128,7 @@ public class BubbleController implements Bubbles { @Nullable private BubbleStackView mStackView; private BubbleIconFactory mBubbleIconFactory; private BubblePositioner mBubblePositioner; - private SysuiProxy mSysuiProxy; + private Bubbles.SysuiProxy mSysuiProxy; // Tracks the id of the current (foreground) user. private int mCurrentUserId; @@ -177,7 +194,7 @@ public class BubbleController implements Bubbles { /** * Injected constructor. */ - public static BubbleController create(Context context, + public static Bubbles create(Context context, @Nullable BubbleStackView.SurfaceSynchronizer synchronizer, FloatingContentCoordinator floatingContentCoordinator, @Nullable IStatusBarService statusBarService, @@ -186,14 +203,15 @@ public class BubbleController implements Bubbles { LauncherApps launcherApps, UiEventLogger uiEventLogger, ShellTaskOrganizer organizer, - ShellExecutor mainExecutor) { + ShellExecutor mainExecutor, + Handler mainHandler) { BubbleLogger logger = new BubbleLogger(uiEventLogger); BubblePositioner positioner = new BubblePositioner(context, windowManager); - BubbleData data = new BubbleData(context, logger, positioner); + BubbleData data = new BubbleData(context, logger, positioner, mainExecutor); return new BubbleController(context, data, synchronizer, floatingContentCoordinator, - new BubbleDataRepository(context, launcherApps), + new BubbleDataRepository(context, launcherApps, mainExecutor), statusBarService, windowManager, windowManagerShellWrapper, launcherApps, - logger, organizer, positioner, mainExecutor); + logger, organizer, positioner, mainExecutor, mainHandler).mImpl; } /** @@ -212,7 +230,8 @@ public class BubbleController implements Bubbles { BubbleLogger bubbleLogger, ShellTaskOrganizer organizer, BubblePositioner positioner, - ShellExecutor mainExecutor) { + ShellExecutor mainExecutor, + Handler mainHandler) { mContext = context; mFloatingContentCoordinator = floatingContentCoordinator; mDataRepository = dataRepository; @@ -299,7 +318,12 @@ public class BubbleController implements Bubbles { mBubbleData.removeBubblesWithInvalidShortcuts( packageName, validShortcuts, DISMISS_SHORTCUT_REMOVED); } - }); + }, mainHandler); + } + + @VisibleForTesting + public Bubbles getImpl() { + return mImpl; } /** @@ -313,8 +337,7 @@ public class BubbleController implements Bubbles { } } - @Override - public void openBubbleOverflow() { + private void openBubbleOverflow() { ensureStackViewCreated(); mBubbleData.setShowingOverflow(true); mBubbleData.setSelectedBubble(mBubbleData.getOverflow()); @@ -322,8 +345,7 @@ public class BubbleController implements Bubbles { } /** Called when any taskbar state changes (e.g. visibility, position, sizes). */ - @Override - public void onTaskbarChanged(Bundle b) { + private void onTaskbarChanged(Bundle b) { if (b == null) { return; } @@ -371,8 +393,7 @@ public class BubbleController implements Bubbles { * Called when the status bar has become visible or invisible (either permanently or * temporarily). */ - @Override - public void onStatusBarVisibilityChanged(boolean visible) { + private void onStatusBarVisibilityChanged(boolean visible) { if (mStackView != null) { // Hide the stack temporarily if the status bar has been made invisible, and the stack // is collapsed. An expanded stack should remain visible until collapsed. @@ -380,15 +401,13 @@ public class BubbleController implements Bubbles { } } - @Override - public void onZenStateChanged() { + private void onZenStateChanged() { for (Bubble b : mBubbleData.getBubbles()) { b.setShowDot(b.showInShade()); } } - @Override - public void onStatusBarStateChanged(boolean isShade) { + private void onStatusBarStateChanged(boolean isShade) { mIsStatusBarShade = isShade; if (!mIsStatusBarShade) { collapseStack(); @@ -402,8 +421,7 @@ public class BubbleController implements Bubbles { updateStack(); } - @Override - public void onUserChanged(int newUserId) { + private void onUserChanged(int newUserId) { saveBubbles(mCurrentUserId); mBubbleData.dismissAll(DISMISS_USER_CHANGED); restoreBubbles(newUserId); @@ -442,7 +460,7 @@ public class BubbleController implements Bubbles { return mBubblePositioner; } - SysuiProxy getSysuiProxy() { + Bubbles.SysuiProxy getSysuiProxy() { return mSysuiProxy; } @@ -453,7 +471,8 @@ public class BubbleController implements Bubbles { private void ensureStackViewCreated() { if (mStackView == null) { mStackView = new BubbleStackView( - mContext, this, mBubbleData, mSurfaceSynchronizer, mFloatingContentCoordinator); + mContext, this, mBubbleData, mSurfaceSynchronizer, mFloatingContentCoordinator, + mMainExecutor); mStackView.onOrientationChanged(); if (mExpandListener != null) { mStackView.setExpandListener(mExpandListener); @@ -576,8 +595,7 @@ public class BubbleController implements Bubbles { mSavedBubbleKeysPerUser.remove(mCurrentUserId); } - @Override - public void updateForThemeChanges() { + private void updateForThemeChanges() { if (mStackView != null) { mStackView.onThemeChanged(); } @@ -593,8 +611,7 @@ public class BubbleController implements Bubbles { } } - @Override - public void onConfigChanged(Configuration newConfig) { + private void onConfigChanged(Configuration newConfig) { if (mBubblePositioner != null) { // This doesn't trigger any changes, always update it mBubblePositioner.update(newConfig.orientation); @@ -620,18 +637,19 @@ public class BubbleController implements Bubbles { } } - @Override - public void setBubbleScrim(View view) { + private void setBubbleScrim(View view, BiConsumer<Executor, Looper> callback) { mBubbleScrim = view; + callback.accept(mMainExecutor, mMainExecutor.executeBlockingForResult(() -> { + return Looper.myLooper(); + }, Looper.class)); } - @Override - public void setSysuiProxy(SysuiProxy proxy) { + private void setSysuiProxy(Bubbles.SysuiProxy proxy) { mSysuiProxy = proxy; } - @Override - public void setExpandListener(BubbleExpandListener listener) { + @VisibleForTesting + public void setExpandListener(Bubbles.BubbleExpandListener listener) { mExpandListener = ((isExpanding, key) -> { if (listener != null) { listener.onBubbleExpandChanged(isExpanding, key); @@ -654,17 +672,17 @@ public class BubbleController implements Bubbles { return mBubbleData.hasBubbles() || mBubbleData.isShowingOverflow(); } - @Override + @VisibleForTesting public boolean isStackExpanded() { return mBubbleData.isExpanded(); } - @Override + @VisibleForTesting public void collapseStack() { mBubbleData.setExpanded(false /* expanded */); } - @Override + @VisibleForTesting public boolean isBubbleNotificationSuppressedFromShade(String key, String groupKey) { boolean isSuppressedBubble = (mBubbleData.hasAnyBubbleWithKey(key) && !mBubbleData.getAnyBubbleWithkey(key).showInShade()); @@ -674,23 +692,19 @@ public class BubbleController implements Bubbles { return (isSummary && isSuppressedSummary) || isSuppressedBubble; } - @Override - public boolean isSummarySuppressed(String groupKey) { - return mBubbleData.isSummarySuppressed(groupKey); - } - - @Override - public void removeSuppressedSummary(String groupKey) { - mBubbleData.removeSuppressedSummary(groupKey); - } - - @Override - public String getSummaryKey(String groupKey) { - return mBubbleData.getSummaryKey(groupKey); + private void removeSuppressedSummaryIfNecessary(String groupKey, Consumer<String> callback, + Executor callbackExecutor) { + if (mBubbleData.isSummarySuppressed(groupKey)) { + mBubbleData.removeSuppressedSummary(groupKey); + if (callback != null) { + callbackExecutor.execute(() -> { + callback.accept(mBubbleData.getSummaryKey(groupKey)); + }); + } + } } - @Override - public boolean isBubbleExpanded(String key) { + private boolean isBubbleExpanded(String key) { return isStackExpanded() && mBubbleData != null && mBubbleData.getSelectedBubble() != null && mBubbleData.getSelectedBubble().getKey().equals(key); } @@ -704,7 +718,7 @@ public class BubbleController implements Bubbles { setIsBubble(bubble, true /* isBubble */); } - @Override + @VisibleForTesting public void expandStackAndSelectBubble(BubbleEntry entry) { if (mIsStatusBarShade) { mNotifEntryToExpandOnShadeUnlock = null; @@ -809,15 +823,13 @@ public class BubbleController implements Bubbles { } } - @Override - public void onEntryAdded(BubbleEntry entry) { + private void onEntryAdded(BubbleEntry entry) { if (canLaunchInActivityView(mContext, entry)) { updateBubble(entry); } } - @Override - public void onEntryUpdated(BubbleEntry entry, boolean shouldBubbleUp) { + private void onEntryUpdated(BubbleEntry entry, boolean shouldBubbleUp) { // shouldBubbleUp checks canBubble & for bubble metadata boolean shouldBubble = shouldBubbleUp && canLaunchInActivityView(mContext, entry); if (!shouldBubble && mBubbleData.hasAnyBubbleWithKey(entry.getKey())) { @@ -828,8 +840,7 @@ public class BubbleController implements Bubbles { } } - @Override - public void onEntryRemoved(BubbleEntry entry) { + private void onEntryRemoved(BubbleEntry entry) { if (isSummaryOfBubbles(entry)) { final String groupKey = entry.getStatusBarNotification().getGroupKey(); mBubbleData.removeSuppressedSummary(groupKey); @@ -844,8 +855,7 @@ public class BubbleController implements Bubbles { } } - @Override - public void onRankingUpdated(RankingMap rankingMap) { + private void onRankingUpdated(RankingMap rankingMap) { if (mTmpRanking == null) { mTmpRanking = new NotificationListenerService.Ranking(); } @@ -882,6 +892,8 @@ public class BubbleController implements Bubbles { return bubbleChildren; } for (Bubble bubble : mBubbleData.getActiveBubbles()) { + // TODO(178620678): Prevent calling into SysUI since this can be a part of a blocking + // call from SysUI to Shell final BubbleEntry entry = mSysuiProxy.getPendingOrActiveEntry(bubble.getKey()); if (entry != null && groupKey.equals(entry.getStatusBarNotification().getGroupKey())) { bubbleChildren.add(bubble); @@ -951,7 +963,7 @@ public class BubbleController implements Bubbles { ArrayList<Bubble> bubblesToBeRemovedFromRepository = new ArrayList<>(); for (Pair<Bubble, Integer> removed : removedBubbles) { final Bubble bubble = removed.first; - @DismissReason final int reason = removed.second; + @Bubbles.DismissReason final int reason = removed.second; if (mStackView != null) { mStackView.removeBubble(bubble); @@ -1029,8 +1041,7 @@ public class BubbleController implements Bubbles { } }; - @Override - public boolean handleDismissalInterception(BubbleEntry entry, + private boolean handleDismissalInterception(BubbleEntry entry, @Nullable List<BubbleEntry> children, IntConsumer removeCallback) { if (isSummaryOfBubbles(entry)) { handleSummaryDismissalInterception(entry, children, removeCallback); @@ -1137,8 +1148,7 @@ public class BubbleController implements Bubbles { /** * Description of current bubble state. */ - @Override - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + private void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println("BubbleController state:"); mBubbleData.dump(fd, pw, args); pw.println(); @@ -1216,4 +1226,175 @@ public class BubbleController implements Bubbles { } } } + + private class BubblesImpl implements Bubbles { + @Override + public boolean isBubbleNotificationSuppressedFromShade(String key, String groupKey) { + return mMainExecutor.executeBlockingForResult(() -> { + return BubbleController.this.isBubbleNotificationSuppressedFromShade(key, groupKey); + }, Boolean.class); + } + + @Override + public boolean isBubbleExpanded(String key) { + return mMainExecutor.executeBlockingForResult(() -> { + return BubbleController.this.isBubbleExpanded(key); + }, Boolean.class); + } + + @Override + public boolean isStackExpanded() { + return mMainExecutor.executeBlockingForResult(() -> { + return BubbleController.this.isStackExpanded(); + }, Boolean.class); + } + + @Override + public void removeSuppressedSummaryIfNecessary(String groupKey, Consumer<String> callback, + Executor callbackExecutor) { + mMainExecutor.execute(() -> { + BubbleController.this.removeSuppressedSummaryIfNecessary(groupKey, callback, + callbackExecutor); + }); + } + + @Override + public void collapseStack() { + mMainExecutor.execute(() -> { + BubbleController.this.collapseStack(); + }); + } + + @Override + public void updateForThemeChanges() { + mMainExecutor.execute(() -> { + BubbleController.this.updateForThemeChanges(); + }); + } + + @Override + public void expandStackAndSelectBubble(BubbleEntry entry) { + mMainExecutor.execute(() -> { + BubbleController.this.expandStackAndSelectBubble(entry); + }); + } + + @Override + public void onTaskbarChanged(Bundle b) { + mMainExecutor.execute(() -> { + BubbleController.this.onTaskbarChanged(b); + }); + } + + @Override + public void openBubbleOverflow() { + mMainExecutor.execute(() -> { + BubbleController.this.openBubbleOverflow(); + }); + } + + @Override + public boolean handleDismissalInterception(BubbleEntry entry, + @Nullable List<BubbleEntry> children, IntConsumer removeCallback) { + return mMainExecutor.executeBlockingForResult(() -> { + return BubbleController.this.handleDismissalInterception(entry, children, + removeCallback); + }, Boolean.class); + } + + @Override + public void setSysuiProxy(SysuiProxy proxy) { + mMainExecutor.execute(() -> { + BubbleController.this.setSysuiProxy(proxy); + }); + } + + @Override + public void setBubbleScrim(View view, BiConsumer<Executor, Looper> callback) { + mMainExecutor.execute(() -> { + BubbleController.this.setBubbleScrim(view, callback); + }); + } + + @Override + public void setExpandListener(BubbleExpandListener listener) { + mMainExecutor.execute(() -> { + BubbleController.this.setExpandListener(listener); + }); + } + + @Override + public void onEntryAdded(BubbleEntry entry) { + mMainExecutor.execute(() -> { + BubbleController.this.onEntryAdded(entry); + }); + } + + @Override + public void onEntryUpdated(BubbleEntry entry, boolean shouldBubbleUp) { + mMainExecutor.execute(() -> { + BubbleController.this.onEntryUpdated(entry, shouldBubbleUp); + }); + } + + @Override + public void onEntryRemoved(BubbleEntry entry) { + mMainExecutor.execute(() -> { + BubbleController.this.onEntryRemoved(entry); + }); + } + + @Override + public void onRankingUpdated(RankingMap rankingMap) { + mMainExecutor.execute(() -> { + BubbleController.this.onRankingUpdated(rankingMap); + }); + } + + @Override + public void onStatusBarVisibilityChanged(boolean visible) { + mMainExecutor.execute(() -> { + BubbleController.this.onStatusBarVisibilityChanged(visible); + }); + } + + @Override + public void onZenStateChanged() { + mMainExecutor.execute(() -> { + BubbleController.this.onZenStateChanged(); + }); + } + + @Override + public void onStatusBarStateChanged(boolean isShade) { + mMainExecutor.execute(() -> { + BubbleController.this.onStatusBarStateChanged(isShade); + }); + } + + @Override + public void onUserChanged(int newUserId) { + mMainExecutor.execute(() -> { + BubbleController.this.onUserChanged(newUserId); + }); + } + + @Override + public void onConfigChanged(Configuration newConfig) { + mMainExecutor.execute(() -> { + BubbleController.this.onConfigChanged(newConfig); + }); + } + + @Override + public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + try { + mMainExecutor.executeBlocking(() -> { + BubbleController.this.dump(fd, pw, args); + }); + } catch (InterruptedException e) { + Slog.e(TAG, "Failed to dump BubbleController in 2s"); + } + } + } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java index e24ff063b661..9d196ba32f8a 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java @@ -46,6 +46,7 @@ import java.util.HashSet; import java.util.List; import java.util.Objects; import java.util.Set; +import java.util.concurrent.Executor; import java.util.function.Consumer; import java.util.function.Predicate; @@ -117,6 +118,7 @@ public class BubbleData { private final Context mContext; private final BubblePositioner mPositioner; + private final Executor mMainExecutor; /** Bubbles that are actively in the stack. */ private final List<Bubble> mBubbles; /** Bubbles that aged out to overflow. */ @@ -155,10 +157,12 @@ public class BubbleData { */ private HashMap<String, String> mSuppressedGroupKeys = new HashMap<>(); - public BubbleData(Context context, BubbleLogger bubbleLogger, BubblePositioner positioner) { + public BubbleData(Context context, BubbleLogger bubbleLogger, BubblePositioner positioner, + Executor mainExecutor) { mContext = context; mLogger = bubbleLogger; mPositioner = positioner; + mMainExecutor = mainExecutor; mOverflow = new BubbleOverflow(context, positioner); mBubbles = new ArrayList<>(); mOverflowBubbles = new ArrayList<>(); @@ -264,7 +268,8 @@ public class BubbleData { bubbleToReturn = mPendingBubbles.get(key); } else if (entry != null) { // New bubble - bubbleToReturn = new Bubble(entry, mSuppressionListener, mCancelledListener); + bubbleToReturn = new Bubble(entry, mSuppressionListener, mCancelledListener, + mMainExecutor); } else { // Persisted bubble being promoted bubbleToReturn = persistedBubble; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleDataRepository.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleDataRepository.kt index fc565f17546d..3108b02cc010 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleDataRepository.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleDataRepository.kt @@ -27,6 +27,8 @@ import android.util.Log import com.android.wm.shell.bubbles.storage.BubbleEntity import com.android.wm.shell.bubbles.storage.BubblePersistentRepository import com.android.wm.shell.bubbles.storage.BubbleVolatileRepository +import com.android.wm.shell.common.ShellExecutor +import com.android.wm.shell.common.annotations.ExternalThread import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job @@ -34,12 +36,12 @@ import kotlinx.coroutines.cancelAndJoin import kotlinx.coroutines.launch import kotlinx.coroutines.yield -internal class BubbleDataRepository(context: Context, private val launcherApps: LauncherApps) { +internal class BubbleDataRepository(context: Context, private val launcherApps: LauncherApps, + private val mainExecutor : ShellExecutor) { private val volatileRepository = BubbleVolatileRepository(launcherApps) private val persistentRepository = BubblePersistentRepository(context) private val ioScope = CoroutineScope(Dispatchers.IO) - private val uiScope = CoroutineScope(Dispatchers.Main) private var job: Job? = null /** @@ -109,6 +111,8 @@ internal class BubbleDataRepository(context: Context, private val launcherApps: /** * Load bubbles from disk. + * @param cb The callback to be run after the bubbles are loaded. This callback is always made + * on the main thread of the hosting process. */ @SuppressLint("WrongConstant") fun loadBubbles(cb: (List<Bubble>) -> Unit) = ioScope.launch { @@ -163,10 +167,11 @@ internal class BubbleDataRepository(context: Context, private val launcherApps: shortcutInfo, entity.desiredHeight, entity.desiredHeightResId, - entity.title + entity.title, + mainExecutor ) } } - uiScope.launch { cb(bubbles) } + mainExecutor.execute { cb(bubbles) } } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java index fac368677d12..af421facd72a 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java @@ -79,6 +79,7 @@ import com.android.wm.shell.bubbles.animation.ExpandedAnimationController; import com.android.wm.shell.bubbles.animation.PhysicsAnimationLayout; import com.android.wm.shell.bubbles.animation.StackAnimationController; import com.android.wm.shell.common.FloatingContentCoordinator; +import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.magnetictarget.MagnetizedObject; import java.io.FileDescriptor; @@ -147,7 +148,7 @@ public class BubbleStackView extends FrameLayout * Handler to use for all delayed animations - this way, we can easily cancel them before * starting a new animation. */ - private final Handler mDelayedAnimationHandler = new Handler(); + private final ShellExecutor mDelayedAnimationExecutor; /** * Interface to synchronize {@link View} state and the screen. @@ -311,7 +312,7 @@ public class BubbleStackView extends FrameLayout } } - private BubbleController.BubbleExpandListener mExpandListener; + private Bubbles.BubbleExpandListener mExpandListener; /** Callback to run when we want to unbubble the given notification's conversation. */ private Consumer<String> mUnbubbleConversationCallback; @@ -734,9 +735,11 @@ public class BubbleStackView extends FrameLayout @SuppressLint("ClickableViewAccessibility") public BubbleStackView(Context context, BubbleController bubbleController, BubbleData data, @Nullable SurfaceSynchronizer synchronizer, - FloatingContentCoordinator floatingContentCoordinator) { + FloatingContentCoordinator floatingContentCoordinator, + ShellExecutor mainExecutor) { super(context); + mDelayedAnimationExecutor = mainExecutor; mBubbleController = bubbleController; mBubbleData = data; @@ -1366,7 +1369,7 @@ public class BubbleStackView extends FrameLayout /** * Sets the listener to notify when the bubble stack is expanded. */ - public void setExpandListener(BubbleController.BubbleExpandListener listener) { + public void setExpandListener(Bubbles.BubbleExpandListener listener) { mExpandListener = listener; } @@ -1734,7 +1737,7 @@ public class BubbleStackView extends FrameLayout mExpandedBubble.getExpandedView().setSurfaceZOrderedOnTop(false); } - mDelayedAnimationHandler.postDelayed(() -> { + mDelayedAnimationExecutor.executeDelayed(() -> { PhysicsAnimator.getInstance(mExpandedViewContainerMatrix).cancel(); PhysicsAnimator.getInstance(mExpandedViewContainerMatrix) .spring(AnimatableScaleMatrix.SCALE_X, @@ -1791,10 +1794,12 @@ public class BubbleStackView extends FrameLayout final long startDelay = (long) (ExpandedAnimationController.EXPAND_COLLAPSE_TARGET_ANIM_DURATION * 0.6f); - mDelayedAnimationHandler.postDelayed(() -> mExpandedAnimationController.collapseBackToStack( - mStackAnimationController.getStackPositionAlongNearestHorizontalEdge() - /* collapseTo */, - () -> mBubbleContainer.setActiveController(mStackAnimationController)), startDelay); + mDelayedAnimationExecutor.executeDelayed(() -> { + mExpandedAnimationController.collapseBackToStack( + mStackAnimationController.getStackPositionAlongNearestHorizontalEdge() + /* collapseTo */, + () -> mBubbleContainer.setActiveController(mStackAnimationController)); + }, startDelay); if (mTaskbarScrim.getVisibility() == VISIBLE) { mTaskbarScrim.animate().alpha(0f).start(); @@ -1945,7 +1950,7 @@ public class BubbleStackView extends FrameLayout mExpandedViewContainer.setAnimationMatrix(mExpandedViewContainerMatrix); - mDelayedAnimationHandler.postDelayed(() -> { + mDelayedAnimationExecutor.executeDelayed(() -> { if (!mIsExpanded) { mIsBubbleSwitchAnimating = false; return; @@ -1978,7 +1983,7 @@ public class BubbleStackView extends FrameLayout * animating flags for those animations. */ private void cancelDelayedExpandCollapseSwitchAnimations() { - mDelayedAnimationHandler.removeCallbacksAndMessages(null); + mDelayedAnimationExecutor.removeAllCallbacks(); mIsExpansionAnimating = false; mIsBubbleSwitchAnimating = false; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java index 0e7e92d9554a..c5a712e271e4 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java @@ -46,6 +46,7 @@ import com.android.wm.shell.R; import java.lang.ref.WeakReference; import java.util.Objects; +import java.util.concurrent.Executor; /** * Simple task to inflate views & load necessary info to display a bubble. @@ -71,6 +72,7 @@ public class BubbleViewInfoTask extends AsyncTask<Void, Void, BubbleViewInfoTask private BubbleIconFactory mIconFactory; private boolean mSkipInflation; private Callback mCallback; + private Executor mMainExecutor; /** * Creates a task to load information for the provided {@link Bubble}. Once all info @@ -82,7 +84,8 @@ public class BubbleViewInfoTask extends AsyncTask<Void, Void, BubbleViewInfoTask BubbleStackView stackView, BubbleIconFactory factory, boolean skipInflation, - Callback c) { + Callback c, + Executor mainExecutor) { mBubble = b; mContext = new WeakReference<>(context); mController = new WeakReference<>(controller); @@ -90,6 +93,7 @@ public class BubbleViewInfoTask extends AsyncTask<Void, Void, BubbleViewInfoTask mIconFactory = factory; mSkipInflation = skipInflation; mCallback = c; + mMainExecutor = mainExecutor; } @Override @@ -103,10 +107,12 @@ public class BubbleViewInfoTask extends AsyncTask<Void, Void, BubbleViewInfoTask if (isCancelled() || viewInfo == null) { return; } - mBubble.setViewInfo(viewInfo); - if (mCallback != null) { - mCallback.onBubbleViewsReady(mBubble); - } + mMainExecutor.execute(() -> { + mBubble.setViewInfo(viewInfo); + if (mCallback != null) { + mCallback.onBubbleViewsReady(mBubble); + } + }); } /** diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java index fa5ac449cd54..6102147e4b53 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java @@ -23,6 +23,7 @@ import static java.lang.annotation.RetentionPolicy.SOURCE; import android.content.res.Configuration; import android.os.Bundle; +import android.os.Looper; import android.service.notification.NotificationListenerService.RankingMap; import android.util.ArraySet; import android.view.View; @@ -37,6 +38,9 @@ import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.Target; import java.util.List; +import java.util.concurrent.Executor; +import java.util.function.BiConsumer; +import java.util.function.Consumer; import java.util.function.IntConsumer; /** @@ -86,13 +90,14 @@ public interface Bubbles { /** @return {@code true} if stack of bubbles is expanded or not. */ boolean isStackExpanded(); - /** @return {@code true} if the summary for the provided group key is suppressed. */ - boolean isSummarySuppressed(String groupKey); - /** - * Removes a group key indicating that summary for this group should no longer be suppressed. + * Removes a group key indicating that the summary for this group should no longer be + * suppressed. + * + * @param callback If removed, this callback will be called with the summary key of the group */ - void removeSuppressedSummary(String groupKey); + void removeSuppressedSummaryIfNecessary(String groupKey, Consumer<String> callback, + Executor callbackExecutor); /** Tell the stack of bubbles to collapse. */ void collapseStack(); @@ -134,19 +139,16 @@ public interface Bubbles { boolean handleDismissalInterception(BubbleEntry entry, @Nullable List<BubbleEntry> children, IntConsumer removeCallback); - /** - * Retrieves the notif entry key of the summary associated with the provided group key. - * - * @param groupKey the group to look up - * @return the key for the notification that is the summary of this group. - */ - String getSummaryKey(String groupKey); - /** Set the proxy to commnuicate with SysUi side components. */ void setSysuiProxy(SysuiProxy proxy); - /** Set the scrim view for bubbles. */ - void setBubbleScrim(View view); + /** + * Set the scrim view for bubbles. + * + * @param callback The callback made with the executor and the executor's looper that the view + * will be running on. + **/ + void setBubbleScrim(View view, BiConsumer<Executor, Looper> callback); /** Set a listener to be notified of bubble expand events. */ void setExpandListener(BubbleExpandListener listener); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/RelativeTouchListener.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/RelativeTouchListener.kt index a1b0dbe0a6dd..cf0cefec401a 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/RelativeTouchListener.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/RelativeTouchListener.kt @@ -91,7 +91,6 @@ abstract class RelativeTouchListener : View.OnTouchListener { private var touchSlop: Int = -1 private var movedEnough = false - private val handler = Handler(Looper.myLooper()!!) private var performedLongClick = false @Suppress("UNCHECKED_CAST") @@ -115,7 +114,7 @@ abstract class RelativeTouchListener : View.OnTouchListener { viewPositionOnTouchDown.set(v.translationX, v.translationY) performedLongClick = false - handler.postDelayed({ + v.handler.postDelayed({ if (v.isLongClickable) { performedLongClick = v.performLongClick() } @@ -125,7 +124,7 @@ abstract class RelativeTouchListener : View.OnTouchListener { MotionEvent.ACTION_MOVE -> { if (!movedEnough && hypot(dx, dy) > touchSlop && !performedLongClick) { movedEnough = true - handler.removeCallbacksAndMessages(null) + v.handler.removeCallbacksAndMessages(null) } if (movedEnough) { @@ -141,7 +140,7 @@ abstract class RelativeTouchListener : View.OnTouchListener { } else if (!performedLongClick) { v.performClick() } else { - handler.removeCallbacksAndMessages(null) + v.handler.removeCallbacksAndMessages(null) } velocityTracker.clear() diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/ShellExecutor.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/ShellExecutor.java index b736fb0b9895..6abc8f6dda89 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/ShellExecutor.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/ShellExecutor.java @@ -20,6 +20,7 @@ import android.os.Looper; import android.os.SystemClock; import android.os.Trace; +import java.lang.reflect.Array; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; @@ -68,6 +69,26 @@ public interface ShellExecutor extends Executor { } /** + * Convenience method to execute the blocking call with a default timeout and returns a value. + * Waits indefinitely for a typed result from a call. + */ + default <T> T executeBlockingForResult(Supplier<T> runnable, Class clazz) { + final T[] result = (T[]) Array.newInstance(clazz, 1); + final CountDownLatch latch = new CountDownLatch(1); + execute(() -> { + result[0] = runnable.get(); + latch.countDown(); + }); + try { + latch.await(); + return result[0]; + } catch (InterruptedException e) { + return null; + } + } + + + /** * See {@link android.os.Handler#postDelayed(Runnable, long)}. */ void executeDelayed(Runnable runnable, long delayMillis); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java index 128d13c2ce2e..bb6704333050 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java @@ -30,7 +30,6 @@ import android.content.res.Resources; import android.graphics.Point; import android.graphics.PointF; import android.graphics.Rect; -import android.os.Handler; import android.provider.DeviceConfig; import android.util.Log; import android.util.Size; @@ -847,11 +846,11 @@ public class PipTouchHandler { && mPipBoundsState.getBounds().height() < mPipBoundsState.getMaxSize().y; if (toExpand) { + mPipResizeGestureHandler.setUserResizeBounds(mPipBoundsState.getBounds()); animateToMaximizedState(null); } else { - animateToMinimizedState(); + animateToUnexpandedState(getUserResizeBounds()); } - mPipResizeGestureHandler.setUserResizeBounds(mPipBoundsState.getBounds()); } else { // Expand to fullscreen if this is a double tap // the PiP should be frozen until the transition ends diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestCannotPairNonResizeableApps.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestCannotPairNonResizeableApps.kt index 564a418a1082..d25774935e86 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestCannotPairNonResizeableApps.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestCannotPairNonResizeableApps.kt @@ -21,7 +21,6 @@ import android.platform.test.annotations.Presubmit import android.os.SystemClock import androidx.test.filters.RequiresDevice import androidx.test.platform.app.InstrumentationRegistry -import com.android.server.wm.flicker.Flicker import com.android.server.wm.flicker.FlickerTestRunner import com.android.server.wm.flicker.FlickerTestRunnerFactory import com.android.server.wm.flicker.dsl.FlickerBuilder @@ -46,10 +45,8 @@ import org.junit.runners.Parameterized @RunWith(Parameterized::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) class AppPairsTestCannotPairNonResizeableApps( - testName: String, - flickerProvider: () -> Flicker, - cleanUp: Boolean -) : FlickerTestRunner(testName, flickerProvider, cleanUp) { + testSpec: FlickerTestRunnerFactory.TestSpec +) : FlickerTestRunner(testSpec) { companion object : AppPairsTransition(InstrumentationRegistry.getInstrumentation()) { @Parameterized.Parameters(name = "{0}") @JvmStatic @@ -83,9 +80,8 @@ class AppPairsTestCannotPairNonResizeableApps( } } - return FlickerTestRunnerFactory(instrumentation, - repetitions = AppPairsHelper.TEST_REPETITIONS) - .buildTest(transition, testSpec) + return FlickerTestRunnerFactory.getInstance().buildTest(instrumentation, + transition, testSpec, repetitions = AppPairsHelper.TEST_REPETITIONS) } } }
\ No newline at end of file diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestPairPrimaryAndSecondaryApps.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestPairPrimaryAndSecondaryApps.kt index f63eb1db4d5c..5cbfec638da5 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestPairPrimaryAndSecondaryApps.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestPairPrimaryAndSecondaryApps.kt @@ -21,13 +21,12 @@ import android.os.SystemClock import android.platform.test.annotations.Presubmit import androidx.test.filters.RequiresDevice import androidx.test.platform.app.InstrumentationRegistry -import com.android.server.wm.flicker.Flicker import com.android.server.wm.flicker.FlickerTestRunner import com.android.server.wm.flicker.FlickerTestRunnerFactory import com.android.server.wm.flicker.dsl.FlickerBuilder import com.android.server.wm.flicker.helpers.buildTestTag import com.android.server.wm.flicker.traces.layers.getVisibleBounds -import com.android.wm.shell.flicker.FlickerTestBase +import com.android.wm.shell.flicker.FlickerTestBase.Companion.APP_PAIR_SPLIT_DIVIDER import com.android.wm.shell.flicker.appPairsDividerIsVisible import com.android.wm.shell.flicker.helpers.AppPairsHelper import org.junit.FixMethodOrder @@ -44,10 +43,8 @@ import org.junit.runners.Parameterized @RunWith(Parameterized::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) class AppPairsTestPairPrimaryAndSecondaryApps( - testName: String, - flickerProvider: () -> Flicker, - cleanUp: Boolean -) : FlickerTestRunner(testName, flickerProvider, cleanUp) { + testSpec: FlickerTestRunnerFactory.TestSpec +) : FlickerTestRunner(testSpec) { companion object : AppPairsTransition(InstrumentationRegistry.getInstrumentation()) { @Parameterized.Parameters(name = "{0}") @JvmStatic @@ -67,8 +64,7 @@ class AppPairsTestPairPrimaryAndSecondaryApps( layersTrace { appPairsDividerIsVisible() end("appsEndingBounds", enabled = false) { - val dividerRegion = entry.getVisibleBounds( - FlickerTestBase.APP_PAIR_SPLIT_DIVIDER) + val dividerRegion = entry.getVisibleBounds(APP_PAIR_SPLIT_DIVIDER) this.hasVisibleRegion(primaryApp.defaultWindowName, appPairsHelper.getPrimaryBounds(dividerRegion)) .hasVisibleRegion(secondaryApp.defaultWindowName, @@ -83,8 +79,8 @@ class AppPairsTestPairPrimaryAndSecondaryApps( } } } - return FlickerTestRunnerFactory(instrumentation, - repetitions = AppPairsHelper.TEST_REPETITIONS).buildTest(transition, testSpec) + return FlickerTestRunnerFactory.getInstance().buildTest(instrumentation, transition, + testSpec, repetitions = AppPairsHelper.TEST_REPETITIONS) } } } diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestUnpairPrimaryAndSecondaryApps.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestUnpairPrimaryAndSecondaryApps.kt index 731d99829b1d..f57a000a0ccb 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestUnpairPrimaryAndSecondaryApps.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestUnpairPrimaryAndSecondaryApps.kt @@ -21,13 +21,12 @@ import android.os.SystemClock import android.platform.test.annotations.Presubmit import androidx.test.filters.RequiresDevice import androidx.test.platform.app.InstrumentationRegistry -import com.android.server.wm.flicker.Flicker import com.android.server.wm.flicker.FlickerTestRunner import com.android.server.wm.flicker.FlickerTestRunnerFactory import com.android.server.wm.flicker.dsl.FlickerBuilder import com.android.server.wm.flicker.helpers.buildTestTag import com.android.server.wm.flicker.traces.layers.getVisibleBounds -import com.android.wm.shell.flicker.FlickerTestBase +import com.android.wm.shell.flicker.FlickerTestBase.Companion.APP_PAIR_SPLIT_DIVIDER import com.android.wm.shell.flicker.appPairsDividerIsInvisible import com.android.wm.shell.flicker.helpers.AppPairsHelper import org.junit.FixMethodOrder @@ -44,10 +43,8 @@ import org.junit.runners.Parameterized @RunWith(Parameterized::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) class AppPairsTestUnpairPrimaryAndSecondaryApps( - testName: String, - flickerProvider: () -> Flicker, - cleanUp: Boolean -) : FlickerTestRunner(testName, flickerProvider, cleanUp) { + testSpec: FlickerTestRunnerFactory.TestSpec +) : FlickerTestRunner(testSpec) { companion object : AppPairsTransition(InstrumentationRegistry.getInstrumentation()) { @Parameterized.Parameters(name = "{0}") @JvmStatic @@ -72,8 +69,7 @@ class AppPairsTestUnpairPrimaryAndSecondaryApps( layersTrace { appPairsDividerIsInvisible() start("appsStartingBounds", enabled = false) { - val dividerRegion = entry.getVisibleBounds( - FlickerTestBase.APP_PAIR_SPLIT_DIVIDER) + val dividerRegion = entry.getVisibleBounds(APP_PAIR_SPLIT_DIVIDER) this.hasVisibleRegion(primaryApp.defaultWindowName, appPairsHelper.getPrimaryBounds(dividerRegion)) .hasVisibleRegion(secondaryApp.defaultWindowName, @@ -92,8 +88,8 @@ class AppPairsTestUnpairPrimaryAndSecondaryApps( } } } - return FlickerTestRunnerFactory(instrumentation, - repetitions = AppPairsHelper.TEST_REPETITIONS).buildTest(transition, testSpec) + return FlickerTestRunnerFactory.getInstance().buildTest(instrumentation, transition, + testSpec, repetitions = AppPairsHelper.TEST_REPETITIONS) } } } diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/RotateTwoLaunchedAppsInAppPairsMode.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/RotateTwoLaunchedAppsInAppPairsMode.kt index da3450bf9ff6..7191e8e95590 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/RotateTwoLaunchedAppsInAppPairsMode.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/RotateTwoLaunchedAppsInAppPairsMode.kt @@ -22,7 +22,6 @@ import android.platform.test.annotations.Presubmit import android.view.Surface import androidx.test.filters.RequiresDevice import androidx.test.platform.app.InstrumentationRegistry -import com.android.server.wm.flicker.Flicker import com.android.server.wm.flicker.FlickerTestRunner import com.android.server.wm.flicker.FlickerTestRunnerFactory import com.android.server.wm.flicker.dsl.FlickerBuilder @@ -54,16 +53,13 @@ import org.junit.runners.Parameterized @RunWith(Parameterized::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) class RotateTwoLaunchedAppsInAppPairsMode( - testName: String, - flickerProvider: () -> Flicker, - cleanUp: Boolean -) : FlickerTestRunner(testName, flickerProvider, cleanUp) { + testSpec: FlickerTestRunnerFactory.TestSpec +) : FlickerTestRunner(testSpec) { companion object : RotateTwoLaunchedAppsTransition( InstrumentationRegistry.getInstrumentation()) { @Parameterized.Parameters(name = "{0}") @JvmStatic fun getParams(): Collection<Array<Any>> { - val instrumentation = InstrumentationRegistry.getInstrumentation() val testSpec: FlickerBuilder.(Bundle) -> Unit = { configuration -> withTestName { buildTestTag("testRotateTwoLaunchedAppsInAppPairsMode", configuration) @@ -96,10 +92,10 @@ class RotateTwoLaunchedAppsInAppPairsMode( } } - return FlickerTestRunnerFactory(instrumentation, + return FlickerTestRunnerFactory.getInstance().buildTest(instrumentation, + transition, testSpec, repetitions = SplitScreenHelper.TEST_REPETITIONS, - supportedRotations = listOf(Surface.ROTATION_90, Surface.ROTATION_270) - ).buildTest(transition, testSpec) + supportedRotations = listOf(Surface.ROTATION_90, Surface.ROTATION_270)) } } }
\ No newline at end of file diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/RotateTwoLaunchedAppsRotateAndEnterAppPairsMode.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/RotateTwoLaunchedAppsRotateAndEnterAppPairsMode.kt index 05543fdb3445..19ca31fbee4a 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/RotateTwoLaunchedAppsRotateAndEnterAppPairsMode.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/RotateTwoLaunchedAppsRotateAndEnterAppPairsMode.kt @@ -22,7 +22,6 @@ import android.platform.test.annotations.Presubmit import android.view.Surface import androidx.test.filters.RequiresDevice import androidx.test.platform.app.InstrumentationRegistry -import com.android.server.wm.flicker.Flicker import com.android.server.wm.flicker.FlickerTestRunner import com.android.server.wm.flicker.FlickerTestRunnerFactory import com.android.server.wm.flicker.dsl.FlickerBuilder @@ -54,16 +53,13 @@ import org.junit.runners.Parameterized @RunWith(Parameterized::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) class RotateTwoLaunchedAppsRotateAndEnterAppPairsMode( - testName: String, - flickerProvider: () -> Flicker, - cleanUp: Boolean -) : FlickerTestRunner(testName, flickerProvider, cleanUp) { + testSpec: FlickerTestRunnerFactory.TestSpec +) : FlickerTestRunner(testSpec) { companion object : RotateTwoLaunchedAppsTransition( InstrumentationRegistry.getInstrumentation()) { @Parameterized.Parameters(name = "{0}") @JvmStatic fun getParams(): Collection<Array<Any>> { - val instrumentation = InstrumentationRegistry.getInstrumentation() val testSpec: FlickerBuilder.(Bundle) -> Unit = { configuration -> withTestName { buildTestTag("testRotateAndEnterAppPairsMode", configuration) @@ -96,10 +92,11 @@ class RotateTwoLaunchedAppsRotateAndEnterAppPairsMode( } } - return FlickerTestRunnerFactory(instrumentation, + return FlickerTestRunnerFactory.getInstance().buildTest(instrumentation, + transition, testSpec, repetitions = SplitScreenHelper.TEST_REPETITIONS, supportedRotations = listOf(Surface.ROTATION_90, Surface.ROTATION_270) - ).buildTest(transition, testSpec) + ) } } }
\ No newline at end of file diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitLegacySplitScreenFromBottomTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitLegacySplitScreenFromBottomTest.kt index 4ddfb3ecdebc..a3b8673d93ed 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitLegacySplitScreenFromBottomTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitLegacySplitScreenFromBottomTest.kt @@ -20,7 +20,6 @@ import android.platform.test.annotations.Presubmit import android.view.Surface import androidx.test.filters.RequiresDevice import androidx.test.platform.app.InstrumentationRegistry -import com.android.server.wm.flicker.Flicker import com.android.server.wm.flicker.FlickerTestRunner import com.android.server.wm.flicker.FlickerTestRunnerFactory import com.android.server.wm.flicker.endRotation @@ -48,10 +47,8 @@ import org.junit.runners.Parameterized @RunWith(Parameterized::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) class ExitLegacySplitScreenFromBottomTest( - testName: String, - flickerProvider: () -> Flicker, - cleanUp: Boolean -) : FlickerTestRunner(testName, flickerProvider, cleanUp) { + testSpec: FlickerTestRunnerFactory.TestSpec +) : FlickerTestRunner(testSpec) { companion object { @Parameterized.Parameters(name = "{0}") @JvmStatic @@ -59,9 +56,9 @@ class ExitLegacySplitScreenFromBottomTest( val instrumentation = InstrumentationRegistry.getInstrumentation() val splitScreenApp = SplitScreenHelper.getPrimary(instrumentation) // TODO(b/162923992) Use of multiple segments of flicker spec for testing - return FlickerTestRunnerFactory(instrumentation, - listOf(Surface.ROTATION_0, Surface.ROTATION_90)) - .buildTest { configuration -> + return FlickerTestRunnerFactory.getInstance().buildTest(instrumentation, + supportedRotations = listOf(Surface.ROTATION_0, Surface.ROTATION_90)) { + configuration -> withTestName { buildTestTag("exitSplitScreenFromBottom", configuration) } @@ -87,6 +84,11 @@ class ExitLegacySplitScreenFromBottomTest( transitions { device.exitSplitScreenFromBottom() } + assertions { + windowManagerTrace { + all("isNotEmpty") { isNotEmpty() } + } + } } } } diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenToLauncherTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenToLauncherTest.kt index 43a756585e3c..4dcbdfff8cd5 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenToLauncherTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenToLauncherTest.kt @@ -21,7 +21,6 @@ import android.support.test.launcherhelper.LauncherStrategyFactory import android.view.Surface import androidx.test.filters.RequiresDevice import androidx.test.platform.app.InstrumentationRegistry -import com.android.server.wm.flicker.Flicker import com.android.server.wm.flicker.FlickerTestRunner import com.android.server.wm.flicker.FlickerTestRunnerFactory import com.android.server.wm.flicker.endRotation @@ -60,10 +59,8 @@ import org.junit.runners.Parameterized @RunWith(Parameterized::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) class LegacySplitScreenToLauncherTest( - testName: String, - flickerProvider: () -> Flicker, - cleanUp: Boolean -) : FlickerTestRunner(testName, flickerProvider, cleanUp) { + testSpec: FlickerTestRunnerFactory.TestSpec +) : FlickerTestRunner(testSpec) { companion object { @Parameterized.Parameters(name = "{0}") @JvmStatic @@ -74,8 +71,8 @@ class LegacySplitScreenToLauncherTest( val testApp = SimpleAppHelper(instrumentation) // b/161435597 causes the test not to work on 90 degrees - return FlickerTestRunnerFactory(instrumentation, listOf(Surface.ROTATION_0)) - .buildTest { configuration -> + return FlickerTestRunnerFactory.getInstance().buildTest(instrumentation, + supportedRotations = listOf(Surface.ROTATION_0)) { configuration -> withTestName { buildTestTag("splitScreenToLauncher", configuration) } diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ResizeLegacySplitScreenTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ResizeLegacySplitScreenTest.kt index f6b07729c196..95c1c16385c4 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ResizeLegacySplitScreenTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ResizeLegacySplitScreenTest.kt @@ -25,7 +25,6 @@ import androidx.test.filters.RequiresDevice import androidx.test.platform.app.InstrumentationRegistry import androidx.test.uiautomator.By import com.android.server.wm.flicker.DOCKED_STACK_DIVIDER -import com.android.server.wm.flicker.Flicker import com.android.server.wm.flicker.FlickerTestRunner import com.android.server.wm.flicker.FlickerTestRunnerFactory import com.android.server.wm.flicker.endRotation @@ -69,10 +68,8 @@ import org.junit.runners.Parameterized @FixMethodOrder(MethodSorters.NAME_ASCENDING) @FlakyTest(bugId = 159096424) class ResizeLegacySplitScreenTest( - testName: String, - flickerProvider: () -> Flicker, - cleanUp: Boolean -) : FlickerTestRunner(testName, flickerProvider, cleanUp) { + testSpec: FlickerTestRunnerFactory.TestSpec +) : FlickerTestRunner(testSpec) { companion object { private const val sSimpleActivity = "SimpleActivity" private const val sImeActivity = "ImeActivity" @@ -86,9 +83,8 @@ class ResizeLegacySplitScreenTest( val testAppTop = SimpleAppHelper(instrumentation) val testAppBottom = ImeAppHelper(instrumentation) - return FlickerTestRunnerFactory(instrumentation, - supportedRotations = listOf(Surface.ROTATION_0)) - .buildTest { configuration -> + return FlickerTestRunnerFactory.getInstance().buildTest(instrumentation, + supportedRotations = listOf(Surface.ROTATION_0)) { configuration -> withTestName { val description = (startRatio.toString().replace("/", "-") + "_to_" + stopRatio.toString().replace("/", "-")) diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt index 2ffc338f4f75..af62eb9ae40d 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt @@ -20,7 +20,6 @@ import android.view.Surface import androidx.test.filters.FlakyTest import androidx.test.filters.RequiresDevice import androidx.test.platform.app.InstrumentationRegistry -import com.android.server.wm.flicker.Flicker import com.android.server.wm.flicker.FlickerTestRunner import com.android.server.wm.flicker.FlickerTestRunnerFactory import com.android.server.wm.flicker.helpers.buildTestTag @@ -53,19 +52,16 @@ import org.junit.runners.Parameterized @FixMethodOrder(MethodSorters.NAME_ASCENDING) @FlakyTest(bugId = 152738416) class EnterPipTest( - testName: String, - flickerProvider: () -> Flicker, - cleanUp: Boolean -) : FlickerTestRunner(testName, flickerProvider, cleanUp) { + testSpec: FlickerTestRunnerFactory.TestSpec +) : FlickerTestRunner(testSpec) { companion object { @Parameterized.Parameters(name = "{0}") @JvmStatic fun getParams(): List<Array<Any>> { val instrumentation = InstrumentationRegistry.getInstrumentation() val testApp = PipAppHelper(instrumentation) - return FlickerTestRunnerFactory(instrumentation, - supportedRotations = listOf(Surface.ROTATION_0)) - .buildTest { configuration -> + return FlickerTestRunnerFactory.getInstance().buildTest(instrumentation, + supportedRotations = listOf(Surface.ROTATION_0)) { configuration -> withTestName { buildTestTag("enterPip", testApp, configuration) } repeat { configuration.repetitions } setup { diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt index 4a6a5b504e2c..a00c5f463a50 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt @@ -20,7 +20,6 @@ import android.platform.test.annotations.Presubmit import android.view.Surface import androidx.test.filters.RequiresDevice import androidx.test.platform.app.InstrumentationRegistry -import com.android.server.wm.flicker.Flicker import com.android.server.wm.flicker.FlickerTestRunner import com.android.server.wm.flicker.FlickerTestRunnerFactory import com.android.server.wm.flicker.endRotation @@ -54,10 +53,8 @@ import org.junit.runners.Parameterized @RunWith(Parameterized::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) class PipRotationTest( - testName: String, - flickerProvider: () -> Flicker, - cleanUp: Boolean -) : FlickerTestRunner(testName, flickerProvider, cleanUp) { + testSpec: FlickerTestRunnerFactory.TestSpec +) : FlickerTestRunner(testSpec) { companion object { @Parameterized.Parameters(name = "{0}") @JvmStatic @@ -65,9 +62,9 @@ class PipRotationTest( val instrumentation = InstrumentationRegistry.getInstrumentation() val testApp = FixedAppHelper(instrumentation) val pipApp = PipAppHelper(instrumentation) - return FlickerTestRunnerFactory(instrumentation, - listOf(Surface.ROTATION_0, Surface.ROTATION_90)) - .buildRotationTest { configuration -> + return FlickerTestRunnerFactory.getInstance().buildRotationTest(instrumentation, + supportedRotations = listOf(Surface.ROTATION_0, Surface.ROTATION_90)) { + configuration -> withTestName { buildTestTag("PipRotationTest", testApp, configuration) } repeat { configuration.repetitions } setup { diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipToAppTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipToAppTest.kt index 1502bcdf3a11..3e7eb134e627 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipToAppTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipToAppTest.kt @@ -20,7 +20,6 @@ import android.view.Surface import androidx.test.filters.FlakyTest import androidx.test.filters.RequiresDevice import androidx.test.platform.app.InstrumentationRegistry -import com.android.server.wm.flicker.Flicker import com.android.server.wm.flicker.FlickerTestRunner import com.android.server.wm.flicker.FlickerTestRunnerFactory import com.android.server.wm.flicker.focusChanges @@ -54,18 +53,16 @@ import org.junit.runners.Parameterized @FixMethodOrder(MethodSorters.NAME_ASCENDING) @FlakyTest(bugId = 152738416) class PipToAppTest( - testName: String, - flickerProvider: () -> Flicker, - cleanUp: Boolean -) : FlickerTestRunner(testName, flickerProvider, cleanUp) { + testSpec: FlickerTestRunnerFactory.TestSpec +) : FlickerTestRunner(testSpec) { companion object { @Parameterized.Parameters(name = "{0}") @JvmStatic fun getParams(): List<Array<Any>> { val instrumentation = InstrumentationRegistry.getInstrumentation() val testApp = PipAppHelper(instrumentation) - return FlickerTestRunnerFactory(instrumentation, listOf(Surface.ROTATION_0)) - .buildTest { configuration -> + return FlickerTestRunnerFactory.getInstance().buildTest(instrumentation, + supportedRotations = listOf(Surface.ROTATION_0)) { configuration -> withTestName { buildTestTag("exitPipModeToApp", testApp, configuration) } repeat { configuration.repetitions } setup { diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipToHomeTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipToHomeTest.kt index df88a2da0a92..5d3bc1388686 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipToHomeTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipToHomeTest.kt @@ -20,7 +20,6 @@ import android.view.Surface import androidx.test.filters.FlakyTest import androidx.test.filters.RequiresDevice import androidx.test.platform.app.InstrumentationRegistry -import com.android.server.wm.flicker.Flicker import com.android.server.wm.flicker.FlickerTestRunner import com.android.server.wm.flicker.FlickerTestRunnerFactory import com.android.server.wm.flicker.focusChanges @@ -53,18 +52,16 @@ import org.junit.runners.Parameterized @FixMethodOrder(MethodSorters.NAME_ASCENDING) @FlakyTest(bugId = 152738416) class PipToHomeTest( - testName: String, - flickerProvider: () -> Flicker, - cleanUp: Boolean -) : FlickerTestRunner(testName, flickerProvider, cleanUp) { + testSpec: FlickerTestRunnerFactory.TestSpec +) : FlickerTestRunner(testSpec) { companion object { @Parameterized.Parameters(name = "{0}") @JvmStatic fun getParams(): List<Array<Any>> { val instrumentation = InstrumentationRegistry.getInstrumentation() val testApp = PipAppHelper(instrumentation) - return FlickerTestRunnerFactory(instrumentation, listOf(Surface.ROTATION_0)) - .buildTest { configuration -> + return FlickerTestRunnerFactory.getInstance().buildTest(instrumentation, + supportedRotations = listOf(Surface.ROTATION_0)) { configuration -> withTestName { buildTestTag("exitPipModeToApp", testApp, configuration) } repeat { configuration.repetitions } setup { diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleDataTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleDataTest.java index 7c9b9c37c2c4..d3a736e9153e 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleDataTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleDataTest.java @@ -41,6 +41,7 @@ import androidx.test.filters.SmallTest; import com.android.wm.shell.ShellTestCase; import com.android.wm.shell.bubbles.BubbleData.TimeSource; +import com.android.wm.shell.common.ShellExecutor; import com.google.common.collect.ImmutableList; @@ -98,6 +99,8 @@ public class BubbleDataTest extends ShellTestCase { private PendingIntent mDeleteIntent; @Mock private BubbleLogger mBubbleLogger; + @Mock + private ShellExecutor mMainExecutor; @Captor private ArgumentCaptor<BubbleData.Update> mUpdateCaptor; @@ -124,21 +127,31 @@ public class BubbleDataTest extends ShellTestCase { mock(NotificationListenerService.Ranking.class); when(ranking.visuallyInterruptive()).thenReturn(true); mEntryInterruptive = createBubbleEntry(1, "interruptive", "package.d", ranking); - mBubbleInterruptive = new Bubble(mEntryInterruptive, mSuppressionListener, null); + mBubbleInterruptive = new Bubble(mEntryInterruptive, mSuppressionListener, null, + mMainExecutor); mEntryDismissed = createBubbleEntry(1, "dismissed", "package.d", null); - mBubbleDismissed = new Bubble(mEntryDismissed, mSuppressionListener, null); - - mBubbleA1 = new Bubble(mEntryA1, mSuppressionListener, mPendingIntentCanceledListener); - mBubbleA2 = new Bubble(mEntryA2, mSuppressionListener, mPendingIntentCanceledListener); - mBubbleA3 = new Bubble(mEntryA3, mSuppressionListener, mPendingIntentCanceledListener); - mBubbleB1 = new Bubble(mEntryB1, mSuppressionListener, mPendingIntentCanceledListener); - mBubbleB2 = new Bubble(mEntryB2, mSuppressionListener, mPendingIntentCanceledListener); - mBubbleB3 = new Bubble(mEntryB3, mSuppressionListener, mPendingIntentCanceledListener); - mBubbleC1 = new Bubble(mEntryC1, mSuppressionListener, mPendingIntentCanceledListener); + mBubbleDismissed = new Bubble(mEntryDismissed, mSuppressionListener, null, + mMainExecutor); + + mBubbleA1 = new Bubble(mEntryA1, mSuppressionListener, mPendingIntentCanceledListener, + mMainExecutor); + mBubbleA2 = new Bubble(mEntryA2, mSuppressionListener, mPendingIntentCanceledListener, + mMainExecutor); + mBubbleA3 = new Bubble(mEntryA3, mSuppressionListener, mPendingIntentCanceledListener, + mMainExecutor); + mBubbleB1 = new Bubble(mEntryB1, mSuppressionListener, mPendingIntentCanceledListener, + mMainExecutor); + mBubbleB2 = new Bubble(mEntryB2, mSuppressionListener, mPendingIntentCanceledListener, + mMainExecutor); + mBubbleB3 = new Bubble(mEntryB3, mSuppressionListener, mPendingIntentCanceledListener, + mMainExecutor); + mBubbleC1 = new Bubble(mEntryC1, mSuppressionListener, mPendingIntentCanceledListener, + mMainExecutor); TestableBubblePositioner positioner = new TestableBubblePositioner(mContext, mock(WindowManager.class)); - mBubbleData = new BubbleData(getContext(), mBubbleLogger, positioner); + mBubbleData = new BubbleData(getContext(), mBubbleLogger, positioner, + mMainExecutor); // Used by BubbleData to set lastAccessedTime when(mTimeSource.currentTimeMillis()).thenReturn(1000L); @@ -796,7 +809,7 @@ public class BubbleDataTest extends ShellTestCase { assertWithMessage("addedBubble").that(update.addedBubble).isEqualTo(expected); } - private void assertBubbleRemoved(Bubble expected, @BubbleController.DismissReason int reason) { + private void assertBubbleRemoved(Bubble expected, @Bubbles.DismissReason int reason) { BubbleData.Update update = mUpdateCaptor.getValue(); assertWithMessage("removedBubbles").that(update.removedBubbles) .isEqualTo(ImmutableList.of(Pair.create(expected, reason))); diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleTest.java index bde04b604c79..fc828b30279f 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleTest.java @@ -39,6 +39,7 @@ import androidx.test.filters.SmallTest; import com.android.wm.shell.R; import com.android.wm.shell.ShellTestCase; +import com.android.wm.shell.common.ShellExecutor; import org.junit.Before; import org.junit.Test; @@ -54,6 +55,8 @@ public class BubbleTest extends ShellTestCase { private Notification mNotif; @Mock private StatusBarNotification mSbn; + @Mock + private ShellExecutor mMainExecutor; private BubbleEntry mBubbleEntry; private Bundle mExtras; @@ -78,7 +81,7 @@ public class BubbleTest extends ShellTestCase { when(mNotif.getBubbleMetadata()).thenReturn(metadata); when(mSbn.getKey()).thenReturn("mock"); mBubbleEntry = new BubbleEntry(mSbn, null, true, false, false, false); - mBubble = new Bubble(mBubbleEntry, mSuppressionListener, null); + mBubble = new Bubble(mBubbleEntry, mSuppressionListener, null, mMainExecutor); } @Test diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipTouchStateTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipTouchStateTest.java index 0d4d1269f767..35656bde7169 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipTouchStateTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipTouchStateTest.java @@ -47,17 +47,17 @@ public class PipTouchStateTest extends ShellTestCase { private PipTouchState mTouchState; private CountDownLatch mDoubleTapCallbackTriggeredLatch; private CountDownLatch mHoverExitCallbackTriggeredLatch; - private TestShellExecutor mShellMainExecutor; + private TestShellExecutor mMainExecutor; @Before public void setUp() throws Exception { - mShellMainExecutor = new TestShellExecutor(); + mMainExecutor = new TestShellExecutor(); mDoubleTapCallbackTriggeredLatch = new CountDownLatch(1); mHoverExitCallbackTriggeredLatch = new CountDownLatch(1); mTouchState = new PipTouchState(ViewConfiguration.get(getContext()), mDoubleTapCallbackTriggeredLatch::countDown, mHoverExitCallbackTriggeredLatch::countDown, - mShellMainExecutor); + mMainExecutor); assertFalse(mTouchState.isDoubleTap()); assertFalse(mTouchState.isWaitingForDoubleTap()); } @@ -87,7 +87,7 @@ public class PipTouchStateTest extends ShellTestCase { assertTrue(mTouchState.getDoubleTapTimeoutCallbackDelay() == 10); mTouchState.scheduleDoubleTapTimeoutCallback(); - mShellMainExecutor.flushAll(); + mMainExecutor.flushAll(); assertTrue(mDoubleTapCallbackTriggeredLatch.getCount() == 0); } @@ -122,7 +122,7 @@ public class PipTouchStateTest extends ShellTestCase { @Test public void testHoverExitTimeout_timeoutCallbackCalled() throws Exception { mTouchState.scheduleHoverExitTimeoutCallback(); - mShellMainExecutor.flushAll(); + mMainExecutor.flushAll(); assertTrue(mHoverExitCallbackTriggeredLatch.getCount() == 0); } @@ -137,7 +137,7 @@ public class PipTouchStateTest extends ShellTestCase { mTouchState.scheduleHoverExitTimeoutCallback(); mTouchState.onTouchEvent(createMotionEvent(ACTION_BUTTON_PRESS, SystemClock.uptimeMillis(), 0, 0)); - mShellMainExecutor.flushAll(); + mMainExecutor.flushAll(); assertTrue(mHoverExitCallbackTriggeredLatch.getCount() == 1); } diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp index 615bf4de9fcc..ce1d96c167d7 100644 --- a/libs/hwui/Android.bp +++ b/libs/hwui/Android.bp @@ -435,6 +435,7 @@ cc_defaults { "canvas/CanvasFrontend.cpp", "canvas/CanvasOpBuffer.cpp", "canvas/CanvasOpRasterizer.cpp", + "effects/StretchEffect.cpp", "pipeline/skia/SkiaDisplayList.cpp", "pipeline/skia/SkiaRecordingCanvas.cpp", "pipeline/skia/RenderNodeDrawable.cpp", diff --git a/libs/hwui/RenderProperties.h b/libs/hwui/RenderProperties.h index aeb60e6ce355..609706e2e49d 100644 --- a/libs/hwui/RenderProperties.h +++ b/libs/hwui/RenderProperties.h @@ -23,6 +23,7 @@ #include "Outline.h" #include "Rect.h" #include "RevealClip.h" +#include "effects/StretchEffect.h" #include "utils/MathUtils.h" #include "utils/PaintUtils.h" @@ -98,6 +99,10 @@ public: SkImageFilter* getImageFilter() const { return mImageFilter.get(); } + const StretchEffect& getStretchEffect() const { return mStretchEffect; } + + StretchEffect& mutableStretchEffect() { return mStretchEffect; } + // Sets alpha, xfermode, and colorfilter from an SkPaint // paint may be NULL, in which case defaults will be set bool setFromPaint(const SkPaint* paint); @@ -124,6 +129,7 @@ private: SkBlendMode mMode; sk_sp<SkColorFilter> mColorFilter; sk_sp<SkImageFilter> mImageFilter; + StretchEffect mStretchEffect; }; /* diff --git a/libs/hwui/effects/StretchEffect.cpp b/libs/hwui/effects/StretchEffect.cpp new file mode 100644 index 000000000000..51cbc7592861 --- /dev/null +++ b/libs/hwui/effects/StretchEffect.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2021 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. + */ + +#include "StretchEffect.h" + +namespace android::uirenderer { + +sk_sp<SkImageFilter> StretchEffect::getImageFilter() const { + // TODO: Implement & Cache + // Probably need to use mutable to achieve caching + return nullptr; +} + +} // namespace android::uirenderer
\ No newline at end of file diff --git a/libs/hwui/effects/StretchEffect.h b/libs/hwui/effects/StretchEffect.h new file mode 100644 index 000000000000..7dfd6398765a --- /dev/null +++ b/libs/hwui/effects/StretchEffect.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2021 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. + */ + +#pragma once + +#include "utils/MathUtils.h" + +#include <SkPoint.h> +#include <SkRect.h> +#include <SkImageFilter.h> + +namespace android::uirenderer { + +// TODO: Inherit from base RenderEffect type? +class StretchEffect { +public: + enum class StretchInterpolator { + SmoothStep, + }; + + bool isEmpty() const { + return MathUtils::isZero(stretchDirection.x()) + && MathUtils::isZero(stretchDirection.y()); + } + + void setEmpty() { + *this = StretchEffect{}; + } + + void mergeWith(const StretchEffect& other) { + if (other.isEmpty()) { + return; + } + if (isEmpty()) { + *this = other; + return; + } + stretchDirection += other.stretchDirection; + if (isEmpty()) { + return setEmpty(); + } + stretchArea.join(other.stretchArea); + maxStretchAmount = std::max(maxStretchAmount, other.maxStretchAmount); + } + + sk_sp<SkImageFilter> getImageFilter() const; + + SkRect stretchArea {0, 0, 0, 0}; + SkVector stretchDirection {0, 0}; + float maxStretchAmount = 0; +}; + +} // namespace android::uirenderer diff --git a/libs/hwui/jni/android_graphics_RenderNode.cpp b/libs/hwui/jni/android_graphics_RenderNode.cpp index 8b35d96aeac8..80239687a7fb 100644 --- a/libs/hwui/jni/android_graphics_RenderNode.cpp +++ b/libs/hwui/jni/android_graphics_RenderNode.cpp @@ -166,6 +166,31 @@ static jboolean android_view_RenderNode_setOutlineNone(CRITICAL_JNI_PARAMS_COMMA return true; } +static jboolean android_view_RenderNode_clearStretch(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) { + RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); + auto& stretch = renderNode->mutateStagingProperties() + .mutateLayerProperties().mutableStretchEffect(); + if (stretch.isEmpty()) { + return false; + } + stretch.setEmpty(); + renderNode->setPropertyFieldsDirty(RenderNode::GENERIC); + return true; +} + +static jboolean android_view_RenderNode_stretch(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, + jfloat left, jfloat top, jfloat right, jfloat bottom, jfloat vX, jfloat vY, jfloat max) { + RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); + renderNode->mutateStagingProperties().mutateLayerProperties().mutableStretchEffect().mergeWith( + StretchEffect{ + .stretchArea = SkRect::MakeLTRB(left, top, right, bottom), + .stretchDirection = {.fX = vX, .fY = vY}, + .maxStretchAmount = max + }); + renderNode->setPropertyFieldsDirty(RenderNode::GENERIC); + return true; +} + static jboolean android_view_RenderNode_hasShadow(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) { RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); return renderNode->stagingProperties().hasShadow(); @@ -678,6 +703,8 @@ static const JNINativeMethod gMethods[] = { { "nSetOutlinePath", "(JJF)Z", (void*) android_view_RenderNode_setOutlinePath }, { "nSetOutlineEmpty", "(J)Z", (void*) android_view_RenderNode_setOutlineEmpty }, { "nSetOutlineNone", "(J)Z", (void*) android_view_RenderNode_setOutlineNone }, + { "nClearStretch", "(J)Z", (void*) android_view_RenderNode_clearStretch }, + { "nStretch", "(JFFFFFFF)Z", (void*) android_view_RenderNode_stretch }, { "nHasShadow", "(J)Z", (void*) android_view_RenderNode_hasShadow }, { "nSetSpotShadowColor", "(JI)Z", (void*) android_view_RenderNode_setSpotShadowColor }, { "nGetSpotShadowColor", "(J)I", (void*) android_view_RenderNode_getSpotShadowColor }, diff --git a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp index 75815bb6e63d..c01021221f37 100644 --- a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp +++ b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp @@ -20,6 +20,8 @@ #include "SkiaDisplayList.h" #include "utils/TraceUtils.h" +#include <include/effects/SkImageFilters.h> + #include <optional> namespace android { @@ -171,11 +173,25 @@ static bool layerNeedsPaint(const LayerProperties& properties, float alphaMultip SkPaint* paint) { if (alphaMultiplier < 1.0f || properties.alpha() < 255 || properties.xferMode() != SkBlendMode::kSrcOver || properties.getColorFilter() != nullptr || - properties.getImageFilter() != nullptr) { + properties.getImageFilter() != nullptr || !properties.getStretchEffect().isEmpty()) { paint->setAlpha(properties.alpha() * alphaMultiplier); paint->setBlendMode(properties.xferMode()); paint->setColorFilter(sk_ref_sp(properties.getColorFilter())); - paint->setImageFilter(sk_ref_sp(properties.getImageFilter())); + + sk_sp<SkImageFilter> imageFilter = sk_ref_sp(properties.getImageFilter()); + sk_sp<SkImageFilter> stretchFilter = properties.getStretchEffect().getImageFilter(); + sk_sp<SkImageFilter> filter; + if (imageFilter && stretchFilter) { + filter = SkImageFilters::Compose( + std::move(stretchFilter), + std::move(imageFilter) + ); + } else if (stretchFilter) { + filter = std::move(stretchFilter); + } else { + filter = std::move(imageFilter); + } + paint->setImageFilter(std::move(filter)); return true; } return false; diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp index eacabfd1dbf9..633f21ceba07 100644 --- a/libs/hwui/renderthread/CanvasContext.cpp +++ b/libs/hwui/renderthread/CanvasContext.cpp @@ -490,9 +490,11 @@ void CanvasContext::draw() { if (mNativeSurface) { // TODO(b/165985262): measure performance impact - if (const auto vsyncId = mCurrentFrameInfo->get(FrameInfoIndex::FrameTimelineVsyncId); - vsyncId != UiFrameInfoBuilder::INVALID_VSYNC_ID) { - native_window_set_frame_timeline_vsync(mNativeSurface->getNativeWindow(), vsyncId); + const auto vsyncId = mCurrentFrameInfo->get(FrameInfoIndex::FrameTimelineVsyncId); + if (vsyncId != UiFrameInfoBuilder::INVALID_VSYNC_ID) { + const auto inputEventId = mCurrentFrameInfo->get(FrameInfoIndex::NewestInputEvent); + native_window_set_frame_timeline_info(mNativeSurface->getNativeWindow(), vsyncId, + inputEventId); } } diff --git a/location/java/android/location/GnssMeasurement.java b/location/java/android/location/GnssMeasurement.java index 3d188c0acce3..65a0110ad87e 100644 --- a/location/java/android/location/GnssMeasurement.java +++ b/location/java/android/location/GnssMeasurement.java @@ -31,6 +31,7 @@ import android.annotation.FloatRange; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.annotation.TestApi; import android.os.Parcel; @@ -1775,6 +1776,7 @@ public final class GnssMeasurement implements Parcelable { */ @Nullable @SystemApi + @SuppressLint("NullableCollection") public Collection<CorrelationVector> getCorrelationVectors() { return mReadOnlyCorrelationVectors; } @@ -1785,7 +1787,9 @@ public final class GnssMeasurement implements Parcelable { * @hide */ @TestApi - public void setCorrelationVectors(@Nullable Collection<CorrelationVector> correlationVectors) { + public void setCorrelationVectors( + @SuppressLint("NullableCollection") + @Nullable Collection<CorrelationVector> correlationVectors) { if (correlationVectors == null || correlationVectors.isEmpty()) { resetCorrelationVectors(); } else { diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java index 96ec59021d28..fdb044d0dcf6 100644 --- a/location/java/android/location/LocationManager.java +++ b/location/java/android/location/LocationManager.java @@ -2233,6 +2233,7 @@ public class LocationManager { * @see #getGnssCapabilities() */ @Nullable + @SuppressLint("NullableCollection") public List<GnssAntennaInfo> getGnssAntennaInfos() { try { return mService.getGnssAntennaInfos(); diff --git a/location/java/android/location/provider/LocationProviderBase.java b/location/java/android/location/provider/LocationProviderBase.java index 1306ea2c0204..8f455cd7df07 100644 --- a/location/java/android/location/provider/LocationProviderBase.java +++ b/location/java/android/location/provider/LocationProviderBase.java @@ -255,7 +255,9 @@ public abstract class LocationProviderBase { /** * Implements optional custom commands. */ - public abstract void onSendExtraCommand(@NonNull String command, @Nullable Bundle extras); + public abstract void onSendExtraCommand(@NonNull String command, + @SuppressLint("NullableCollection") + @Nullable Bundle extras); private final class Service extends ILocationProvider.Stub { diff --git a/media/java/android/media/MediaServiceManager.java b/media/java/android/media/MediaServiceManager.java index 96bff4f92668..b899559d2e50 100644 --- a/media/java/android/media/MediaServiceManager.java +++ b/media/java/android/media/MediaServiceManager.java @@ -33,6 +33,7 @@ import android.os.ServiceManager; public class MediaServiceManager { private static final String MEDIA_SESSION_SERVICE = "media_session"; private static final String MEDIA_TRANSCODING_SERVICE = "media.transcoding"; + private static final String MEDIA_COMMUNICATION_SERVICE = "media_communication"; /** * @hide @@ -79,4 +80,12 @@ public class MediaServiceManager { public ServiceRegisterer getMediaTranscodingServiceRegisterer() { return new ServiceRegisterer(MEDIA_TRANSCODING_SERVICE); } + + /** + * Returns {@link ServiceRegisterer} for MEDIA_COMMUNICATION_SERVICE. + */ + @NonNull + public ServiceRegisterer getMediaCommunicationServiceRegisterer() { + return new ServiceRegisterer(MEDIA_COMMUNICATION_SERVICE); + } } diff --git a/media/java/android/media/musicrecognition/MusicRecognitionManager.java b/media/java/android/media/musicrecognition/MusicRecognitionManager.java index 6bbcfd3b5b66..b183eaff83ec 100644 --- a/media/java/android/media/musicrecognition/MusicRecognitionManager.java +++ b/media/java/android/media/musicrecognition/MusicRecognitionManager.java @@ -23,6 +23,7 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; +import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.annotation.SystemService; import android.content.Context; @@ -90,7 +91,9 @@ public class MusicRecognitionManager { * supplied bundle */ void onRecognitionSucceeded(@NonNull RecognitionRequest recognitionRequest, - @NonNull MediaMetadata result, @Nullable Bundle extras); + @NonNull MediaMetadata result, + @SuppressLint("NullableCollection") + @Nullable Bundle extras); /** * Invoked when the search is not successful (possibly but not necessarily due to error). diff --git a/media/java/android/media/musicrecognition/MusicRecognitionService.java b/media/java/android/media/musicrecognition/MusicRecognitionService.java index e2071b84c00b..04b4c39bf0fa 100644 --- a/media/java/android/media/musicrecognition/MusicRecognitionService.java +++ b/media/java/android/media/musicrecognition/MusicRecognitionService.java @@ -20,6 +20,7 @@ import static com.android.internal.util.function.pooled.PooledLambda.obtainMessa import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.app.Service; import android.content.Intent; @@ -53,7 +54,9 @@ public abstract class MusicRecognitionService extends Service { * @param extras extra data to be supplied back to the caller. Note that all executable * parameters and file descriptors would be removed from the supplied bundle */ - void onRecognitionSucceeded(@NonNull MediaMetadata result, @Nullable Bundle extras); + void onRecognitionSucceeded(@NonNull MediaMetadata result, + @SuppressLint("NullableCollection") + @Nullable Bundle extras); /** * Call this method if the search does not find a result on an error occurred. diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java index 4d835b22e34c..8525e9979aef 100644 --- a/media/java/android/media/tv/tuner/Tuner.java +++ b/media/java/android/media/tv/tuner/Tuner.java @@ -22,6 +22,7 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; +import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.content.Context; import android.hardware.tv.tuner.V1_0.Constants; @@ -1017,6 +1018,7 @@ public class Tuner implements AutoCloseable { * failed. */ @Nullable + @SuppressLint("NullableCollection") public List<FrontendInfo> getAvailableFrontendInfos() { FrontendInfo[] feInfoList = getFrontendInfoListInternal(); if (feInfoList == null) { diff --git a/media/java/android/media/tv/tuner/filter/Filter.java b/media/java/android/media/tv/tuner/filter/Filter.java index 9f327c93f63b..51b685aeb8be 100644 --- a/media/java/android/media/tv/tuner/filter/Filter.java +++ b/media/java/android/media/tv/tuner/filter/Filter.java @@ -284,6 +284,12 @@ public class Filter implements AutoCloseable { /** * Configures the filter. * + * <p>Recofiguring must happen after stopping the filter. + * + * <p>When stopping, reconfiguring and restarting the filter, the client should discard all + * coming events until it receives {@link RestartEvent} through {@link FilterCallback} to avoid + * using the events from the previous configuration. + * * @param config the configuration of the filter. * @return result status of the operation. */ @@ -393,6 +399,10 @@ public class Filter implements AutoCloseable { * * <p>Does nothing if the filter is already started. * + * <p>When stopping, reconfiguring and restarting the filter, the client should discard all + * coming events until it receives {@link RestartEvent} through {@link FilterCallback} to avoid + * using the events from the previous configuration. + * * @return result status of the operation. */ @Result @@ -409,6 +419,12 @@ public class Filter implements AutoCloseable { * * <p>Does nothing if the filter is stopped or not started. * + * <p>Filter must be stopped to reconfigure. + * + * <p>When stopping, reconfiguring and restarting the filter, the client should discard all + * coming events until it receives {@link RestartEvent} through {@link FilterCallback} to avoid + * using the events from the previous configuration. + * * @return result status of the operation. */ @Result diff --git a/media/java/android/media/tv/tuner/filter/RestartEvent.java b/media/java/android/media/tv/tuner/filter/RestartEvent.java index 069630188e55..9c5992af5f48 100644 --- a/media/java/android/media/tv/tuner/filter/RestartEvent.java +++ b/media/java/android/media/tv/tuner/filter/RestartEvent.java @@ -19,17 +19,29 @@ package android.media.tv.tuner.filter; import android.annotation.SystemApi; /** - * An Event that the client would reveice after stopping, reconfiguring and restarting a filter. + * An Event that the client would receive after starting a filter. This event is optional to be + * received on the newly opened and started filter. It must be received after stopping, + * reconfiguring and restarting a Filter to differentiate the valid reconfigured events from the + * previous events. * * <p>After stopping and restarting the filter, the client has to discard all coming events until * it receives {@link RestartEvent} to avoid using the events from the previous configuration. * * <p>Recofiguring must happen after stopping the filter. * + * @see Filter#stop() + * @see Filter#start() + * @see Filter#configure(FilterConfiguration) + * * @hide */ @SystemApi public final class RestartEvent extends FilterEvent { + /** + * The stard id reserved for the newly opened filter's first start event. + */ + public static final int NEW_FILTER_FIRST_START_ID = 0; + private final int mStartId; // This constructor is used by JNI code only @@ -38,13 +50,13 @@ public final class RestartEvent extends FilterEvent { } /** - * Gets the start id. + * Gets the start id sent via the current Restart Event. * - * <p>An unique ID to mark the start point of receiving the valid filter events after - * reconfiguring. It must be sent at least once in the first event after the filter is - * restarted. + * <p>An unique ID to mark the start point of receiving the valid reconfigured filter events. + * The client must receive at least once after the filter is reconfigured and restarted. * - * <p>0 is reserved for the newly opened filter's first start. It's optional to be received. + * <p>{@link #NEW_FILTER_FIRST_START_ID} is reserved for the newly opened filter's first start. + * It's optional to be received. */ public int getStartId() { return mStartId; diff --git a/media/jni/android_media_MediaMetricsJNI.cpp b/media/jni/android_media_MediaMetricsJNI.cpp index c064de299b19..08a8d897c96e 100644 --- a/media/jni/android_media_MediaMetricsJNI.cpp +++ b/media/jni/android_media_MediaMetricsJNI.cpp @@ -18,7 +18,6 @@ #include <binder/Parcel.h> #include <jni.h> -#include <media/IMediaMetricsService.h> #include <media/MediaMetricsItem.h> #include <nativehelper/JNIHelp.h> #include <variant> @@ -151,12 +150,7 @@ static jint android_media_MediaMetrics_submit_bytebuffer( return (jint)BAD_VALUE; } - sp<IMediaMetricsService> service = mediametrics::BaseItem::getService(); - if (service == nullptr) { - ALOGW("Cannot retrieve mediametrics service"); - return (jint)NO_INIT; - } - return (jint)service->submitBuffer((char *)buffer, length); + return (jint)mediametrics::BaseItem::submitBuffer((char *)buffer, length); } // Helper function to convert a native PersistableBundle to a Java diff --git a/core/java/android/net/CaptivePortal.java b/packages/Connectivity/framework/src/android/net/CaptivePortal.java index 269bbf20c8b1..269bbf20c8b1 100644 --- a/core/java/android/net/CaptivePortal.java +++ b/packages/Connectivity/framework/src/android/net/CaptivePortal.java diff --git a/core/java/android/net/CaptivePortalData.aidl b/packages/Connectivity/framework/src/android/net/CaptivePortalData.aidl index 1d57ee759136..1d57ee759136 100644 --- a/core/java/android/net/CaptivePortalData.aidl +++ b/packages/Connectivity/framework/src/android/net/CaptivePortalData.aidl diff --git a/core/java/android/net/CaptivePortalData.java b/packages/Connectivity/framework/src/android/net/CaptivePortalData.java index 9b56b23cc879..9b56b23cc879 100644 --- a/core/java/android/net/CaptivePortalData.java +++ b/packages/Connectivity/framework/src/android/net/CaptivePortalData.java diff --git a/core/java/android/net/ConnectionInfo.aidl b/packages/Connectivity/framework/src/android/net/ConnectionInfo.aidl index 07faf8bbbed8..07faf8bbbed8 100644 --- a/core/java/android/net/ConnectionInfo.aidl +++ b/packages/Connectivity/framework/src/android/net/ConnectionInfo.aidl diff --git a/core/java/android/net/ConnectionInfo.java b/packages/Connectivity/framework/src/android/net/ConnectionInfo.java index 4514a8484d96..4514a8484d96 100644 --- a/core/java/android/net/ConnectionInfo.java +++ b/packages/Connectivity/framework/src/android/net/ConnectionInfo.java diff --git a/core/java/android/net/ConnectivityDiagnosticsManager.aidl b/packages/Connectivity/framework/src/android/net/ConnectivityDiagnosticsManager.aidl index 82ba0ca113c5..82ba0ca113c5 100644 --- a/core/java/android/net/ConnectivityDiagnosticsManager.aidl +++ b/packages/Connectivity/framework/src/android/net/ConnectivityDiagnosticsManager.aidl diff --git a/core/java/android/net/ConnectivityDiagnosticsManager.java b/packages/Connectivity/framework/src/android/net/ConnectivityDiagnosticsManager.java index 523449497345..523449497345 100644 --- a/core/java/android/net/ConnectivityDiagnosticsManager.java +++ b/packages/Connectivity/framework/src/android/net/ConnectivityDiagnosticsManager.java diff --git a/packages/Connectivity/framework/src/android/net/ConnectivityFrameworkInitializer.java b/packages/Connectivity/framework/src/android/net/ConnectivityFrameworkInitializer.java new file mode 100644 index 000000000000..9afa5d1311c5 --- /dev/null +++ b/packages/Connectivity/framework/src/android/net/ConnectivityFrameworkInitializer.java @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2021 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.net; + +import android.annotation.SystemApi; +import android.app.SystemServiceRegistry; +import android.content.Context; + +/** + * Class for performing registration for all core connectivity services. + * + * @hide + */ +@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) +public final class ConnectivityFrameworkInitializer { + private ConnectivityFrameworkInitializer() {} + + /** + * Called by {@link SystemServiceRegistry}'s static initializer and registers all core + * connectivity services to {@link Context}, so that {@link Context#getSystemService} can + * return them. + * + * @throws IllegalStateException if this is called anywhere besides + * {@link SystemServiceRegistry}. + */ + public static void registerServiceWrappers() { + // registerContextAwareService will throw if this is called outside of SystemServiceRegistry + // initialization. + SystemServiceRegistry.registerContextAwareService( + Context.CONNECTIVITY_SERVICE, + ConnectivityManager.class, + (context, serviceBinder) -> { + IConnectivityManager icm = IConnectivityManager.Stub.asInterface(serviceBinder); + return new ConnectivityManager(context, icm); + } + ); + + // TODO: move outside of the connectivity JAR + SystemServiceRegistry.registerContextAwareService( + Context.VPN_MANAGEMENT_SERVICE, + VpnManager.class, + (context) -> { + final ConnectivityManager cm = context.getSystemService( + ConnectivityManager.class); + return cm.createVpnManager(); + } + ); + + SystemServiceRegistry.registerContextAwareService( + Context.CONNECTIVITY_DIAGNOSTICS_SERVICE, + ConnectivityDiagnosticsManager.class, + (context) -> { + final ConnectivityManager cm = context.getSystemService( + ConnectivityManager.class); + return cm.createDiagnosticsManager(); + } + ); + + SystemServiceRegistry.registerContextAwareService( + Context.TEST_NETWORK_SERVICE, + TestNetworkManager.class, + context -> { + final ConnectivityManager cm = context.getSystemService( + ConnectivityManager.class); + return cm.startOrGetTestNetworkManager(); + } + ); + } +} diff --git a/core/java/android/net/ConnectivityManager.java b/packages/Connectivity/framework/src/android/net/ConnectivityManager.java index ac8f9c9e62fd..2a0a74ed0604 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/packages/Connectivity/framework/src/android/net/ConnectivityManager.java @@ -4823,6 +4823,28 @@ public class ConnectivityManager { } } + /** @hide */ + public TestNetworkManager startOrGetTestNetworkManager() { + final IBinder tnBinder; + try { + tnBinder = mService.startOrGetTestNetworkService(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + + return new TestNetworkManager(ITestNetworkManager.Stub.asInterface(tnBinder)); + } + + /** @hide */ + public VpnManager createVpnManager() { + return new VpnManager(mContext, mService); + } + + /** @hide */ + public ConnectivityDiagnosticsManager createDiagnosticsManager() { + return new ConnectivityDiagnosticsManager(mContext, mService); + } + /** * Simulates a Data Stall for the specified Network. * diff --git a/core/java/android/net/ConnectivityMetricsEvent.aidl b/packages/Connectivity/framework/src/android/net/ConnectivityMetricsEvent.aidl index 1c541dc4c8cc..1c541dc4c8cc 100644 --- a/core/java/android/net/ConnectivityMetricsEvent.aidl +++ b/packages/Connectivity/framework/src/android/net/ConnectivityMetricsEvent.aidl diff --git a/core/java/android/net/ConnectivityThread.java b/packages/Connectivity/framework/src/android/net/ConnectivityThread.java index 0b218e738b77..0b218e738b77 100644 --- a/core/java/android/net/ConnectivityThread.java +++ b/packages/Connectivity/framework/src/android/net/ConnectivityThread.java diff --git a/core/java/android/net/DhcpInfo.aidl b/packages/Connectivity/framework/src/android/net/DhcpInfo.aidl index 29cd21fe7652..29cd21fe7652 100644 --- a/core/java/android/net/DhcpInfo.aidl +++ b/packages/Connectivity/framework/src/android/net/DhcpInfo.aidl diff --git a/core/java/android/net/DhcpInfo.java b/packages/Connectivity/framework/src/android/net/DhcpInfo.java index 912df67a0b45..912df67a0b45 100644 --- a/core/java/android/net/DhcpInfo.java +++ b/packages/Connectivity/framework/src/android/net/DhcpInfo.java diff --git a/core/java/android/net/DnsResolver.java b/packages/Connectivity/framework/src/android/net/DnsResolver.java index 3f7660f5709a..3f7660f5709a 100644 --- a/core/java/android/net/DnsResolver.java +++ b/packages/Connectivity/framework/src/android/net/DnsResolver.java diff --git a/core/java/android/net/ICaptivePortal.aidl b/packages/Connectivity/framework/src/android/net/ICaptivePortal.aidl index fe21905c7002..fe21905c7002 100644 --- a/core/java/android/net/ICaptivePortal.aidl +++ b/packages/Connectivity/framework/src/android/net/ICaptivePortal.aidl diff --git a/core/java/android/net/IConnectivityDiagnosticsCallback.aidl b/packages/Connectivity/framework/src/android/net/IConnectivityDiagnosticsCallback.aidl index 82b64a928000..82b64a928000 100644 --- a/core/java/android/net/IConnectivityDiagnosticsCallback.aidl +++ b/packages/Connectivity/framework/src/android/net/IConnectivityDiagnosticsCallback.aidl diff --git a/core/java/android/net/IConnectivityManager.aidl b/packages/Connectivity/framework/src/android/net/IConnectivityManager.aidl index 1b4d2e413943..1b4d2e413943 100644 --- a/core/java/android/net/IConnectivityManager.aidl +++ b/packages/Connectivity/framework/src/android/net/IConnectivityManager.aidl diff --git a/core/java/android/net/ISocketKeepaliveCallback.aidl b/packages/Connectivity/framework/src/android/net/ISocketKeepaliveCallback.aidl index 020fbcacbfef..020fbcacbfef 100644 --- a/core/java/android/net/ISocketKeepaliveCallback.aidl +++ b/packages/Connectivity/framework/src/android/net/ISocketKeepaliveCallback.aidl diff --git a/core/java/android/net/ITestNetworkManager.aidl b/packages/Connectivity/framework/src/android/net/ITestNetworkManager.aidl index 2a863adde581..2a863adde581 100644 --- a/core/java/android/net/ITestNetworkManager.aidl +++ b/packages/Connectivity/framework/src/android/net/ITestNetworkManager.aidl diff --git a/core/java/android/net/InetAddresses.java b/packages/Connectivity/framework/src/android/net/InetAddresses.java index 01b795e456fa..01b795e456fa 100644 --- a/core/java/android/net/InetAddresses.java +++ b/packages/Connectivity/framework/src/android/net/InetAddresses.java diff --git a/core/java/android/net/InterfaceConfiguration.aidl b/packages/Connectivity/framework/src/android/net/InterfaceConfiguration.aidl index 8aa5e3452853..8aa5e3452853 100644 --- a/core/java/android/net/InterfaceConfiguration.aidl +++ b/packages/Connectivity/framework/src/android/net/InterfaceConfiguration.aidl diff --git a/core/java/android/net/InvalidPacketException.java b/packages/Connectivity/framework/src/android/net/InvalidPacketException.java index 1873d778c0f2..1873d778c0f2 100644 --- a/core/java/android/net/InvalidPacketException.java +++ b/packages/Connectivity/framework/src/android/net/InvalidPacketException.java diff --git a/core/java/android/net/IpConfiguration.aidl b/packages/Connectivity/framework/src/android/net/IpConfiguration.aidl index 7a30f0e79cad..7a30f0e79cad 100644 --- a/core/java/android/net/IpConfiguration.aidl +++ b/packages/Connectivity/framework/src/android/net/IpConfiguration.aidl diff --git a/core/java/android/net/IpConfiguration.java b/packages/Connectivity/framework/src/android/net/IpConfiguration.java index d5f8b2edb6bb..d5f8b2edb6bb 100644 --- a/core/java/android/net/IpConfiguration.java +++ b/packages/Connectivity/framework/src/android/net/IpConfiguration.java diff --git a/core/java/android/net/IpPrefix.aidl b/packages/Connectivity/framework/src/android/net/IpPrefix.aidl index 0d70f2a1ed2c..0d70f2a1ed2c 100644 --- a/core/java/android/net/IpPrefix.aidl +++ b/packages/Connectivity/framework/src/android/net/IpPrefix.aidl diff --git a/core/java/android/net/IpPrefix.java b/packages/Connectivity/framework/src/android/net/IpPrefix.java index bcb65fab8571..bcb65fab8571 100644 --- a/core/java/android/net/IpPrefix.java +++ b/packages/Connectivity/framework/src/android/net/IpPrefix.java diff --git a/core/java/android/net/KeepalivePacketData.aidl b/packages/Connectivity/framework/src/android/net/KeepalivePacketData.aidl index d456b53fd188..d456b53fd188 100644 --- a/core/java/android/net/KeepalivePacketData.aidl +++ b/packages/Connectivity/framework/src/android/net/KeepalivePacketData.aidl diff --git a/core/java/android/net/KeepalivePacketData.java b/packages/Connectivity/framework/src/android/net/KeepalivePacketData.java index 5877f1f4e269..5877f1f4e269 100644 --- a/core/java/android/net/KeepalivePacketData.java +++ b/packages/Connectivity/framework/src/android/net/KeepalivePacketData.java diff --git a/core/java/android/net/LinkAddress.aidl b/packages/Connectivity/framework/src/android/net/LinkAddress.aidl index 9c804db08d61..9c804db08d61 100644 --- a/core/java/android/net/LinkAddress.aidl +++ b/packages/Connectivity/framework/src/android/net/LinkAddress.aidl diff --git a/core/java/android/net/LinkAddress.java b/packages/Connectivity/framework/src/android/net/LinkAddress.java index d1bdaa078cdc..d1bdaa078cdc 100644 --- a/core/java/android/net/LinkAddress.java +++ b/packages/Connectivity/framework/src/android/net/LinkAddress.java diff --git a/core/java/android/net/LinkProperties.aidl b/packages/Connectivity/framework/src/android/net/LinkProperties.aidl index a8b3c7b0392f..a8b3c7b0392f 100644 --- a/core/java/android/net/LinkProperties.aidl +++ b/packages/Connectivity/framework/src/android/net/LinkProperties.aidl diff --git a/core/java/android/net/LinkProperties.java b/packages/Connectivity/framework/src/android/net/LinkProperties.java index e41ed72b259c..e41ed72b259c 100644 --- a/core/java/android/net/LinkProperties.java +++ b/packages/Connectivity/framework/src/android/net/LinkProperties.java diff --git a/core/java/android/net/MacAddress.aidl b/packages/Connectivity/framework/src/android/net/MacAddress.aidl index 48a18a7ac821..48a18a7ac821 100644 --- a/core/java/android/net/MacAddress.aidl +++ b/packages/Connectivity/framework/src/android/net/MacAddress.aidl diff --git a/core/java/android/net/MacAddress.java b/packages/Connectivity/framework/src/android/net/MacAddress.java index c83c23a4b66e..c83c23a4b66e 100644 --- a/core/java/android/net/MacAddress.java +++ b/packages/Connectivity/framework/src/android/net/MacAddress.java diff --git a/core/java/android/net/NattKeepalivePacketData.java b/packages/Connectivity/framework/src/android/net/NattKeepalivePacketData.java index c4f8fc281f25..c4f8fc281f25 100644 --- a/core/java/android/net/NattKeepalivePacketData.java +++ b/packages/Connectivity/framework/src/android/net/NattKeepalivePacketData.java diff --git a/core/java/android/net/NattSocketKeepalive.java b/packages/Connectivity/framework/src/android/net/NattSocketKeepalive.java index a15d165e65e7..a15d165e65e7 100644 --- a/core/java/android/net/NattSocketKeepalive.java +++ b/packages/Connectivity/framework/src/android/net/NattSocketKeepalive.java diff --git a/core/java/android/net/Network.aidl b/packages/Connectivity/framework/src/android/net/Network.aidl index 05622025bf33..05622025bf33 100644 --- a/core/java/android/net/Network.aidl +++ b/packages/Connectivity/framework/src/android/net/Network.aidl diff --git a/core/java/android/net/Network.java b/packages/Connectivity/framework/src/android/net/Network.java index 46141e0d0c1e..46141e0d0c1e 100644 --- a/core/java/android/net/Network.java +++ b/packages/Connectivity/framework/src/android/net/Network.java diff --git a/core/java/android/net/NetworkAgent.java b/packages/Connectivity/framework/src/android/net/NetworkAgent.java index d22d82d1f4d0..d22d82d1f4d0 100644 --- a/core/java/android/net/NetworkAgent.java +++ b/packages/Connectivity/framework/src/android/net/NetworkAgent.java diff --git a/core/java/android/net/NetworkAgentConfig.aidl b/packages/Connectivity/framework/src/android/net/NetworkAgentConfig.aidl index cb70bdd31260..cb70bdd31260 100644 --- a/core/java/android/net/NetworkAgentConfig.aidl +++ b/packages/Connectivity/framework/src/android/net/NetworkAgentConfig.aidl diff --git a/core/java/android/net/NetworkAgentConfig.java b/packages/Connectivity/framework/src/android/net/NetworkAgentConfig.java index 664c2650ff0c..664c2650ff0c 100644 --- a/core/java/android/net/NetworkAgentConfig.java +++ b/packages/Connectivity/framework/src/android/net/NetworkAgentConfig.java diff --git a/core/java/android/net/NetworkCapabilities.aidl b/packages/Connectivity/framework/src/android/net/NetworkCapabilities.aidl index 01d328605de4..01d328605de4 100644 --- a/core/java/android/net/NetworkCapabilities.aidl +++ b/packages/Connectivity/framework/src/android/net/NetworkCapabilities.aidl diff --git a/core/java/android/net/NetworkCapabilities.java b/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java index 3843b9ab93c2..0832152d6ab6 100644 --- a/core/java/android/net/NetworkCapabilities.java +++ b/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java @@ -34,9 +34,9 @@ import android.util.ArraySet; import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.ArrayUtils; import com.android.internal.util.BitUtils; import com.android.internal.util.Preconditions; +import com.android.net.module.util.CollectionUtils; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -767,7 +767,7 @@ public final class NetworkCapabilities implements Parcelable { if (originalOwnerUid == creatorUid) { setOwnerUid(creatorUid); } - if (ArrayUtils.contains(originalAdministratorUids, creatorUid)) { + if (CollectionUtils.contains(originalAdministratorUids, creatorUid)) { setAdministratorUids(new int[] {creatorUid}); } // There is no need to clear the UIDs, they have already been cleared by clearAll() above. @@ -1873,7 +1873,7 @@ public final class NetworkCapabilities implements Parcelable { sb.append(" OwnerUid: ").append(mOwnerUid); } - if (!ArrayUtils.isEmpty(mAdministratorUids)) { + if (mAdministratorUids != null && mAdministratorUids.length != 0) { sb.append(" AdminUids: ").append(Arrays.toString(mAdministratorUids)); } @@ -2506,7 +2506,7 @@ public final class NetworkCapabilities implements Parcelable { @NonNull public NetworkCapabilities build() { if (mCaps.getOwnerUid() != Process.INVALID_UID) { - if (!ArrayUtils.contains(mCaps.getAdministratorUids(), mCaps.getOwnerUid())) { + if (!CollectionUtils.contains(mCaps.getAdministratorUids(), mCaps.getOwnerUid())) { throw new IllegalStateException("The owner UID must be included in " + " administrator UIDs."); } diff --git a/core/java/android/net/NetworkConfig.java b/packages/Connectivity/framework/src/android/net/NetworkConfig.java index 32a2cda00370..32a2cda00370 100644 --- a/core/java/android/net/NetworkConfig.java +++ b/packages/Connectivity/framework/src/android/net/NetworkConfig.java diff --git a/core/java/android/net/NetworkInfo.aidl b/packages/Connectivity/framework/src/android/net/NetworkInfo.aidl index f50187302966..f50187302966 100644 --- a/core/java/android/net/NetworkInfo.aidl +++ b/packages/Connectivity/framework/src/android/net/NetworkInfo.aidl diff --git a/core/java/android/net/NetworkInfo.java b/packages/Connectivity/framework/src/android/net/NetworkInfo.java index d752901e2eb0..d752901e2eb0 100644 --- a/core/java/android/net/NetworkInfo.java +++ b/packages/Connectivity/framework/src/android/net/NetworkInfo.java diff --git a/core/java/android/net/NetworkProvider.java b/packages/Connectivity/framework/src/android/net/NetworkProvider.java index 14cb51c85d06..14cb51c85d06 100644 --- a/core/java/android/net/NetworkProvider.java +++ b/packages/Connectivity/framework/src/android/net/NetworkProvider.java diff --git a/core/java/android/net/NetworkRequest.aidl b/packages/Connectivity/framework/src/android/net/NetworkRequest.aidl index 508defc6b497..508defc6b497 100644 --- a/core/java/android/net/NetworkRequest.aidl +++ b/packages/Connectivity/framework/src/android/net/NetworkRequest.aidl diff --git a/core/java/android/net/NetworkRequest.java b/packages/Connectivity/framework/src/android/net/NetworkRequest.java index c4d1b09a5c20..c4d1b09a5c20 100644 --- a/core/java/android/net/NetworkRequest.java +++ b/packages/Connectivity/framework/src/android/net/NetworkRequest.java diff --git a/core/java/android/net/NetworkUtils.java b/packages/Connectivity/framework/src/android/net/NetworkUtils.java index 8be4af7b1396..8be4af7b1396 100644 --- a/core/java/android/net/NetworkUtils.java +++ b/packages/Connectivity/framework/src/android/net/NetworkUtils.java diff --git a/core/java/android/net/PacProxySelector.java b/packages/Connectivity/framework/src/android/net/PacProxySelector.java index 326943a27d4e..326943a27d4e 100644 --- a/core/java/android/net/PacProxySelector.java +++ b/packages/Connectivity/framework/src/android/net/PacProxySelector.java diff --git a/core/java/android/net/Proxy.java b/packages/Connectivity/framework/src/android/net/Proxy.java index 03b07e080add..03b07e080add 100644 --- a/core/java/android/net/Proxy.java +++ b/packages/Connectivity/framework/src/android/net/Proxy.java diff --git a/core/java/android/net/ProxyInfo.aidl b/packages/Connectivity/framework/src/android/net/ProxyInfo.aidl index a5d0c120e747..a5d0c120e747 100644 --- a/core/java/android/net/ProxyInfo.aidl +++ b/packages/Connectivity/framework/src/android/net/ProxyInfo.aidl diff --git a/core/java/android/net/ProxyInfo.java b/packages/Connectivity/framework/src/android/net/ProxyInfo.java index 9c9fed102828..9c9fed102828 100644 --- a/core/java/android/net/ProxyInfo.java +++ b/packages/Connectivity/framework/src/android/net/ProxyInfo.java diff --git a/core/java/android/net/RouteInfo.aidl b/packages/Connectivity/framework/src/android/net/RouteInfo.aidl index 7af9fdaef342..7af9fdaef342 100644 --- a/core/java/android/net/RouteInfo.aidl +++ b/packages/Connectivity/framework/src/android/net/RouteInfo.aidl diff --git a/core/java/android/net/RouteInfo.java b/packages/Connectivity/framework/src/android/net/RouteInfo.java index 5b6684ace052..5b6684ace052 100644 --- a/core/java/android/net/RouteInfo.java +++ b/packages/Connectivity/framework/src/android/net/RouteInfo.java diff --git a/core/java/android/net/SocketKeepalive.java b/packages/Connectivity/framework/src/android/net/SocketKeepalive.java index d007a9520cb5..d007a9520cb5 100644 --- a/core/java/android/net/SocketKeepalive.java +++ b/packages/Connectivity/framework/src/android/net/SocketKeepalive.java diff --git a/core/java/android/net/StaticIpConfiguration.aidl b/packages/Connectivity/framework/src/android/net/StaticIpConfiguration.aidl index 8aac701fe7e1..8aac701fe7e1 100644 --- a/core/java/android/net/StaticIpConfiguration.aidl +++ b/packages/Connectivity/framework/src/android/net/StaticIpConfiguration.aidl diff --git a/core/java/android/net/StaticIpConfiguration.java b/packages/Connectivity/framework/src/android/net/StaticIpConfiguration.java index ce545974f5cb..ce545974f5cb 100644 --- a/core/java/android/net/StaticIpConfiguration.java +++ b/packages/Connectivity/framework/src/android/net/StaticIpConfiguration.java diff --git a/core/java/android/net/TcpKeepalivePacketData.java b/packages/Connectivity/framework/src/android/net/TcpKeepalivePacketData.java index ddb3a6a72fb4..ddb3a6a72fb4 100644 --- a/core/java/android/net/TcpKeepalivePacketData.java +++ b/packages/Connectivity/framework/src/android/net/TcpKeepalivePacketData.java diff --git a/core/java/android/net/TcpRepairWindow.java b/packages/Connectivity/framework/src/android/net/TcpRepairWindow.java index f062fa9034ea..f062fa9034ea 100644 --- a/core/java/android/net/TcpRepairWindow.java +++ b/packages/Connectivity/framework/src/android/net/TcpRepairWindow.java diff --git a/core/java/android/net/TcpSocketKeepalive.java b/packages/Connectivity/framework/src/android/net/TcpSocketKeepalive.java index d89814d49bd0..d89814d49bd0 100644 --- a/core/java/android/net/TcpSocketKeepalive.java +++ b/packages/Connectivity/framework/src/android/net/TcpSocketKeepalive.java diff --git a/core/java/android/net/TestNetworkInterface.aidl b/packages/Connectivity/framework/src/android/net/TestNetworkInterface.aidl index e1f4f9f794eb..e1f4f9f794eb 100644 --- a/core/java/android/net/TestNetworkInterface.aidl +++ b/packages/Connectivity/framework/src/android/net/TestNetworkInterface.aidl diff --git a/core/java/android/net/TestNetworkInterface.java b/packages/Connectivity/framework/src/android/net/TestNetworkInterface.java index 4449ff80180b..4449ff80180b 100644 --- a/core/java/android/net/TestNetworkInterface.java +++ b/packages/Connectivity/framework/src/android/net/TestNetworkInterface.java diff --git a/core/java/android/net/TestNetworkManager.java b/packages/Connectivity/framework/src/android/net/TestNetworkManager.java index 4e894143bf91..4e894143bf91 100644 --- a/core/java/android/net/TestNetworkManager.java +++ b/packages/Connectivity/framework/src/android/net/TestNetworkManager.java diff --git a/core/java/android/net/TransportInfo.java b/packages/Connectivity/framework/src/android/net/TransportInfo.java index aa4bbb051179..aa4bbb051179 100644 --- a/core/java/android/net/TransportInfo.java +++ b/packages/Connectivity/framework/src/android/net/TransportInfo.java diff --git a/core/java/android/net/UidRange.aidl b/packages/Connectivity/framework/src/android/net/UidRange.aidl index f70fc8e2fefd..f70fc8e2fefd 100644 --- a/core/java/android/net/UidRange.aidl +++ b/packages/Connectivity/framework/src/android/net/UidRange.aidl diff --git a/core/java/android/net/VpnManager.java b/packages/Connectivity/framework/src/android/net/VpnManager.java index c87b8279c4d6..c87b8279c4d6 100644 --- a/core/java/android/net/VpnManager.java +++ b/packages/Connectivity/framework/src/android/net/VpnManager.java diff --git a/core/java/android/net/VpnService.java b/packages/Connectivity/framework/src/android/net/VpnService.java index 8e90a119fe21..8e90a119fe21 100644 --- a/core/java/android/net/VpnService.java +++ b/packages/Connectivity/framework/src/android/net/VpnService.java diff --git a/core/java/android/net/apf/ApfCapabilities.aidl b/packages/Connectivity/framework/src/android/net/apf/ApfCapabilities.aidl index 7c4d4c2da4bc..7c4d4c2da4bc 100644 --- a/core/java/android/net/apf/ApfCapabilities.aidl +++ b/packages/Connectivity/framework/src/android/net/apf/ApfCapabilities.aidl diff --git a/core/java/android/net/apf/ApfCapabilities.java b/packages/Connectivity/framework/src/android/net/apf/ApfCapabilities.java index bf5b26e278f9..bf5b26e278f9 100644 --- a/core/java/android/net/apf/ApfCapabilities.java +++ b/packages/Connectivity/framework/src/android/net/apf/ApfCapabilities.java diff --git a/core/java/android/net/util/DnsUtils.java b/packages/Connectivity/framework/src/android/net/util/DnsUtils.java index 7908353eeda2..7908353eeda2 100644 --- a/core/java/android/net/util/DnsUtils.java +++ b/packages/Connectivity/framework/src/android/net/util/DnsUtils.java diff --git a/core/java/android/net/util/KeepaliveUtils.java b/packages/Connectivity/framework/src/android/net/util/KeepaliveUtils.java index bfc4563fbf8f..bfc4563fbf8f 100644 --- a/core/java/android/net/util/KeepaliveUtils.java +++ b/packages/Connectivity/framework/src/android/net/util/KeepaliveUtils.java diff --git a/core/java/android/net/util/MultinetworkPolicyTracker.java b/packages/Connectivity/framework/src/android/net/util/MultinetworkPolicyTracker.java index 85e3fa3048ed..85e3fa3048ed 100644 --- a/core/java/android/net/util/MultinetworkPolicyTracker.java +++ b/packages/Connectivity/framework/src/android/net/util/MultinetworkPolicyTracker.java diff --git a/core/java/android/net/util/SocketUtils.java b/packages/Connectivity/framework/src/android/net/util/SocketUtils.java index e64060f1b220..e64060f1b220 100644 --- a/core/java/android/net/util/SocketUtils.java +++ b/packages/Connectivity/framework/src/android/net/util/SocketUtils.java diff --git a/packages/Connectivity/service/Android.bp b/packages/Connectivity/service/Android.bp index c8f3bd3666e4..8fc318180778 100644 --- a/packages/Connectivity/service/Android.bp +++ b/packages/Connectivity/service/Android.bp @@ -57,6 +57,7 @@ java_library { static_libs: [ "net-utils-device-common", "net-utils-framework-common", + "netd-client", ], apex_available: [ "//apex_available:platform", diff --git a/packages/SettingsLib/MainSwitchPreference/res/drawable/thumb_off.xml b/packages/SettingsLib/MainSwitchPreference/res/drawable/thumb_off.xml index 8a73fb52de75..2be00b95af3c 100644 --- a/packages/SettingsLib/MainSwitchPreference/res/drawable/thumb_off.xml +++ b/packages/SettingsLib/MainSwitchPreference/res/drawable/thumb_off.xml @@ -15,11 +15,17 @@ limitations under the License. --> -<shape xmlns:android="http://schemas.android.com/apk/res/android" - android:shape="oval" > +<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> + <item + android:top="4dp" + android:left="4dp" + android:right="4dp" + android:bottom="4dp"> - <size android:height="24dp" android:width="24dp" /> - <solid android:color="@color/thumb_off" /> - <stroke android:width="4dp" android:color="@android:color/transparent" /> + <shape android:shape="oval" > + <size android:height="20dp" android:width="20dp" /> + <solid android:color="@color/thumb_off" /> + </shape> -</shape> + </item> +</layer-list> diff --git a/packages/SettingsLib/MainSwitchPreference/res/drawable/thumb_on.xml b/packages/SettingsLib/MainSwitchPreference/res/drawable/thumb_on.xml index 8a0af00b0d61..e85eb42007b8 100644 --- a/packages/SettingsLib/MainSwitchPreference/res/drawable/thumb_on.xml +++ b/packages/SettingsLib/MainSwitchPreference/res/drawable/thumb_on.xml @@ -15,11 +15,17 @@ limitations under the License. --> -<shape xmlns:android="http://schemas.android.com/apk/res/android" - android:shape="oval" > +<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> + <item + android:top="4dp" + android:left="4dp" + android:right="4dp" + android:bottom="4dp"> - <size android:height="24dp" android:width="24dp" /> - <solid android:color="?android:attr/colorAccent" /> - <stroke android:width="4dp" android:color="@android:color/transparent" /> + <shape android:shape="oval" > + <size android:height="20dp" android:width="20dp" /> + <solid android:color="?android:attr/colorAccent" /> + </shape> -</shape> + </item> +</layer-list> diff --git a/packages/SettingsLib/MainSwitchPreference/res/drawable/track_off.xml b/packages/SettingsLib/MainSwitchPreference/res/drawable/track_off.xml index 1be3a8eda19e..b29f4596d77c 100644 --- a/packages/SettingsLib/MainSwitchPreference/res/drawable/track_off.xml +++ b/packages/SettingsLib/MainSwitchPreference/res/drawable/track_off.xml @@ -20,7 +20,7 @@ <item android:width="13.33dp" android:height="1.67dp" - android:left="19dp" + android:left="21dp" android:gravity="center" android:drawable="@drawable/track_off_indicator" /> </layer-list> diff --git a/packages/SettingsLib/MainSwitchPreference/res/drawable/track_off_background.xml b/packages/SettingsLib/MainSwitchPreference/res/drawable/track_off_background.xml index 3cc490f9815c..c838654dd209 100644 --- a/packages/SettingsLib/MainSwitchPreference/res/drawable/track_off_background.xml +++ b/packages/SettingsLib/MainSwitchPreference/res/drawable/track_off_background.xml @@ -17,17 +17,17 @@ <vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="48dp" - android:height="24dp" - android:viewportWidth="48" - android:viewportHeight="24"> + android:width="52dp" + android:height="28dp" + android:viewportWidth="52" + android:viewportHeight="28"> <group> <clip-path - android:pathData="M12 0H36C42.6274 0 48 5.37258 48 12C48 18.6274 42.6274 24 36 24H12C5.37258 24 0 18.6274 0 12C0 5.37258 5.37258 0 12 0Z" /> + android:pathData="M14 0H38C45.732 0 52 6.26801 52 14C52 21.732 45.732 28 38 28H14C6.26801 28 0 21.732 0 14C0 6.26801 6.26801 0 14 0Z" /> <path - android:pathData="M0 0V24H48V0" + android:pathData="M0 0V28H52V0" android:fillColor="@color/track_off" /> </group> diff --git a/packages/SettingsLib/MainSwitchPreference/res/drawable/track_on.xml b/packages/SettingsLib/MainSwitchPreference/res/drawable/track_on.xml index 255389143782..cf241129f16d 100644 --- a/packages/SettingsLib/MainSwitchPreference/res/drawable/track_on.xml +++ b/packages/SettingsLib/MainSwitchPreference/res/drawable/track_on.xml @@ -21,6 +21,6 @@ android:width="13.19dp" android:height="10.06dp" android:gravity="center" - android:right="19dp" + android:right="21dp" android:drawable="@drawable/track_on_indicator" /> </layer-list> diff --git a/packages/SettingsLib/MainSwitchPreference/res/drawable/track_on_background.xml b/packages/SettingsLib/MainSwitchPreference/res/drawable/track_on_background.xml index 68ce19b6c67f..bb1a7ef9c733 100644 --- a/packages/SettingsLib/MainSwitchPreference/res/drawable/track_on_background.xml +++ b/packages/SettingsLib/MainSwitchPreference/res/drawable/track_on_background.xml @@ -17,19 +17,20 @@ <vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="48dp" - android:height="24dp" - android:viewportWidth="48" - android:viewportHeight="24" + android:width="52dp" + android:height="28dp" + android:viewportWidth="52" + android:viewportHeight="28" android:tint="@*android:color/switch_track_material"> <group> <clip-path - android:pathData="M12 0H36C42.6274 0 48 5.37258 48 12C48 18.6274 42.6274 24 36 24H12C5.37258 24 0 18.6274 0 12C0 5.37258 5.37258 0 12 0Z" /> + android:pathData="M14 0H38C45.732 0 52 6.26801 52 14C52 21.732 45.732 28 38 28H14C6.26801 28 0 21.732 0 14C0 6.26801 6.26801 0 14 0Z" /> <path - android:pathData="M0 0V24H48V0" + android:pathData="M0 0V28H52V0" android:fillColor="@*android:color/white_disabled_material" /> + </group> </vector> diff --git a/packages/SettingsLib/MainSwitchPreference/res/layout/main_switch_bar.xml b/packages/SettingsLib/MainSwitchPreference/res/layout/main_switch_bar.xml index 7e3ce9d3595c..52779bcabf00 100644 --- a/packages/SettingsLib/MainSwitchPreference/res/layout/main_switch_bar.xml +++ b/packages/SettingsLib/MainSwitchPreference/res/layout/main_switch_bar.xml @@ -26,7 +26,7 @@ android:minHeight="@dimen/min_switch_bar_height" android:layout_height="wrap_content" android:layout_width="match_parent" - android:background="?android:attr/colorBackground" + android:background="?android:attr/selectableItemBackground" android:paddingLeft="@dimen/switchbar_margin_start" android:paddingRight="@dimen/switchbar_margin_end"> @@ -35,7 +35,7 @@ android:layout_height="wrap_content" android:layout_width="0dp" android:layout_weight="1" - android:paddingRight="54dp" + android:layout_marginRight="16dp" android:layout_gravity="center_vertical" android:maxLines="2" android:ellipsize="end" diff --git a/packages/SettingsLib/MainSwitchPreference/res/values-night/colors.xml b/packages/SettingsLib/MainSwitchPreference/res/values-night/colors.xml index 9dc0af3b5643..147db773fd05 100644 --- a/packages/SettingsLib/MainSwitchPreference/res/values-night/colors.xml +++ b/packages/SettingsLib/MainSwitchPreference/res/values-night/colors.xml @@ -17,7 +17,6 @@ <resources> - <color name="title_text_color">@*android:color/primary_text_dark</color> <color name="thumb_off">#BFFFFFFF</color> <color name="track_off">@*android:color/material_grey_600</color> diff --git a/packages/SettingsLib/MainSwitchPreference/res/values/colors.xml b/packages/SettingsLib/MainSwitchPreference/res/values/colors.xml index 8194bddc99b4..147db773fd05 100644 --- a/packages/SettingsLib/MainSwitchPreference/res/values/colors.xml +++ b/packages/SettingsLib/MainSwitchPreference/res/values/colors.xml @@ -17,7 +17,6 @@ <resources> - <color name="title_text_color">@*android:color/primary_text_light</color> <color name="thumb_off">#BFFFFFFF</color> <color name="track_off">@*android:color/material_grey_600</color> diff --git a/packages/SettingsLib/MainSwitchPreference/res/values/dimens.xml b/packages/SettingsLib/MainSwitchPreference/res/values/dimens.xml index dd443deeb869..b145c9bc4b39 100644 --- a/packages/SettingsLib/MainSwitchPreference/res/values/dimens.xml +++ b/packages/SettingsLib/MainSwitchPreference/res/values/dimens.xml @@ -18,13 +18,13 @@ <resources> <!-- Size of layout margin left --> - <dimen name="switchbar_margin_start">26dp</dimen> + <dimen name="switchbar_margin_start">22dp</dimen> <!-- Size of layout margin right --> - <dimen name="switchbar_margin_end">24dp</dimen> + <dimen name="switchbar_margin_end">16dp</dimen> <!-- Minimum width of switch --> - <dimen name="min_switch_width">48dp</dimen> + <dimen name="min_switch_width">52dp</dimen> <!-- Minimum width of switch bar --> <dimen name="min_switch_bar_height">72dp</dimen> diff --git a/packages/SettingsLib/MainSwitchPreference/res/values/styles.xml b/packages/SettingsLib/MainSwitchPreference/res/values/styles.xml index fbb896c76295..59b5899a4173 100644 --- a/packages/SettingsLib/MainSwitchPreference/res/values/styles.xml +++ b/packages/SettingsLib/MainSwitchPreference/res/values/styles.xml @@ -19,7 +19,6 @@ <style name="MainSwitchText"> <item name="android:textSize">20sp</item> - <item name="android:textColor">@color/title_text_color</item> </style> <style name="Settings.MainSwitch" parent="@android:style/Widget.Material.CompoundButton.Switch"> diff --git a/packages/SettingsLib/MainSwitchPreference/src/com/android/settingslib/widget/MainSwitchBar.java b/packages/SettingsLib/MainSwitchPreference/src/com/android/settingslib/widget/MainSwitchBar.java index 532c996824d4..74b65780ffc2 100644 --- a/packages/SettingsLib/MainSwitchPreference/src/com/android/settingslib/widget/MainSwitchBar.java +++ b/packages/SettingsLib/MainSwitchPreference/src/com/android/settingslib/widget/MainSwitchBar.java @@ -136,10 +136,8 @@ public class MainSwitchBar extends LinearLayout implements CompoundButton.OnChec * Show the MainSwitchBar */ public void show() { - if (!isShowing()) { - setVisibility(View.VISIBLE); - mSwitch.setOnCheckedChangeListener(this); - } + setVisibility(View.VISIBLE); + mSwitch.setOnCheckedChangeListener(this); } /** diff --git a/packages/SettingsLib/MainSwitchPreference/src/com/android/settingslib/widget/MainSwitchPreference.java b/packages/SettingsLib/MainSwitchPreference/src/com/android/settingslib/widget/MainSwitchPreference.java index dae0e705794d..274bf8df2222 100644 --- a/packages/SettingsLib/MainSwitchPreference/src/com/android/settingslib/widget/MainSwitchPreference.java +++ b/packages/SettingsLib/MainSwitchPreference/src/com/android/settingslib/widget/MainSwitchPreference.java @@ -17,9 +17,11 @@ package com.android.settingslib.widget; import android.content.Context; +import android.content.res.TypedArray; +import android.text.TextUtils; import android.util.AttributeSet; -import android.widget.Switch; +import androidx.core.content.res.TypedArrayUtils; import androidx.preference.PreferenceViewHolder; import androidx.preference.TwoStatePreference; @@ -38,30 +40,29 @@ public class MainSwitchPreference extends TwoStatePreference { private final List<OnMainSwitchChangeListener> mSwitchChangeListeners = new ArrayList<>(); private MainSwitchBar mMainSwitchBar; - private Switch mSwitch; private String mTitle; private RestrictedLockUtils.EnforcedAdmin mEnforcedAdmin; public MainSwitchPreference(Context context) { super(context); - init(); + init(context, null); } public MainSwitchPreference(Context context, AttributeSet attrs) { super(context, attrs); - init(); + init(context, attrs); } public MainSwitchPreference(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); - init(); + init(context, attrs); } public MainSwitchPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); - init(); + init(context, attrs); } @Override @@ -76,8 +77,21 @@ public class MainSwitchPreference extends TwoStatePreference { registerListenerToSwitchBar(); } - private void init() { + private void init(Context context, AttributeSet attrs) { setLayoutResource(R.layout.main_switch_layout); + + if (attrs != null) { + TypedArray a = context.obtainStyledAttributes(attrs, + androidx.preference.R.styleable.Preference, 0 /*defStyleAttr*/, + 0 /*defStyleRes*/); + final CharSequence title = TypedArrayUtils.getText(a, + androidx.preference.R.styleable.Preference_title, + androidx.preference.R.styleable.Preference_android_title); + if (!TextUtils.isEmpty(title)) { + setTitle(title.toString()); + } + a.recycle(); + } } /** diff --git a/packages/SettingsLib/UsageProgressBarPreference/Android.bp b/packages/SettingsLib/UsageProgressBarPreference/Android.bp index f346a5962d1c..3331550d0535 100644 --- a/packages/SettingsLib/UsageProgressBarPreference/Android.bp +++ b/packages/SettingsLib/UsageProgressBarPreference/Android.bp @@ -6,6 +6,7 @@ android_library { static_libs: [ "androidx.preference_preference", + "androidx-constraintlayout_constraintlayout", ], sdk_version: "system_current", diff --git a/packages/SettingsLib/UsageProgressBarPreference/res/layout/preference_usage_progress_bar.xml b/packages/SettingsLib/UsageProgressBarPreference/res/layout/preference_usage_progress_bar.xml index 9dbd5fa4b2d2..f45105dc3311 100644 --- a/packages/SettingsLib/UsageProgressBarPreference/res/layout/preference_usage_progress_bar.xml +++ b/packages/SettingsLib/UsageProgressBarPreference/res/layout/preference_usage_progress_bar.xml @@ -17,6 +17,7 @@ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_vertical" @@ -26,29 +27,40 @@ android:paddingTop="32dp" android:paddingBottom="32dp"> - <RelativeLayout + <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/usage_summary" - android:layout_width="wrap_content" + android:layout_width="0dp" android:layout_height="wrap_content" - android:layout_alignParentStart="true" - android:layout_alignBaseline="@id/total_summary" - android:singleLine="true" + app:layout_constraintWidth_percent="0.45" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintBaseline_toBaselineOf="@id/total_summary" android:ellipsize="marquee" android:fontFamily="@*android:string/config_headlineFontFamily" android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Display1" - android:textSize="20sp"/> + android:textSize="14sp" + android:textAlignment="viewStart"/> <TextView android:id="@+id/total_summary" - android:layout_width="wrap_content" + android:layout_width="0dp" android:layout_height="wrap_content" - android:layout_alignParentEnd="true" - android:singleLine="true" + app:layout_constraintWidth_percent="0.45" + app:layout_constraintEnd_toStartOf="@id/custom_content" android:ellipsize="marquee" - android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Body1"/> - </RelativeLayout> + android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Body1" + android:textSize="14sp" + android:textAlignment="viewEnd"/> + <FrameLayout + android:id="@+id/custom_content" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:visibility="gone" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintBottom_toBottomOf="@id/total_summary" + app:layout_constraintWidth_percent="0.1"/> + </androidx.constraintlayout.widget.ConstraintLayout> <ProgressBar android:id="@android:id/progress" diff --git a/packages/SettingsLib/UsageProgressBarPreference/src/com/android/settingslib/widget/UsageProgressBarPreference.java b/packages/SettingsLib/UsageProgressBarPreference/src/com/android/settingslib/widget/UsageProgressBarPreference.java index 950a8b4ad7cc..af64a1dc2282 100644 --- a/packages/SettingsLib/UsageProgressBarPreference/src/com/android/settingslib/widget/UsageProgressBarPreference.java +++ b/packages/SettingsLib/UsageProgressBarPreference/src/com/android/settingslib/widget/UsageProgressBarPreference.java @@ -22,6 +22,9 @@ import android.text.Spanned; import android.text.TextUtils; import android.text.style.RelativeSizeSpan; import android.util.AttributeSet; +import android.view.View; +import android.widget.FrameLayout; +import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.TextView; @@ -41,6 +44,7 @@ public class UsageProgressBarPreference extends Preference { private CharSequence mUsageSummary; private CharSequence mTotalSummary; + private ImageView mCustomImageView; private int mPercent = -1; /** @@ -110,6 +114,15 @@ public class UsageProgressBarPreference extends Preference { notifyChanged(); } + /** Set custom ImageView to the right side of total summary. */ + public <T extends ImageView> void setCustomContent(T imageView) { + if (imageView == mCustomImageView) { + return; + } + mCustomImageView = imageView; + notifyChanged(); + } + /** * Binds the created View to the data for this preference. * @@ -141,6 +154,15 @@ public class UsageProgressBarPreference extends Preference { progressBar.setIndeterminate(false); progressBar.setProgress(mPercent); } + + final FrameLayout customLayout = (FrameLayout) holder.findViewById(R.id.custom_content); + if (mCustomImageView == null) { + customLayout.removeAllViews(); + customLayout.setVisibility(View.GONE); + } else { + customLayout.addView(mCustomImageView); + customLayout.setVisibility(View.VISIBLE); + } } private CharSequence enlargeFontOfNumber(CharSequence summary) { diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java index 5580afe70faf..78282fb14f5f 100644 --- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java +++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java @@ -19,6 +19,7 @@ import android.content.Context; import android.content.Intent; import android.net.ConnectivityManager; import android.net.ConnectivityManager.NetworkCallback; +import android.net.LinkProperties; import android.net.Network; import android.net.NetworkCapabilities; import android.net.NetworkInfo; @@ -38,7 +39,9 @@ import android.util.FeatureFlagUtils; import com.android.settingslib.R; import com.android.settingslib.Utils; +import java.util.HashSet; import java.util.List; +import java.util.Set; /** * Track status of Wi-Fi for the Sys UI. @@ -50,6 +53,7 @@ public class WifiStatusTracker { private final NetworkScoreManager mNetworkScoreManager; private final ConnectivityManager mConnectivityManager; private final Handler mHandler = new Handler(Looper.getMainLooper()); + private final Set<Integer> mNetworks = new HashSet<>(); private final WifiNetworkScoreCache.CacheListener mCacheListener = new WifiNetworkScoreCache.CacheListener(mHandler) { @Override @@ -64,6 +68,20 @@ public class WifiStatusTracker { .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR).build(); private final NetworkCallback mNetworkCallback = new NetworkCallback() { + @Override + public void onAvailable( + Network network, NetworkCapabilities networkCapabilities, + LinkProperties linkProperties, boolean blocked) { + boolean isVcnOverWifi = + networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) + && (Utils.tryGetWifiInfoForVcn(networkCapabilities) != null); + boolean isWifi = + networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI); + if (isVcnOverWifi || isWifi) { + mNetworks.add(network.getNetId()); + } + } + // Note: onCapabilitiesChanged is guaranteed to be called "immediately" after onAvailable // and onLinkPropertiesChanged. @Override @@ -84,9 +102,12 @@ public class WifiStatusTracker { @Override public void onLost(Network network) { - updateWifiInfo(null); - updateStatusLabel(); - mCallback.run(); + if (mNetworks.contains(network.getNetId())) { + mNetworks.remove(network.getNetId()); + updateWifiInfo(null); + updateStatusLabel(); + mCallback.run(); + } } }; private final NetworkCallback mDefaultNetworkCallback = new NetworkCallback() { diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/widget/UsageProgressBarPreferenceTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/widget/UsageProgressBarPreferenceTest.java index 85e2174bf87a..1a8477d9b86e 100644 --- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/widget/UsageProgressBarPreferenceTest.java +++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/widget/UsageProgressBarPreferenceTest.java @@ -18,11 +18,15 @@ package com.android.settingslib.widget; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.mock; + import android.content.Context; import android.text.SpannedString; import android.text.style.RelativeSizeSpan; import android.view.LayoutInflater; import android.view.View; +import android.widget.FrameLayout; +import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ProgressBar; import android.widget.TextView; @@ -97,4 +101,30 @@ public class UsageProgressBarPreferenceTest { .findViewById(android.R.id.progress); assertThat(progressBar.getProgress()).isEqualTo((int) (31.0f / 80 * 100)); } + + @Test + public void setCustomContent_setNullImageView_noChild() { + mUsageProgressBarPreference.setCustomContent(null /* imageView */); + + mUsageProgressBarPreference.onBindViewHolder(mViewHolder); + + final FrameLayout customContent = + (FrameLayout) mViewHolder.findViewById(R.id.custom_content); + assertThat(customContent.getChildCount()).isEqualTo(0); + assertThat(customContent.getVisibility()).isEqualTo(View.GONE); + } + + @Test + public void setCustomContent_setImageView_oneChild() { + final ImageView imageView = mock(ImageView.class); + mUsageProgressBarPreference.setCustomContent(imageView); + + mUsageProgressBarPreference.onBindViewHolder(mViewHolder); + + final FrameLayout customContent = + (FrameLayout) mViewHolder.findViewById(R.id.custom_content); + assertThat(customContent.getChildCount()).isEqualTo(1); + assertThat(customContent.getChildAt(0)).isEqualTo(imageView); + assertThat(customContent.getVisibility()).isEqualTo(View.VISIBLE); + } } diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java index efd941e3bd18..438cec8ef68f 100644 --- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java +++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java @@ -272,6 +272,7 @@ public class SettingsBackupTest { Settings.Global.SMART_REPLIES_IN_NOTIFICATIONS_FLAGS, Settings.Global.SMART_SUGGESTIONS_IN_NOTIFICATIONS_FLAGS, Settings.Global.ENABLE_ADB_INCREMENTAL_INSTALL_DEFAULT, + Settings.Global.ENABLE_MULTI_SLOT_TIMEOUT_MILLIS, Settings.Global.ENHANCED_4G_MODE_ENABLED, Settings.Global.EPHEMERAL_COOKIE_MAX_SIZE_BYTES, Settings.Global.ERROR_LOGCAT_PREFIX, @@ -280,6 +281,7 @@ public class SettingsBackupTest { Settings.Global.EUICC_UNSUPPORTED_COUNTRIES, Settings.Global.EUICC_FACTORY_RESET_TIMEOUT_MILLIS, Settings.Global.EUICC_REMOVING_INVISIBLE_PROFILES_TIMEOUT_MILLIS, + Settings.Global.EUICC_SWITCH_SLOT_TIMEOUT_MILLIS, Settings.Global.FANCY_IME_ANIMATIONS, Settings.Global.FORCE_ALLOW_ON_EXTERNAL, Settings.Global.FORCED_APP_STANDBY_ENABLED, diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml index 80c8a285bfc6..35a2195accab 100644 --- a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml +++ b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml @@ -76,7 +76,7 @@ android:textSize="100dp" android:includeFontPadding="false" android:fontFamily="@font/clock" - android:lineSpacingMultiplier=".65" + android:lineSpacingMultiplier=".7" android:typeface="monospace" android:elegantTextHeight="false" dozeWeight="200" @@ -97,7 +97,7 @@ android:gravity="center_horizontal" android:textSize="@dimen/large_clock_text_size" android:includeFontPadding="false" - android:lineSpacingMultiplier=".65" + android:lineSpacingMultiplier=".7" android:fontFamily="@font/clock" android:typeface="monospace" android:elegantTextHeight="false" diff --git a/packages/SystemUI/res/drawable/privacy_item_circle_camera.xml b/packages/SystemUI/res/drawable/privacy_item_circle_camera.xml index cf6413642c63..5cb6f4626b36 100644 --- a/packages/SystemUI/res/drawable/privacy_item_circle_camera.xml +++ b/packages/SystemUI/res/drawable/privacy_item_circle_camera.xml @@ -21,16 +21,16 @@ > <shape android:shape="oval"> <size - android:height="28dp" - android:width="28dp" + android:height="@dimen/ongoing_appops_dialog_circle_size" + android:width="@dimen/ongoing_appops_dialog_circle_size" /> <solid android:color="@color/privacy_circle_camera" /> </shape> </item> <item android:id="@id/icon" android:gravity="center" - android:width="20dp" - android:height="20dp" + android:width="@dimen/ongoing_appops_dialog_icon_size" + android:height="@dimen/ongoing_appops_dialog_icon_size" android:drawable="@*android:drawable/perm_group_camera" /> </layer-list>
\ No newline at end of file diff --git a/packages/SystemUI/res/drawable/privacy_item_circle_location.xml b/packages/SystemUI/res/drawable/privacy_item_circle_location.xml index 0a6a4a31d0a5..28466c8a29b3 100644 --- a/packages/SystemUI/res/drawable/privacy_item_circle_location.xml +++ b/packages/SystemUI/res/drawable/privacy_item_circle_location.xml @@ -21,16 +21,16 @@ > <shape android:shape="oval"> <size - android:height="28dp" - android:width="28dp" + android:height="@dimen/ongoing_appops_dialog_circle_size" + android:width="@dimen/ongoing_appops_dialog_circle_size" /> <solid android:color="@color/privacy_circle_microphone_location" /> </shape> </item> <item android:id="@id/icon" android:gravity="center" - android:width="20dp" - android:height="20dp" + android:width="@dimen/ongoing_appops_dialog_icon_size" + android:height="@dimen/ongoing_appops_dialog_icon_size" android:drawable="@*android:drawable/perm_group_microphone" /> </layer-list>
\ No newline at end of file diff --git a/packages/SystemUI/res/drawable/privacy_item_circle_microphone.xml b/packages/SystemUI/res/drawable/privacy_item_circle_microphone.xml index 0a6a4a31d0a5..28466c8a29b3 100644 --- a/packages/SystemUI/res/drawable/privacy_item_circle_microphone.xml +++ b/packages/SystemUI/res/drawable/privacy_item_circle_microphone.xml @@ -21,16 +21,16 @@ > <shape android:shape="oval"> <size - android:height="28dp" - android:width="28dp" + android:height="@dimen/ongoing_appops_dialog_circle_size" + android:width="@dimen/ongoing_appops_dialog_circle_size" /> <solid android:color="@color/privacy_circle_microphone_location" /> </shape> </item> <item android:id="@id/icon" android:gravity="center" - android:width="20dp" - android:height="20dp" + android:width="@dimen/ongoing_appops_dialog_icon_size" + android:height="@dimen/ongoing_appops_dialog_icon_size" android:drawable="@*android:drawable/perm_group_microphone" /> </layer-list>
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/privacy_dialog.xml b/packages/SystemUI/res/layout/privacy_dialog.xml index 5db247e25d50..4d77a0d75689 100644 --- a/packages/SystemUI/res/layout/privacy_dialog.xml +++ b/packages/SystemUI/res/layout/privacy_dialog.xml @@ -22,7 +22,13 @@ android:layout_height="wrap_content" android:layout_marginStart="@dimen/ongoing_appops_dialog_side_margins" android:layout_marginEnd="@dimen/ongoing_appops_dialog_side_margins" + android:layout_marginTop="8dp" android:orientation="vertical" - android:padding = "8dp" + android:paddingLeft="@dimen/ongoing_appops_dialog_side_padding" + android:paddingRight="@dimen/ongoing_appops_dialog_side_padding" + android:paddingBottom="12dp" + android:paddingTop="8dp" android:background="@drawable/privacy_dialog_bg" -/>
\ No newline at end of file +/> +<!-- 12dp padding bottom so there's 20dp total under the icon --> +<!-- 8dp padding top, as there's 4dp margin in each row -->
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/privacy_dialog_item.xml b/packages/SystemUI/res/layout/privacy_dialog_item.xml index 882e9680407e..91ffe225fac6 100644 --- a/packages/SystemUI/res/layout/privacy_dialog_item.xml +++ b/packages/SystemUI/res/layout/privacy_dialog_item.xml @@ -16,19 +16,22 @@ --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/privacy_item" android:layout_width="match_parent" android:layout_height="wrap_content" android:minHeight="48dp" android:orientation="horizontal" - android:layout_marginTop="8dp" + android:layout_marginTop="4dp" + android:importantForAccessibility="yes" + android:focusable="true" > + <!-- 4dp marginTop makes 20dp minimum between icons --> <ImageView android:id="@+id/icon" - android:layout_width="24dp" - android:layout_height="24dp" + android:layout_width="@dimen/ongoing_appops_dialog_circle_size" + android:layout_height="@dimen/ongoing_appops_dialog_circle_size" android:layout_gravity="center_vertical" - android:layout_marginStart="12dp" - android:layout_marginEnd="12dp" + android:importantForAccessibility="no" /> <TextView @@ -38,25 +41,21 @@ android:layout_width="0dp" android:layout_weight="1" android:layout_gravity="center_vertical" + android:layout_marginStart="16dp" + android:layout_marginEnd="16dp" + android:textDirection="locale" + android:textAlignment="viewStart" android:gravity="start | center_vertical" - android:textAppearance="@style/TextAppearance.QS.TileLabel" + android:textAppearance="@style/TextAppearance.PrivacyDialog" + android:lineHeight="20sp" /> - <FrameLayout - android:id="@+id/link" - android:layout_width="48dp" - android:layout_height="48dp" + <ImageView + android:layout_height="24dp" + android:layout_width="24dp" android:layout_gravity="center_vertical" - android:background="?android:attr/selectableItemBackground" - > - - <ImageView - android:layout_height="24dp" - android:layout_width="24dp" - android:layout_gravity="center" - android:src="@*android:drawable/ic_chevron_end" - android:tint="?android:attr/textColorPrimary" - /> - </FrameLayout> + android:src="@*android:drawable/ic_chevron_end" + android:tint="?android:attr/textColorPrimary" + /> </LinearLayout>
\ No newline at end of file diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml index 6dcb50240262..5db7c25835c8 100644 --- a/packages/SystemUI/res/values-af/strings.xml +++ b/packages/SystemUI/res/values-af/strings.xml @@ -416,10 +416,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Skermopname"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Begin"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Stop"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"Om voort te gaan, moet <b><xliff:g id="APP">%s</xliff:g></b> toegang tot jou toestel se mikrofoon hê."</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"Om voort te gaan, moet <b><xliff:g id="APP">%s</xliff:g></b> toegang tot jou toestel se kamera hê."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"Toestel"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Swiep op om programme te wissel"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Sleep regs om programme vinnig te wissel"</string> @@ -442,8 +440,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"Tik weer om oop te maak"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"Swiep op om oop te maak"</string> <string name="keyguard_retry" msgid="886802522584053523">"Swiep op om weer te probeer"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Ontsluit om NFC te gebruik"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Hierdie toestel behoort aan jou organisasie"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Hierdie toestel behoort aan <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> <string name="phone_hint" msgid="6682125338461375925">"Swiep vanaf ikoon vir foon"</string> @@ -970,6 +967,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Programme gebruik tans jou <xliff:g id="TYPES_LIST">%s</xliff:g>."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" en "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> gebruik tans die <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> het onlangs die <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> gebruik"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(onderneming)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Oproep"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(deur <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"kamera"</string> <string name="privacy_type_location" msgid="7991481648444066703">"ligging"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofoon"</string> diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml index d1954a6f6179..1af18fee0fb9 100644 --- a/packages/SystemUI/res/values-am/strings.xml +++ b/packages/SystemUI/res/values-am/strings.xml @@ -967,6 +967,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"መተግበሪያዎች የእርስዎን <xliff:g id="TYPES_LIST">%s</xliff:g> እየተጠቀሙ ነው።"</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">"፣ "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" እና "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>ን እየተጠቀመ ነው"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> በቅርብ ጊዜ <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>ን ይጠቀማል።"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(ድርጅት)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"የስልክ ጥሪ"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(እስከ <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"ካሜራ"</string> <string name="privacy_type_location" msgid="7991481648444066703">"አካባቢ"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"ማይክሮፎን"</string> diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml index f2652d3c66c2..b34b39a765b1 100644 --- a/packages/SystemUI/res/values-ar/strings.xml +++ b/packages/SystemUI/res/values-ar/strings.xml @@ -424,10 +424,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"تسجيل الشاشة"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"بدء"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"إيقاف"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"للمتابعة، يحتاج تطبيق <b><xliff:g id="APP">%s</xliff:g></b> إلى الوصول إلى ميكروفون الجهاز."</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"للمتابعة، يحتاج تطبيق <b><xliff:g id="APP">%s</xliff:g></b> إلى الوصول إلى كاميرا الجهاز."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"الجهاز"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"مرّر سريعًا لأعلى لتبديل التطبيقات"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"اسحب لليسار للتبديل السريع بين التطبيقات"</string> @@ -450,8 +448,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"انقر مرة أخرى للفتح"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"يمكنك الفتح بالتمرير سريعًا لأعلى."</string> <string name="keyguard_retry" msgid="886802522584053523">"مرِّر سريعًا للأعلى لإعادة المحاولة."</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"يجب فتح قفل الشاشة لاستخدام تقنية الاتصال قصير المدى (NFC)."</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"هذا الجهاز يخص مؤسستك."</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"هذا الجهاز يخص <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>."</string> <string name="phone_hint" msgid="6682125338461375925">"يمكنك التمرير سريعًا من الرمز لتشغيل الهاتف"</string> @@ -990,6 +987,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"تستخدم التطبيقات <xliff:g id="TYPES_LIST">%s</xliff:g>."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">"، "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" و "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"يستخدم تطبيق <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> عملية <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> الآن."</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"استخدَم تطبيق <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> عملية <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> مؤخرًا."</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(للمؤسسات)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"مكالمة هاتفية"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(من خلال <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"الكاميرا"</string> <string name="privacy_type_location" msgid="7991481648444066703">"الموقع"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"الميكروفون"</string> diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml index 8abb5edc233e..88b2bb278995 100644 --- a/packages/SystemUI/res/values-as/strings.xml +++ b/packages/SystemUI/res/values-as/strings.xml @@ -967,6 +967,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"এপ্লিকেশ্বনসমূহে আপোনাৰ <xliff:g id="TYPES_LIST">%s</xliff:g> ব্যৱহাৰ কৰি আছে।"</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" আৰু "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g>এ <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> ব্যৱহাৰ কৰি আছে"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g>এ শেহতীয়াকৈ <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> ব্যৱহাৰ কৰিছে"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(এণ্টাৰপ্ৰাইজ)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Phonecall"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(<xliff:g id="ATTRIBUTION">%s</xliff:g>ৰ জৰিয়তে)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"কেমেৰা"</string> <string name="privacy_type_location" msgid="7991481648444066703">"অৱস্থান"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"মাইক্ৰ\'ফ\'ন"</string> diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml index 352282c3b8f8..6f1c347a5987 100644 --- a/packages/SystemUI/res/values-az/strings.xml +++ b/packages/SystemUI/res/values-az/strings.xml @@ -416,10 +416,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Ekran yazması"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Başlayın"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Dayandırın"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"Davam etmək üçün <b><xliff:g id="APP">%s</xliff:g></b> tətbiqi cihazın mikrofonuna giriş tələb edir."</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"Davam etmək üçün <b><xliff:g id="APP">%s</xliff:g></b> tətbiqi cihazın kamerasına giriş tələb edir."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"Cihaz"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Tətbiqi dəyişmək üçün yuxarı sürüşdürün"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Tətbiqləri cəld dəyişmək üçün sağa çəkin"</string> @@ -442,8 +440,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"Açmaq üçün yenidən tıklayın"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"Açmaq üçün yuxarı sürüşdürün"</string> <string name="keyguard_retry" msgid="886802522584053523">"Yenidən cəhd etmək üçün yuxarı sürüşdürün"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC istifadə etmək üçün kiliddən çıxarın"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Bu cihaz təşkilatınıza məxsusdur"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Bu cihaz <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> təşkilatına məxsusdur"</string> <string name="phone_hint" msgid="6682125338461375925">"Telefon üçün ikonadan sürüşdürün"</string> @@ -970,6 +967,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Tətbiqlər <xliff:g id="TYPES_LIST">%s</xliff:g> istifadə edir."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" və "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> istifadə edir"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> bu yaxınlarda <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> istifadə edib"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(korporativ)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Telefon zəngi"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(<xliff:g id="ATTRIBUTION">%s</xliff:g> vasitəsilə)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"kamera"</string> <string name="privacy_type_location" msgid="7991481648444066703">"məkan"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofon"</string> diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml index ba131c49329e..2185a66477a0 100644 --- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml +++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml @@ -418,10 +418,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Snimak ekrana"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Počnite"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Zaustavite"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"<b><xliff:g id="APP">%s</xliff:g></b> zahteva pristup mikrofonu uređaja radi nastavljanja."</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"<b><xliff:g id="APP">%s</xliff:g></b> zahteva pristup kameri uređaja radi nastavljanja."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"Uređaj"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Prevucite nagore da biste menjali aplikacije"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Prevucite udesno da biste brzo promenili aplikacije"</string> @@ -444,8 +442,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"Dodirnite ponovo da biste otvorili"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"Prevucite nagore da biste otvorili"</string> <string name="keyguard_retry" msgid="886802522584053523">"Prevucite nagore da biste probali ponovo"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Otključajte da biste koristili NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Ovaj uređaj pripada organizaciji"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Ovaj uređaj pripada organizaciji <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> <string name="phone_hint" msgid="6682125338461375925">"Prevucite od ikone za telefon"</string> @@ -975,6 +972,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Aplikacije koriste <xliff:g id="TYPES_LIST">%s</xliff:g>."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" i "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"Aplikacija <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> koristi: <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"Aplikacija <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> je nedavno koristila: <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(za preduzeća)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Telefonski poziv"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(preko: <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"kameru"</string> <string name="privacy_type_location" msgid="7991481648444066703">"lokaciju"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofon"</string> diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml index 61f71885c501..e5356ae6486c 100644 --- a/packages/SystemUI/res/values-be/strings.xml +++ b/packages/SystemUI/res/values-be/strings.xml @@ -420,10 +420,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Запіс экрана"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Пачаць"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Спыніць"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"Каб працягнуць, дайце праграме <b><xliff:g id="APP">%s</xliff:g></b> доступ да мікрафона прылады."</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"Каб працягнуць, дайце праграме <b><xliff:g id="APP">%s</xliff:g></b> доступ да камеры прылады."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"Прылада"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Правядзіце ўверх, каб пераключыць праграмы"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Каб хутка пераключыцца паміж праграмамі, перацягніце ўправа"</string> @@ -446,8 +444,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"Дакраніцеся яшчэ раз, каб адкрыць"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"Каб адкрыць, прагарніце ўверх"</string> <string name="keyguard_retry" msgid="886802522584053523">"Прагартайце ўверх, каб паўтарыць спробу"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Разблакіруйце, каб выкарыстоўваць NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Гэта прылада належыць вашай арганізацыі"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Гэта прылада належыць арганізацыі \"<xliff:g id="ORGANIZATION_NAME">%s</xliff:g>\""</string> <string name="phone_hint" msgid="6682125338461375925">"Тэлефон: правядзіце пальцам ад значка"</string> @@ -980,6 +977,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Праграмы выкарыстоўваюць: <xliff:g id="TYPES_LIST">%s</xliff:g>."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" і "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"Праграма \"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g>\" выкарыстоўвае праграму \"<xliff:g id="APP_OPP_NAME">%2$s</xliff:g>\""</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"Праграма \"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g>\" нядаўна выкарыстоўвала праграму \"<xliff:g id="APP_OPP_NAME">%2$s</xliff:g>\""</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(прадпрыемства)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Тэлефонны выклік"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(праз праграму \"<xliff:g id="ATTRIBUTION">%s</xliff:g>\")"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"камера"</string> <string name="privacy_type_location" msgid="7991481648444066703">"геалакацыя"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"мікрафон"</string> diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml index d6ba258cd1a9..adf852b5495b 100644 --- a/packages/SystemUI/res/values-bg/strings.xml +++ b/packages/SystemUI/res/values-bg/strings.xml @@ -416,10 +416,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Записване на екрана"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Старт"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Стоп"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"За да продължите, <b><xliff:g id="APP">%s</xliff:g></b> се нуждае от достъп до микрофона на устройството ви."</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"За да продължите, <b><xliff:g id="APP">%s</xliff:g></b> се нуждае от достъп до камерата на устройството ви."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"Устройство"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Прекарайте пръст нагоре, за да превключите между приложенията"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Плъзнете надясно за бързо превключване между приложенията"</string> @@ -442,8 +440,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"Докоснете отново, за да отворите"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"Прекарайте пръст нагоре, за да отключите"</string> <string name="keyguard_retry" msgid="886802522584053523">"Плъзнете бързо нагоре, за да опитате отново"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Отключете, за да използвате NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Това устройство принадлежи на организацията ви"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Това устройство принадлежи на <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> <string name="phone_hint" msgid="6682125338461375925">"Плъзнете с пръст от иконата, за да използвате телефона"</string> @@ -970,6 +967,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Някои приложения използват <xliff:g id="TYPES_LIST">%s</xliff:g>."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" и "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> използва <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> наскоро използва <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(корпоративна версия)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Телефонно обаждане"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(чрез <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"камерата"</string> <string name="privacy_type_location" msgid="7991481648444066703">"местополож."</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"микрофона"</string> diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml index 14c77796738c..437abb85b445 100644 --- a/packages/SystemUI/res/values-bn/strings.xml +++ b/packages/SystemUI/res/values-bn/strings.xml @@ -416,10 +416,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"স্ক্রিন রেকর্ড"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"শুরু করুন"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"বন্ধ করুন"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"চালিয়ে যেতে, <b><xliff:g id="APP">%s</xliff:g></b> আপনার ডিভাইসের মাইক্রোফোন অ্যাক্সেস করতে চায়।"</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"চালিয়ে যেতে, <b><xliff:g id="APP">%s</xliff:g></b> আপনার ডিভাইসের ক্যামেরা অ্যাক্সেস করতে চায়।"</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"ডিভাইস"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"অন্য অ্যাপে যেতে উপরের দিকে সোয়াইপ করুন"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"একটি অ্যাপ ছেড়ে দ্রুত অন্য অ্যাপে যেতে ডান দিকে টেনে আনুন"</string> @@ -442,8 +440,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"খোলার জন্য আবার আলতো চাপুন"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"খোলার জন্য উপরে সোয়াইপ করুন"</string> <string name="keyguard_retry" msgid="886802522584053523">"আবার চেষ্টা করতে উপরের দিকে সোয়াইপ করুন"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC ব্যবহার করতে আনলক করুন"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"এই ডিভাইসটি আপনার প্রতিষ্ঠানের"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"এই ডিভাইসটি <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>-এর"</string> <string name="phone_hint" msgid="6682125338461375925">"ফোনের জন্য আইকন থেকে সোয়াইপ করুন"</string> @@ -970,6 +967,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"অ্যাপ্লিকেশনগুলি আপনার <xliff:g id="TYPES_LIST">%s</xliff:g> ব্যবহার করছে।"</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" এবং "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> এখন <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> ব্যবহার করছে"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> সম্প্রতি <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> ব্যবহার করেছে"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"এন্টারপ্রাইজ"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"ফোনকল"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(<xliff:g id="ATTRIBUTION">%s</xliff:g>-এর মাধ্যমে)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"ক্যামেরা"</string> <string name="privacy_type_location" msgid="7991481648444066703">"লোকেশন"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"মাইক্রোফোন"</string> diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml index d2f0c0d9aaac..f2b3edca02de 100644 --- a/packages/SystemUI/res/values-bs/strings.xml +++ b/packages/SystemUI/res/values-bs/strings.xml @@ -972,6 +972,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Aplikacije koriste <xliff:g id="TYPES_LIST">%s</xliff:g>."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" i "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"Aplikacija <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> koristi aplikaciju <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"Aplikacija <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> je nedavno koristila aplikaciju <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(preduzeće)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Telefonski poziv"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(putem aplikacije <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"kameru"</string> <string name="privacy_type_location" msgid="7991481648444066703">"lokaciju"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofon"</string> diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml index 1cc7288344d4..bdcde318179a 100644 --- a/packages/SystemUI/res/values-ca/strings.xml +++ b/packages/SystemUI/res/values-ca/strings.xml @@ -416,10 +416,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Gravació de pantalla"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Inicia"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Atura"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"Per continuar, <b><xliff:g id="APP">%s</xliff:g></b> necessita accedir al micròfon del dispositiu."</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"Per continuar, <b><xliff:g id="APP">%s</xliff:g></b> necessita accedir a la càmera del dispositiu."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"Dispositiu"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Llisca cap amunt per canviar d\'aplicació"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Arrossega el dit cap a la dreta per canviar ràpidament d\'aplicació"</string> @@ -442,8 +440,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"Torna a tocar per obrir-la."</string> <string name="keyguard_unlock" msgid="8031975796351361601">"Llisca cap amunt per obrir"</string> <string name="keyguard_retry" msgid="886802522584053523">"Llisca cap a dalt per tornar-ho a provar"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Desbloqueja per utilitzar l\'NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Aquest dispositiu pertany a la teva organització"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Aquest dispositiu pertany a <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> <string name="phone_hint" msgid="6682125338461375925">"Llisca des de la icona per obrir el telèfon"</string> @@ -970,6 +967,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Algunes aplicacions estan fent servir el següent: <xliff:g id="TYPES_LIST">%s</xliff:g>."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" i "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> està utilitzant: <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"Recentment <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> ha utilitzat: <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(empresa)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Trucada"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(a través de: <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"càmera"</string> <string name="privacy_type_location" msgid="7991481648444066703">"ubicació"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"micròfon"</string> diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml index 13fe67644409..aa5a1dd70695 100644 --- a/packages/SystemUI/res/values-cs/strings.xml +++ b/packages/SystemUI/res/values-cs/strings.xml @@ -420,10 +420,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Záznam obrazovky"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Spustit"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Ukončit"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"Než budete pokračovat, udělte aplikaci <b><xliff:g id="APP">%s</xliff:g></b> přístup k mikrofonu na zařízení."</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"Než budete pokračovat, udělte aplikaci <b><xliff:g id="APP">%s</xliff:g></b> přístup k fotoaparátu na zařízení."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"Zařízení"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Přejetím nahoru přepnete aplikace"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Přetažením doprava rychle přepnete aplikace"</string> @@ -446,8 +444,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"Oznámení otevřete opětovným klepnutím"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"Otevřete přejetím prstem nahoru"</string> <string name="keyguard_retry" msgid="886802522584053523">"Přejetím nahoru to zkusíte znovu"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC vyžaduje odemknutou obrazovku"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Toto zařízení patří vaší organizaci"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Toto zařízení patří organizaci <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> <string name="phone_hint" msgid="6682125338461375925">"Telefon otevřete přejetím prstem od ikony"</string> @@ -980,6 +977,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Aplikace využívají tato oprávnění: <xliff:g id="TYPES_LIST">%s</xliff:g>."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" a "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"Aplikace <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> používá aplikaci <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"Aplikace <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> nedávno použila aplikaci <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(podniková verze)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Telefonní hovor"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(prostřednictvím aplikace <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"fotoaparát"</string> <string name="privacy_type_location" msgid="7991481648444066703">"poloha"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofon"</string> diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml index 18dfc0651a70..5630293c1606 100644 --- a/packages/SystemUI/res/values-da/strings.xml +++ b/packages/SystemUI/res/values-da/strings.xml @@ -416,10 +416,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Optag skærm"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Start"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Stop"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"<b><xliff:g id="APP">%s</xliff:g></b> skal have adgang til din enheds mikrofon, før den kan fortsætte."</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"<b><xliff:g id="APP">%s</xliff:g></b> skal have adgang til din enheds kamera, før den kan fortsætte."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"Enhed"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Stryg opad for at skifte apps"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Træk til højre for hurtigt at skifte app"</string> @@ -442,8 +440,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"Tryk igen for at åbne"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"Stryg opad for at åbne"</string> <string name="keyguard_retry" msgid="886802522584053523">"Stryg opad for at prøve igen"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Lås op for at bruge NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Denne enhed tilhører din organisation"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Denne enhed tilhører <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> <string name="phone_hint" msgid="6682125338461375925">"Stryg fra telefonikonet"</string> @@ -784,7 +781,7 @@ <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string> <string name="keyboard_key_space" msgid="6980847564173394012">"Mellemrumstast"</string> <string name="keyboard_key_enter" msgid="8633362970109751646">"Enter"</string> - <string name="keyboard_key_backspace" msgid="4095278312039628074">"Tilbagetast"</string> + <string name="keyboard_key_backspace" msgid="4095278312039628074">"Backspace"</string> <string name="keyboard_key_media_play_pause" msgid="8389984232732277478">"Afspil/pause"</string> <string name="keyboard_key_media_stop" msgid="1509943745250377699">"Stop"</string> <string name="keyboard_key_media_next" msgid="8502476691227914952">"Næste"</string> @@ -970,6 +967,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Apps anvender enhedens <xliff:g id="TYPES_LIST">%s</xliff:g>"</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" og "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> anvender <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> anvendte <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> for nylig"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(til virksomhedsbrug)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Telefonopkald"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(via <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"kamera"</string> <string name="privacy_type_location" msgid="7991481648444066703">"placering"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofon"</string> diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml index 8485e8447c22..e2468bf04505 100644 --- a/packages/SystemUI/res/values-de/strings.xml +++ b/packages/SystemUI/res/values-de/strings.xml @@ -416,10 +416,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Bildschirmaufnahme"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Starten"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Beenden"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"Zum Fortfahren benötigt, <b><xliff:g id="APP">%s</xliff:g></b> Zugriff auf das Mikrofon deines Geräts."</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"Zum Fortfahren benötigt <b><xliff:g id="APP">%s</xliff:g></b> Zugriff auf die Kamera deines Geräts."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"Gerät"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Nach oben wischen, um Apps zu wechseln"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Zum schnellen Wechseln der Apps nach rechts ziehen"</string> @@ -442,8 +440,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"Erneut tippen, um Benachrichtigung zu öffnen"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"Zum Öffnen nach oben wischen"</string> <string name="keyguard_retry" msgid="886802522584053523">"Zum Wiederholen nach oben wischen"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Zur Verwendung von NFC entsperren"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Dieses Gerät gehört deiner Organisation"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Dieses Gerät gehört <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> <string name="phone_hint" msgid="6682125338461375925">"Zum Öffnen des Telefons vom Symbol wegwischen"</string> @@ -970,6 +967,16 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Apps verwenden gerade Folgendes: <xliff:g id="TYPES_LIST">%s</xliff:g>."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" und "</string> + <!-- no translation found for ongoing_privacy_dialog_using_op (4125175620929701569) --> + <skip /> + <!-- no translation found for ongoing_privacy_dialog_recent_op (4255923947334262404) --> + <skip /> + <!-- no translation found for ongoing_privacy_dialog_enterprise (4082735415905550729) --> + <skip /> + <!-- no translation found for ongoing_privacy_dialog_phonecall (3526223335298089311) --> + <skip /> + <!-- no translation found for ongoing_privacy_dialog_attribution_text (9186683306719924646) --> + <skip /> <string name="privacy_type_camera" msgid="7974051382167078332">"Kamera"</string> <string name="privacy_type_location" msgid="7991481648444066703">"Standort"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"Mikrofon"</string> diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml index f21a9c9d0468..aa747f24a8df 100644 --- a/packages/SystemUI/res/values-el/strings.xml +++ b/packages/SystemUI/res/values-el/strings.xml @@ -416,10 +416,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Εγγραφή οθόνης"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Έναρξη"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Διακοπή"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"Για να συνεχίσετε, η εφαρμογή <b><xliff:g id="APP">%s</xliff:g></b&gt, χρειάζεται πρόσβαση στο μικρόφωνο της συσκευής σας."</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"Για να συνεχίσετε, η εφαρμογή <b><xliff:g id="APP">%s</xliff:g></b> χρειάζεται πρόσβαση στην κάμερα της συσκευής σας."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"Συσκευή"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Σύρετε προς τα επάνω για εναλλαγή των εφαρμογών"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Σύρετε προς τα δεξιά για γρήγορη εναλλαγή εφαρμογών"</string> @@ -442,8 +440,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"Πατήστε ξανά για να ανοίξετε"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"Σύρετε προς τα επάνω για άνοιγμα"</string> <string name="keyguard_retry" msgid="886802522584053523">"Σύρετε προς τα πάνω για να δοκιμάσετε ξανά"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Ξεκλείδωμα για χρήση του NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Αυτή η συσκευή ανήκει στον οργανισμό σας."</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Αυτή η συσκευή ανήκει στον οργανισμό <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> <string name="phone_hint" msgid="6682125338461375925">"Σύρετε προς τα έξω για τηλέφωνο"</string> @@ -970,6 +967,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Οι εφαρμογές χρησιμοποιούν τις λειτουργίες <xliff:g id="TYPES_LIST">%s</xliff:g>."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" και "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"Χρήση <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> από την εφαρμογή <xliff:g id="APPLICATION_NAME">%1$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"Πρόσφατη χρήση <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> από την εφαρμογή <xliff:g id="APPLICATION_NAME">%1$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(για επιχειρήσεις)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Τηλεφωνική κλήση"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(μέσω <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"κάμερα"</string> <string name="privacy_type_location" msgid="7991481648444066703">"τοποθεσία"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"μικρόφωνο"</string> diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml index 4ae38f584303..88a40c346e79 100644 --- a/packages/SystemUI/res/values-en-rAU/strings.xml +++ b/packages/SystemUI/res/values-en-rAU/strings.xml @@ -967,6 +967,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Applications are using your <xliff:g id="TYPES_LIST">%s</xliff:g>."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" and "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> is using the <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> used the <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> recently"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(enterprise)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Phonecall"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(through <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"camera"</string> <string name="privacy_type_location" msgid="7991481648444066703">"location"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"microphone"</string> diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml index ff5e873e5435..bf7883af8138 100644 --- a/packages/SystemUI/res/values-en-rCA/strings.xml +++ b/packages/SystemUI/res/values-en-rCA/strings.xml @@ -967,6 +967,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Applications are using your <xliff:g id="TYPES_LIST">%s</xliff:g>."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" and "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> is using the <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> used the <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> recently"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(enterprise)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Phonecall"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(through <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"camera"</string> <string name="privacy_type_location" msgid="7991481648444066703">"location"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"microphone"</string> diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml index 4ae38f584303..88a40c346e79 100644 --- a/packages/SystemUI/res/values-en-rGB/strings.xml +++ b/packages/SystemUI/res/values-en-rGB/strings.xml @@ -967,6 +967,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Applications are using your <xliff:g id="TYPES_LIST">%s</xliff:g>."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" and "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> is using the <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> used the <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> recently"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(enterprise)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Phonecall"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(through <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"camera"</string> <string name="privacy_type_location" msgid="7991481648444066703">"location"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"microphone"</string> diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml index 4ae38f584303..88a40c346e79 100644 --- a/packages/SystemUI/res/values-en-rIN/strings.xml +++ b/packages/SystemUI/res/values-en-rIN/strings.xml @@ -967,6 +967,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Applications are using your <xliff:g id="TYPES_LIST">%s</xliff:g>."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" and "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> is using the <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> used the <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> recently"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(enterprise)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Phonecall"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(through <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"camera"</string> <string name="privacy_type_location" msgid="7991481648444066703">"location"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"microphone"</string> diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml index cddd75e48d27..a14566ac0c1a 100644 --- a/packages/SystemUI/res/values-en-rXC/strings.xml +++ b/packages/SystemUI/res/values-en-rXC/strings.xml @@ -967,6 +967,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Applications are using your <xliff:g id="TYPES_LIST">%s</xliff:g>."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" and "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> is using the <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> used the <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> recently"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(enterprise)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Phonecall"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(through <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"camera"</string> <string name="privacy_type_location" msgid="7991481648444066703">"location"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"microphone"</string> diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml index 021d944f6aec..4b482b914164 100644 --- a/packages/SystemUI/res/values-es-rUS/strings.xml +++ b/packages/SystemUI/res/values-es-rUS/strings.xml @@ -967,6 +967,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Hay aplicaciones que están usando tu <xliff:g id="TYPES_LIST">%s</xliff:g>."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" y "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> está usando <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> usó <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> recientemente"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(empresarial)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Teléfono"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(a través de <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"cámara"</string> <string name="privacy_type_location" msgid="7991481648444066703">"ubicación"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"micrófono"</string> diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml index 584116e263f8..36fee3f89da9 100644 --- a/packages/SystemUI/res/values-es/strings.xml +++ b/packages/SystemUI/res/values-es/strings.xml @@ -416,10 +416,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Grabar pantalla"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Iniciar"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Detener"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"Para continuar, <b><xliff:g id="APP">%s</xliff:g></b> necesita tener acceso al micrófono del dispositivo."</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"Para continuar, <b><xliff:g id="APP">%s</xliff:g></b> necesita tener acceso a la cámara del dispositivo."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"Dispositivo"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Desliza el dedo hacia arriba para cambiar de aplicación"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Arrastra hacia la derecha para cambiar rápidamente de aplicación"</string> @@ -442,8 +440,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"Toca de nuevo para abrir"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"Desliza el dedo hacia arriba para abrir"</string> <string name="keyguard_retry" msgid="886802522584053523">"Desliza el dedo hacia arriba para volverlo a intentar"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Desbloquear para usar NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Este dispositivo pertenece a tu organización"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Este dispositivo pertenece a <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> <string name="phone_hint" msgid="6682125338461375925">"Desliza desde el icono para abrir el teléfono"</string> @@ -970,6 +967,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Hay aplicaciones que usan tu <xliff:g id="TYPES_LIST">%s</xliff:g>."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" y "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> está usando este elemento: <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> ha usado recientemente este elemento: <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(empresa)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Llamada telefónica"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(a través de <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"cámara"</string> <string name="privacy_type_location" msgid="7991481648444066703">"ubicación"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"micrófono"</string> diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml index 72c6907353b0..ff043e0872af 100644 --- a/packages/SystemUI/res/values-et/strings.xml +++ b/packages/SystemUI/res/values-et/strings.xml @@ -416,10 +416,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Ekraanisalvestus"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Alustage"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Peatage"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"Jätkamiseks vajab rakendus <b><xliff:g id="APP">%s</xliff:g></b> juurdepääsu teie seadme mikrofonile."</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"Jätkamiseks vajab rakendus <b><xliff:g id="APP">%s</xliff:g></b> juurdepääsu teie seadme kaamerale."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"Seade"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Rakenduste vahetamiseks pühkige üles"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Lohistage paremale, et rakendusi kiiresti vahetada"</string> @@ -442,8 +440,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"Avamiseks puudutage uuesti"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"Pühkige avamiseks üles"</string> <string name="keyguard_retry" msgid="886802522584053523">"Uuesti proovimiseks pühkige üles"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC kasutamiseks avage."</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"See seade kuulub teie organisatsioonile"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Selle seadme omanik on <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> <string name="phone_hint" msgid="6682125338461375925">"Telefoni kasutamiseks pühkige ikoonilt eemale"</string> @@ -970,6 +967,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Rakendused kasutavad järgmisi: <xliff:g id="TYPES_LIST">%s</xliff:g>."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" ja "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> kasutab järgmist: <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> kasutas hiljuti järgmist: <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(ettevõte)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Telefonikõne"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(üksuse <xliff:g id="ATTRIBUTION">%s</xliff:g> kaudu)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"kaamera"</string> <string name="privacy_type_location" msgid="7991481648444066703">"asukoht"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofon"</string> diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml index ab26b92b2fae..7517f17623fc 100644 --- a/packages/SystemUI/res/values-eu/strings.xml +++ b/packages/SystemUI/res/values-eu/strings.xml @@ -416,10 +416,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Pantaila-grabaketa"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Hasi"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Gelditu"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"Aurrera egiteko, gailuaren mikrofonoa atzitzeko baimena behar du <b><xliff:g id="APP">%s</xliff:g></b> aplikazioak."</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"Aurrera egiteko, gailuaren kamera atzitzeko baimena behar du <b><xliff:g id="APP">%s</xliff:g></b> aplikazioak."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"Gailua"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Egin gora aplikazioa aldatzeko"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Arrastatu eskuinera aplikazioa azkar aldatzeko"</string> @@ -442,8 +440,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"Irekitzeko, ukitu berriro"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"Pasatu hatza gora irekitzeko"</string> <string name="keyguard_retry" msgid="886802522584053523">"Berriro saiatzeko, pasatu hatza gora"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Desblokeatu NFC erabiltzeko"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Gailu hau zure erakundearena da"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Gailu hau <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> erakundearena da"</string> <string name="phone_hint" msgid="6682125338461375925">"Pasatu hatza ikonotik, telefonoa irekitzeko"</string> @@ -970,6 +967,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Aplikazio batzuk <xliff:g id="TYPES_LIST">%s</xliff:g> erabiltzen ari dira."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" eta "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> aplikazioa <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> erabiltzen ari da"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> aplikazioak <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> erabili du duela gutxi"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(enpresa)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Telefono-deia"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(<xliff:g id="ATTRIBUTION">%s</xliff:g> aplikazioaren bidez)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"kamera"</string> <string name="privacy_type_location" msgid="7991481648444066703">"kokapena"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofonoa"</string> diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml index dccea5a5c84b..231eb45fef64 100644 --- a/packages/SystemUI/res/values-fa/strings.xml +++ b/packages/SystemUI/res/values-fa/strings.xml @@ -967,6 +967,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"برنامهها از <xliff:g id="TYPES_LIST">%s</xliff:g> شما استفاده میکنند."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">"، "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" و "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> درحال استفاده از <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> است"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> اخیراً از <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> استفاده کرده است"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(شرکتی)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Phonecall"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(ازطریق <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"دوربین"</string> <string name="privacy_type_location" msgid="7991481648444066703">"مکان"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"میکروفون"</string> diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml index 5b43cf94c166..a6c43d96ae81 100644 --- a/packages/SystemUI/res/values-fi/strings.xml +++ b/packages/SystemUI/res/values-fi/strings.xml @@ -416,10 +416,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Tallennus"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Aloita"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Lopeta"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"Jotta voit jatkaa, <b><xliff:g id="APP">%s</xliff:g></b> tarvitsee pääsyn laitteesi mikrofoniin."</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"Jotta voit jatkaa, <b><xliff:g id="APP">%s</xliff:g></b> tarvitsee pääsyn laitteesi kameraan."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"Laite"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Vaihda sovellusta pyyhkäisemällä ylös"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Vaihda sovellusta nopeasti vetämällä oikealle"</string> @@ -442,8 +440,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"Avaa napauttamalla uudelleen"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"Avaa pyyhkäisemällä ylös"</string> <string name="keyguard_retry" msgid="886802522584053523">"Yritä uudelleen pyyhkäisemällä ylös"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Avaa lukitus käyttääksesi NFC:tä"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Organisaatiosi omistaa tämän laitteen"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"<xliff:g id="ORGANIZATION_NAME">%s</xliff:g> omistaa tämän laitteen"</string> <string name="phone_hint" msgid="6682125338461375925">"Avaa puhelu pyyhkäisemällä."</string> @@ -970,6 +967,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"<xliff:g id="TYPES_LIST">%s</xliff:g> ovat sovellusten käytössä."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" ja "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> käyttää kohdetta <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> käytti kohdetta <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> äskettäin"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(yritys)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Puhelu"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(kautta: <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"kamera"</string> <string name="privacy_type_location" msgid="7991481648444066703">"sijainti"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofoni"</string> diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml index 2e36a92d073a..07f8af5ad4e2 100644 --- a/packages/SystemUI/res/values-fr-rCA/strings.xml +++ b/packages/SystemUI/res/values-fr-rCA/strings.xml @@ -967,6 +967,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Des applications utilisent votre <xliff:g id="TYPES_LIST">%s</xliff:g>."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" et "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> utilise cet élément : <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> a récemment utilisé cet élément : <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(entreprise)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Appel téléphonique"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(par l\'intermédiaire de <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"appareil photo"</string> <string name="privacy_type_location" msgid="7991481648444066703">"position"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"microphone"</string> diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml index b8a70ee62545..7bbbff668710 100644 --- a/packages/SystemUI/res/values-fr/strings.xml +++ b/packages/SystemUI/res/values-fr/strings.xml @@ -416,10 +416,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Enregistrement de l\'écran"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Démarrer"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Arrêter"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"Pour continuer, <b><xliff:g id="APP">%s</xliff:g></b> a besoin d\'accéder au micro de votre appareil."</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"Pour continuer, <b><xliff:g id="APP">%s</xliff:g></b> a besoin d\'accéder à l\'appareil photo de votre appareil."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"Appareil"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Balayer l\'écran vers le haut pour changer d\'application"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Déplacer vers la droite pour changer rapidement d\'application"</string> @@ -442,8 +440,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"Appuyer à nouveau pour ouvrir"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"Balayer vers le haut pour ouvrir"</string> <string name="keyguard_retry" msgid="886802522584053523">"Balayez l\'écran vers le haut pour réessayer"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Déverrouillez l\'écran pour pouvoir utiliser NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Cet appareil appartient à votre organisation"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Cet appareil appartient à <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> <string name="phone_hint" msgid="6682125338461375925">"Balayer pour téléphoner"</string> @@ -970,6 +967,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Des applications utilisent votre <xliff:g id="TYPES_LIST">%s</xliff:g>."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" et "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> utilise <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> a utilisé <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> récemment"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(Enterprise)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Appel téléphonique"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(via <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"appareil photo"</string> <string name="privacy_type_location" msgid="7991481648444066703">"position"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"micro"</string> diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml index 40a514e25b95..0ac82616c4aa 100644 --- a/packages/SystemUI/res/values-gl/strings.xml +++ b/packages/SystemUI/res/values-gl/strings.xml @@ -416,10 +416,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Gravación da pantalla"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Iniciar"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Deter"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"Para continuar, <b><xliff:g id="APP">%s</xliff:g></b> precisa acceder ao micrófono do dispositivo."</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"Para continuar, <b><xliff:g id="APP">%s</xliff:g></b> precisa acceder á cámara do dispositivo."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"Dispositivo"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Pasar o dedo cara arriba para cambiar de aplicación"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Arrastra cara á dereita para cambiar de aplicacións rapidamente"</string> @@ -442,8 +440,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"Toca de novo para abrir"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"Pasa o dedo cara arriba para abrir"</string> <string name="keyguard_retry" msgid="886802522584053523">"Pasa o dedo cara arriba para tentalo de novo"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Desbloquea o dispositivo para utilizar a NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Este dispositivo pertence á túa organización"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Este dispositivo pertence a <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> <string name="phone_hint" msgid="6682125338461375925">"Pasa o dedo desde a icona para acceder ao teléfono"</string> @@ -970,6 +967,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Hai aplicacións que están utilizando <xliff:g id="TYPES_LIST">%s</xliff:g>."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" e "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> está utilizando a aplicación <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> utilizou recentemente a aplicación <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(versión empresarial)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Chamada de teléfono"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(mediante <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"a cámara"</string> <string name="privacy_type_location" msgid="7991481648444066703">"a localiz."</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"o micrófono"</string> diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml index 2c37ce76d49b..f4e13332a34a 100644 --- a/packages/SystemUI/res/values-gu/strings.xml +++ b/packages/SystemUI/res/values-gu/strings.xml @@ -416,10 +416,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"સ્ક્રીન રેકૉર્ડ કરો"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"શરૂ કરો"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"રોકો"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"ચાલુ રાખવા માટે, <b><xliff:g id="APP">%s</xliff:g></b>ને તમારા ડિવાઇસના માઇક્રોફોનના ઍક્સેસની જરૂર છે."</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"ચાલુ રાખવા માટે, <b><xliff:g id="APP">%s</xliff:g></b>ને તમારા ડિવાઇસના કૅમેરાના ઍક્સેસની જરૂર છે."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"ડિવાઇસ"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"ઍપ સ્વિચ કરવા માટે ઉપરની તરફ સ્વાઇપ કરો"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"ઍપને ઝડપથી સ્વિચ કરવા માટે જમણે ખેંચો"</string> @@ -442,8 +440,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"ખોલવા માટે ફરીથી ટૅપ કરો"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"ખોલવા માટે ઉપરની તરફ સ્વાઇપ કરો"</string> <string name="keyguard_retry" msgid="886802522584053523">"ફરી પ્રયાસ કરવા માટે ઉપરની તરફ સ્વાઇપ કરો"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFCનો ઉપયોગ કરવા માટે અનલૉક કરો"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"આ ડિવાઇસ તમારી સંસ્થાની માલિકીનું છે"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"આ ડિવાઇસ <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>ની માલિકીનું છે"</string> <string name="phone_hint" msgid="6682125338461375925">"ફોન માટે આયકનમાંથી સ્વાઇપ કરો"</string> @@ -970,6 +967,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"ઍપ્લિકેશન તમારા <xliff:g id="TYPES_LIST">%s</xliff:g>નો ઉપયોગ કરી રહી છે."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" અને "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g>, <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>નો ઉપયોગ કરી રહી છે"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g>એ તાજેતરમાં જ <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>નો ઉપયોગ કર્યો છે"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(એન્ટરપ્રાઇઝ)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"ફોન કૉલ"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(<xliff:g id="ATTRIBUTION">%s</xliff:g> મારફતે)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"કૅમેરા"</string> <string name="privacy_type_location" msgid="7991481648444066703">"સ્થાન"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"માઇક્રોફોન"</string> diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml index af9bf1e2c19d..50b078f97ccb 100644 --- a/packages/SystemUI/res/values-hi/strings.xml +++ b/packages/SystemUI/res/values-hi/strings.xml @@ -418,10 +418,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"स्क्रीन रिकॉर्ड"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"शुरू करें"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"रोकें"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"जारी रखने के लिए, <b><xliff:g id="APP">%s</xliff:g></b> को आपके डिवाइस का माइक्रोफ़ोन ऐक्सेस करने की ज़रूरत है."</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"जारी रखने के लिए, <b><xliff:g id="APP">%s</xliff:g></b> को आपके डिवाइस का कैमरा ऐक्सेस करने की ज़रूरत है."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"डिवाइस"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"ऐप्लिकेशन बदलने के लिए ऊपर स्वाइप करें"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"ऐप्लिकेशन को झटपट स्विच करने के लिए उसे दाईं ओर खींचें और छोड़ें"</string> @@ -444,8 +442,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"खोलने के लिए फिर से टैप करें"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"खोलने के लिए ऊपर स्वाइप करें"</string> <string name="keyguard_retry" msgid="886802522584053523">"फिर से कोशिश करने के लिए ऊपर की ओर स्वाइप करें"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"एनएफ़सी इस्तेमाल करने के लिए, स्क्रीन को अनलॉक करें"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"इस डिवाइस का मालिकाना हक आपके संगठन के पास है"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"इस डिवाइस का मालिकाना हक <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> के पास है"</string> <string name="phone_hint" msgid="6682125338461375925">"फ़ोन के लिए आइकॉन से स्वाइप करें"</string> @@ -972,6 +969,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"ऐप्लिकेशन आपकी <xliff:g id="TYPES_LIST">%s</xliff:g> का इस्तेमाल कर रहे हैं."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" और "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g>, <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> का इस्तेमाल कर रहा है"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> ने हाल ही में <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> का इस्तेमाल किया"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"एंटरप्राइज़ वर्शन"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Phonecall"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"<xliff:g id="ATTRIBUTION">%s</xliff:g> के ज़रिए"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"कैमरा"</string> <string name="privacy_type_location" msgid="7991481648444066703">"जगह"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"माइक्रोफ़ोन"</string> diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml index 73e13499b1bc..c80f26260fca 100644 --- a/packages/SystemUI/res/values-hr/strings.xml +++ b/packages/SystemUI/res/values-hr/strings.xml @@ -418,10 +418,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Snimač zaslona"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Početak"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Zaustavi"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"Da bi nastavila s radom, aplikacija <b><xliff:g id="APP">%s</xliff:g></b> treba pristupiti mikrofonu vašeg uređaja."</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"Da bi nastavila s radom, aplikacija <b><xliff:g id="APP">%s</xliff:g></b> treba pristupiti fotoaparatu vašeg uređaja."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"Uređaj"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Prijeđite prstom prema gore da biste promijenili aplikaciju"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Povucite udesno da biste brzo promijenili aplikaciju"</string> @@ -444,8 +442,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"Dodirnite opet za otvaranje"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"Prijeđite prstom prema gore da biste otvorili"</string> <string name="keyguard_retry" msgid="886802522584053523">"Prijeđite prstom prema gore za ponovni pokušaj"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Otključajte da biste upotrijebili NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Ovaj uređaj pripada vašoj organizaciji"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Ovaj uređaj pripada organizaciji <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> <string name="phone_hint" msgid="6682125338461375925">"Prijeđite prstom od ikone za telefon"</string> @@ -975,6 +972,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Aplikacije upotrebljavaju <xliff:g id="TYPES_LIST">%s</xliff:g>."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" i "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"Aplikacija <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> koristi sljedeće: <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"Aplikacija <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> nedavno je koristila sljedeće: <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(za poslovne korisnike)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Telefonski poziv"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(putem aplikacije <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"fotoaparat"</string> <string name="privacy_type_location" msgid="7991481648444066703">"lokaciju"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofon"</string> diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml index c947754be25a..868b2e7cbbb0 100644 --- a/packages/SystemUI/res/values-hu/strings.xml +++ b/packages/SystemUI/res/values-hu/strings.xml @@ -416,10 +416,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Képernyő rögzítése"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Indítás"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Leállítás"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"A folytatáshoz a(z) <b><xliff:g id="APP">%s</xliff:g></b> alkalmazásnak hozzáférésre van szüksége az eszköze mikrofonjához."</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"A folytatáshoz a(z) <b><xliff:g id="APP">%s</xliff:g></b> alkalmazásnak hozzáférésre van szüksége az eszköze kamerájához."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"Eszköz"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Váltás az alkalmazások között felfelé csúsztatással"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Húzza jobbra az ujját az alkalmazások közötti gyors váltáshoz"</string> @@ -442,8 +440,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"Koppintson ismét a megnyitáshoz"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"Csúsztasson felfelé a megnyitáshoz"</string> <string name="keyguard_retry" msgid="886802522584053523">"Az újrapróbálkozáshoz csúsztassa felfelé az ujját"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Az NFC használatához oldja fel a képernyőzárat"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Ez az eszköz az Ön szervezetének tulajdonában van"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Ez az eszköz a(z) <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> tulajdonában van"</string> <string name="phone_hint" msgid="6682125338461375925">"A telefonhoz csúsztasson az ikonról"</string> @@ -970,6 +967,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Több alkalmazás használja a következőket: <xliff:g id="TYPES_LIST">%s</xliff:g>."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" és "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"A(z) <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> használja a következőt: <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"A(z) <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> nemrég használta a következőt: <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(vállalati)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Telefonhívás"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(a következőn keresztül: <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"kamera"</string> <string name="privacy_type_location" msgid="7991481648444066703">"helyadatok"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofon"</string> diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml index 1ef540c05e75..3c088749ed57 100644 --- a/packages/SystemUI/res/values-hy/strings.xml +++ b/packages/SystemUI/res/values-hy/strings.xml @@ -416,10 +416,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Էկրանի ձայնագրում"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Սկսել"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Կանգնեցնել"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"Շարունակելու համար <b><xliff:g id="APP">%s</xliff:g></b> հավելվածին անհրաժեշտ է ձեր սարքի խոսափողի օգտագործման թույլտվություն։"</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"Շարունակելու համար <b><xliff:g id="APP">%s</xliff:g></b> հավելվածին անհրաժեշտ է ձեր սարքի տեսախցիկի օգտագործման թույլտվություն։"</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"Սարք"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Սահեցրեք վերև՝ մյուս հավելվածին անցնելու համար"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Քաշեք աջ՝ հավելվածների միջև անցնելու համար"</string> @@ -442,8 +440,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"Կրկին հպեք՝ բացելու համար"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"Բացելու համար սահեցրեք վերև"</string> <string name="keyguard_retry" msgid="886802522584053523">"Սահեցրեք վերև՝ նորից փորձելու համար"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Ապակողպեք՝ NFC-ն օգտագործելու համար"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Այս սարքը պատկանում է ձեր կազմակերպությանը"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Այս սարքը պատկանում է «<xliff:g id="ORGANIZATION_NAME">%s</xliff:g>» կազմակերպությանը"</string> <string name="phone_hint" msgid="6682125338461375925">"Սահահարվածեք հեռախոսի պատկերակից"</string> @@ -970,6 +967,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Հավելվածներն օգտագործում են ձեր <xliff:g id="TYPES_LIST">%s</xliff:g>:"</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" և "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> հավելվածն օգտագործում է «<xliff:g id="APP_OPP_NAME">%2$s</xliff:g>» գործառույթը"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> հավելվածը վերջերս օգտագործել է «<xliff:g id="APP_OPP_NAME">%2$s</xliff:g>» գործառույթը"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(կորպորատիվ տարբերակ)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Հեռախոսազանգ"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(<xliff:g id="ATTRIBUTION">%s</xliff:g>-ի միջոցով)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"տեսախցիկը"</string> <string name="privacy_type_location" msgid="7991481648444066703">"վայրը"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"խոսափողը"</string> diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml index 0de7efa85607..a5d8a27cf5a0 100644 --- a/packages/SystemUI/res/values-in/strings.xml +++ b/packages/SystemUI/res/values-in/strings.xml @@ -416,10 +416,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Rekaman Layar"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Mulai"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Berhenti"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"Untuk melanjutkan, <b><xliff:g id="APP">%s</xliff:g></b> memerlukan akses ke mikrofon perangkat."</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"Untuk melanjutkan, <b><xliff:g id="APP">%s</xliff:g></b> memerlukan akses ke kamera perangkat."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"Perangkat"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Geser ke atas untuk beralih aplikasi"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Tarik ke kanan untuk beralih aplikasi dengan cepat"</string> @@ -442,8 +440,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"Ketuk lagi untuk membuka"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"Geser ke atas untuk membuka"</string> <string name="keyguard_retry" msgid="886802522584053523">"Geser ke atas untuk mencoba lagi"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Buka kunci untuk menggunakan NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Perangkat ini milik organisasi Anda"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Perangkat ini milik <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> <string name="phone_hint" msgid="6682125338461375925">"Geser dari ikon untuk telepon"</string> @@ -970,6 +967,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Aplikasi menggunakan <xliff:g id="TYPES_LIST">%s</xliff:g>."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" dan "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> sedang menggunakan <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> menggunakan <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> baru-baru ini"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(perusahaan)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Panggilan telepon"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(melalui <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"kamera"</string> <string name="privacy_type_location" msgid="7991481648444066703">"lokasi"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofon"</string> diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml index 777479d4da1f..5f794e76150f 100644 --- a/packages/SystemUI/res/values-is/strings.xml +++ b/packages/SystemUI/res/values-is/strings.xml @@ -416,10 +416,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Skjáupptaka"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Hefja"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Stöðva"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"Til að halda áfram þarf <b><xliff:g id="APP">%s</xliff:g></b> aðgang að hljóðnema tækisins."</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"Til að halda áfram þarf <b><xliff:g id="APP">%s</xliff:g></b> aðgang að myndavél tækisins."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"Tæki"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Strjúktu upp til að skipta á milli forrita"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Dragðu til hægri til að skipta hratt á milli forrita"</string> @@ -442,8 +440,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"Ýttu aftur til að opna"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"Strjúktu upp til að opna"</string> <string name="keyguard_retry" msgid="886802522584053523">"Strjúktu upp til að reyna aftur"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Taktu úr lás til að nota NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Þetta tæki tilheyrir fyrirtækinu þínu"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Þetta tæki tilheyrir <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> <string name="phone_hint" msgid="6682125338461375925">"Strjúktu frá tákninu fyrir síma"</string> @@ -970,6 +967,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Forrit eru að nota <xliff:g id="TYPES_LIST">%s</xliff:g>."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" og "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> er að nota <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> notaði <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> nýlega"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(fyrirtæki)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Símtal"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(í gegnum <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"myndavél"</string> <string name="privacy_type_location" msgid="7991481648444066703">"staðsetning"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"hljóðnemi"</string> diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml index 2af2d5f4344e..cfd07970b0cd 100644 --- a/packages/SystemUI/res/values-it/strings.xml +++ b/packages/SystemUI/res/values-it/strings.xml @@ -416,10 +416,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Registrazione schermo"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Inizia"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Interrompi"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"Per continuare, l\'app <b><xliff:g id="APP">%s</xliff:g></b> deve accedere al microfono del dispositivo."</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"Per continuare, l\'app <b><xliff:g id="APP">%s</xliff:g></b> deve accedere alla videocamera del dispositivo."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"Dispositivo"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Scorri verso l\'alto per passare ad altre app"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Trascina verso destra per cambiare velocemente app"</string> @@ -442,8 +440,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"Tocca ancora per aprire"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"Scorri verso l\'alto per aprire"</string> <string name="keyguard_retry" msgid="886802522584053523">"Scorri verso l\'alto per riprovare"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Sblocca per usare NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Questo dispositivo appartiene alla tua organizzazione"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Questo dispositivo appartiene a <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> <string name="phone_hint" msgid="6682125338461375925">"Scorri per accedere al telefono"</string> @@ -970,6 +967,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Le app stanno usando <xliff:g id="TYPES_LIST">%s</xliff:g>."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" e "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> sta usando: <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> ha usato di recente: <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(enterprise)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Phonecall"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(tramite <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"Fotocamera"</string> <string name="privacy_type_location" msgid="7991481648444066703">"luogo"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"un microfono"</string> diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml index e8a1ede7d39f..c4d088d24cce 100644 --- a/packages/SystemUI/res/values-iw/strings.xml +++ b/packages/SystemUI/res/values-iw/strings.xml @@ -420,10 +420,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"הקלטת המסך"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"התחלה"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"עצירה"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"כדי להמשיך, האפליקציה <b><xliff:g id="APP">%s</xliff:g></b> צריכה גישה למיקרופון של המכשיר שלך."</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"כדי להמשיך, האפליקציה <b><xliff:g id="APP">%s</xliff:g></b> צריכה גישה למצלמה של המכשיר שלך."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"מכשיר"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"יש להחליק מעלה כדי להחליף אפליקציות"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"יש לגרור ימינה כדי לעבור במהירות בין אפליקציות"</string> @@ -446,8 +444,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"הקש שוב כדי לפתוח"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"צריך להחליק כדי לפתוח"</string> <string name="keyguard_retry" msgid="886802522584053523">"יש להחליק למעלה כדי לנסות שוב"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"יש לבטל נעילה כדי להשתמש ב-NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"המכשיר הזה שייך לארגון שלך"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"המכשיר הזה שייך לארגון <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> <string name="phone_hint" msgid="6682125338461375925">"החלק מהסמל כדי להפעיל את הטלפון"</string> @@ -980,6 +977,16 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"אפליקציות משתמשות ב<xliff:g id="TYPES_LIST">%s</xliff:g>."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" וגם "</string> + <!-- no translation found for ongoing_privacy_dialog_using_op (4125175620929701569) --> + <skip /> + <!-- no translation found for ongoing_privacy_dialog_recent_op (4255923947334262404) --> + <skip /> + <!-- no translation found for ongoing_privacy_dialog_enterprise (4082735415905550729) --> + <skip /> + <!-- no translation found for ongoing_privacy_dialog_phonecall (3526223335298089311) --> + <skip /> + <!-- no translation found for ongoing_privacy_dialog_attribution_text (9186683306719924646) --> + <skip /> <string name="privacy_type_camera" msgid="7974051382167078332">"מצלמה"</string> <string name="privacy_type_location" msgid="7991481648444066703">"מיקום"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"מיקרופון"</string> diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml index e15366c5f37a..3fcc7138d9b3 100644 --- a/packages/SystemUI/res/values-ja/strings.xml +++ b/packages/SystemUI/res/values-ja/strings.xml @@ -416,10 +416,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"スクリーン レコード"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"開始"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"停止"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"続行するには、<b><xliff:g id="APP">%s</xliff:g></b> にデバイスのマイクへのアクセスを許可する必要があります。"</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"続行するには、<b><xliff:g id="APP">%s</xliff:g></b> にデバイスのカメラへのアクセスを許可する必要があります。"</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"デバイス"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"アプリを切り替えるには上にスワイプ"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"右にドラッグするとアプリを素早く切り替えることができます"</string> @@ -442,8 +440,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"開くにはもう一度タップしてください"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"開くには上にスワイプします"</string> <string name="keyguard_retry" msgid="886802522584053523">"上にスワイプしてもう一度お試しください"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC を使用するには、ロックを解除してください"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"これは組織が所有するデバイスです"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"これは <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> が所有するデバイスです"</string> <string name="phone_hint" msgid="6682125338461375925">"右にスワイプして通話"</string> @@ -970,6 +967,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"アプリは<xliff:g id="TYPES_LIST">%s</xliff:g>を使用しています。"</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">"、 "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" 、 "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> は <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> を使用しています"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> は最近 <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> を使用しました"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(エンタープライズ版)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"電話"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(<xliff:g id="ATTRIBUTION">%s</xliff:g> 経由)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"カメラ"</string> <string name="privacy_type_location" msgid="7991481648444066703">"現在地情報"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"マイク"</string> diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml index 386847e198ea..5c11fa44f3fc 100644 --- a/packages/SystemUI/res/values-ka/strings.xml +++ b/packages/SystemUI/res/values-ka/strings.xml @@ -416,10 +416,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"ეკრანის ჩანაწერი"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"დაწყება"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"შეწყვეტა"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"გასაგრძელებლად <b><xliff:g id="APP">%s</xliff:g></b>-ს თქვენი მოწყობილობის მიკროფონზე წვდომა სჭირდება."</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"გასაგრძელებლად <b><xliff:g id="APP">%s</xliff:g></b>-ს თქვენი მოწყობილობის კამერაზე წვდომა სჭირდება."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"მოწყობილობა"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"გადაფურცლეთ ზემოთ აპების გადასართავად"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"აპების სწრაფად გადასართავად ჩავლებით გადაიტანეთ მარჯვნივ"</string> @@ -442,8 +440,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"შეეხეთ ისევ გასახსნელად"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"გასახსნელად გადაფურცლეთ ზემოთ"</string> <string name="keyguard_retry" msgid="886802522584053523">"ხელახლა საცდელად გადაფურცლეთ ზემოთ"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"განბლოკეთ NFC-ის გამოსაყენებლად"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"ამ მოწყობილობას ფლობს თქვენი ორგანიზაცია"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"ამ მოწყობილობას ფლობს <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> <string name="phone_hint" msgid="6682125338461375925">"ტელეფონისთვის გადაფურცლეთ ხატულადან"</string> @@ -970,6 +967,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"აპლიკაციების მიერ გამოიყენება თქვენი <xliff:g id="TYPES_LIST">%s</xliff:g>."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" და "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> იყენებს აპს <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"აპმა <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> ახლახან გამოიყენა <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(კორპორაციული)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"სატელეფონო ზარი"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(აპის <xliff:g id="ATTRIBUTION">%s</xliff:g> მეშვეობით)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"კამერა"</string> <string name="privacy_type_location" msgid="7991481648444066703">"მდებარეობა"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"მიკროფონი"</string> diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml index db318eadc1b9..89f905733fa6 100644 --- a/packages/SystemUI/res/values-kk/strings.xml +++ b/packages/SystemUI/res/values-kk/strings.xml @@ -285,8 +285,8 @@ <string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"Жұмыс режимі қосулы."</string> <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6256690740556798683">"Жұмыс режимі өшірілді."</string> <string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"Жұмыс режимі қосылды."</string> - <string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"Data Saver өшірілді."</string> - <string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"Data Saver қосылды."</string> + <string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"Трафикті үнемдеу режимі өшірілді."</string> + <string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"Трафикті үнемдеу режимі қосылды."</string> <string name="accessibility_quick_settings_sensor_privacy_changed_off" msgid="7608378211873807353">"Sensor Privacy функциясы өшірулі."</string> <string name="accessibility_quick_settings_sensor_privacy_changed_on" msgid="4267393685085328801">"Sensor Privacy функциясы қосулы."</string> <string name="accessibility_brightness" msgid="5391187016177823721">"Дисплей жарықтығы"</string> @@ -383,7 +383,7 @@ <string name="quick_settings_tethering_label" msgid="5257299852322475780">"Тетеринг"</string> <string name="quick_settings_hotspot_label" msgid="1199196300038363424">"Хотспот"</string> <string name="quick_settings_hotspot_secondary_label_transient" msgid="7585604088079160564">"Қосылуда…"</string> - <string name="quick_settings_hotspot_secondary_label_data_saver_enabled" msgid="1280433136266439372">"Data Saver қосулы"</string> + <string name="quick_settings_hotspot_secondary_label_data_saver_enabled" msgid="1280433136266439372">"Трафикті үнемдеу режимі қосулы"</string> <plurals name="quick_settings_hotspot_secondary_label_num_devices" formatted="false" msgid="3142308865165871976"> <item quantity="other">%d құрылғы</item> <item quantity="one">%d құрылғы</item> @@ -416,10 +416,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Экранды жазу"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Бастау"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Тоқтату"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"Жалғастыру үшін <b><xliff:g id="APP">%s</xliff:g></b> қолданбасы құрылғыңыздың микрофонына рұқсат алу керек."</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"Жалғастыру үшін <b><xliff:g id="APP">%s</xliff:g></b> қолданбасы құрылғыңыздың камерасына рұқсат алу керек."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"Құрылғы"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Қолданбалар арасында ауысу үшін жоғары сырғытыңыз"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Қолданбаларды жылдам ауыстырып қосу үшін оңға қарай сүйреңіз"</string> @@ -442,8 +440,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"Ашу үшін қайта түртіңіз"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"Ашу үшін жоғары қарай сырғытыңыз."</string> <string name="keyguard_retry" msgid="886802522584053523">"Әрекетті қайталау үшін жоғары сырғытыңыз."</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC пайдалану үшін құлыпты ашыңыз."</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Бұл құрылғы ұйымыңызға тиесілі."</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Бұл құрылғы <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> ұйымына тиесілі."</string> <string name="phone_hint" msgid="6682125338461375925">"Телефонды ашу үшін белгішеден әрі қарай сырғытыңыз"</string> @@ -825,9 +822,9 @@ <string name="accessibility_long_click_tile" msgid="210472753156768705">"Параметрлерді ашу"</string> <string name="accessibility_status_bar_headphones" msgid="1304082414912647414">"Құлақаспап қосылды"</string> <string name="accessibility_status_bar_headset" msgid="2699275863720926104">"Құлақаспап жинағы қосылды"</string> - <string name="data_saver" msgid="3484013368530820763">"Data Saver"</string> - <string name="accessibility_data_saver_on" msgid="5394743820189757731">"Дерек сақтағыш қосулы"</string> - <string name="accessibility_data_saver_off" msgid="58339669022107171">"Дерек сақтағышы өшірулі"</string> + <string name="data_saver" msgid="3484013368530820763">"Трафикті үнемдеу"</string> + <string name="accessibility_data_saver_on" msgid="5394743820189757731">"Трафикті үнемдеу режимі қосулы"</string> + <string name="accessibility_data_saver_off" msgid="58339669022107171">"Трафикті үнемдеу режимі өшірулі"</string> <string name="switch_bar_on" msgid="1770868129120096114">"Қосулы"</string> <string name="switch_bar_off" msgid="5669805115416379556">"Өшірулі"</string> <string name="tile_unavailable" msgid="3095879009136616920">"Қолжетімді емес"</string> @@ -970,6 +967,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Қолданбаларда <xliff:g id="TYPES_LIST">%s</xliff:g> пайдаланылуда."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" және "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> қолданбасы қазір <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> пайдаланады"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> қолданбасы жақында <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> пайдаланды"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(корпоративтік)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Телефон қоңырауы"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(<xliff:g id="ATTRIBUTION">%s</xliff:g> арқылы)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"камера"</string> <string name="privacy_type_location" msgid="7991481648444066703">"геодерек"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"микрофон"</string> diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml index dca2623c9ce2..85557070a51a 100644 --- a/packages/SystemUI/res/values-km/strings.xml +++ b/packages/SystemUI/res/values-km/strings.xml @@ -416,10 +416,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"ការថតអេក្រង់"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"ចាប់ផ្ដើម"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"ឈប់"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"ដើម្បីបន្ត <b><xliff:g id="APP">%s</xliff:g></b> ត្រូវការសិទ្ធិចូលប្រើមីក្រូហ្វូនរបស់ឧបករណ៍អ្នក។"</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"ដើម្បីបន្ត <b><xliff:g id="APP">%s</xliff:g></b> ត្រូវការសិទ្ធិចូលប្រើកាមេរ៉ារបស់ឧបករណ៍អ្នក។"</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"ឧបករណ៍"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"អូសឡើងលើដើម្បីប្តូរកម្មវិធី"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"អូសទៅស្ដាំដើម្បីប្ដូរកម្មវិធីបានរហ័ស"</string> @@ -442,8 +440,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"ប៉ះម្ដងទៀត ដើម្បីបើក"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"អូសឡើងលើដើម្បីបើក"</string> <string name="keyguard_retry" msgid="886802522584053523">"អូសឡើងលើ ដើម្បីព្យាយាមម្ដងទៀត"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"ដោះសោ ដើម្បីប្រើ NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"ឧបករណ៍នេះគឺជាកម្មសិទ្ធិរបស់ស្ថាប័នអ្នក"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"ឧបករណ៍នេះគឺជាកម្មសិទ្ធិរបស់ <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> <string name="phone_hint" msgid="6682125338461375925">"អូសចេញពីរូបតំណាងដើម្បីប្រើទូរស័ព្ទ"</string> @@ -970,6 +967,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"កម្មវិធីកំពុងប្រើ <xliff:g id="TYPES_LIST">%s</xliff:g> របស់អ្នក។"</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" និង "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> កំពុងប្រើ <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> បានប្រើ <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> ថ្មីៗនេះ"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(សហគ្រាស)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"ការហៅទូរសព្ទ"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(តាមរយៈ <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"កាមេរ៉ា"</string> <string name="privacy_type_location" msgid="7991481648444066703">"ទីតាំង"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"មីក្រូហ្វូន"</string> diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml index e08a29611463..c920cc288bc2 100644 --- a/packages/SystemUI/res/values-kn/strings.xml +++ b/packages/SystemUI/res/values-kn/strings.xml @@ -416,10 +416,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"ಸ್ಕ್ರೀನ್ ರೆಕಾರ್ಡ್"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"ಪ್ರಾರಂಭಿಸಿ"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"ನಿಲ್ಲಿಸಿ"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"ಮುಂದುವರಿಯಲು, <b><xliff:g id="APP">%s</xliff:g></b> ಗೆ ನಿಮ್ಮ ಸಾಧನದ ಮೈಕ್ರೋಫೋನ್ನ ಪ್ರವೇಶದ ಅಗತ್ಯವಿದೆ."</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"ಮುಂದುವರಿಯಲು, <b><xliff:g id="APP">%s</xliff:g></b> ಗೆ ನಿಮ್ಮ ಸಾಧನದ ಕ್ಯಾಮರಾದ ಪ್ರವೇಶದ ಅಗತ್ಯವಿದೆ."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"ಸಾಧನ"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"ಅಪ್ಲಿಕೇಶನ್ಗಳನ್ನು ಬದಲಾಯಿಸಲು ಸ್ವೈಪ್ ಮಾಡಿ"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"ಅಪ್ಲಿಕೇಶನ್ಗಳನ್ನು ಬದಲಿಸಲು ತ್ವರಿತವಾಗಿ ಬಲಕ್ಕೆ ಡ್ರ್ಯಾಗ್ ಮಾಡಿ"</string> @@ -442,8 +440,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"ತೆರೆಯಲು ಮತ್ತೆ ಟ್ಯಾಪ್ ಮಾಡಿ"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"ತೆರೆಯಲು ಮೇಲಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ"</string> <string name="keyguard_retry" msgid="886802522584053523">"ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಲು ಮೇಲಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC ಬಳಸಲು ಅನ್ಲಾಕ್ ಮಾಡಿ"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"ಈ ಸಾಧನವು ನಿಮ್ಮ ಸಂಸ್ಥೆಗೆ ಸೇರಿದೆ"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"ಈ ಸಾಧನವು <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> ಗೆ ಸೇರಿದೆ"</string> <string name="phone_hint" msgid="6682125338461375925">"ಫೋನ್ಗಾಗಿ ಐಕಾನ್ನಿಂದ ಸ್ವೈಪ್ ಮಾಡಿ"</string> @@ -970,6 +967,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"ನಿಮ್ಮ <xliff:g id="TYPES_LIST">%s</xliff:g> ಅನ್ನು ಆ್ಯಪ್ಗಳು ಬಳಸುತ್ತಿವೆ."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" ಮತ್ತು "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g>, <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> ಅನ್ನು ಬಳಸುತ್ತಿದೆ"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> ಇತ್ತೀಚೆಗೆ <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> ಅನ್ನು ಬಳಸಿದೆ"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(ಎಂಟರ್ಪ್ರೈಸ್)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"ಫೋನ್ ಕರೆ"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(<xliff:g id="ATTRIBUTION">%s</xliff:g> ಮೂಲಕ)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"ಕ್ಯಾಮರಾ"</string> <string name="privacy_type_location" msgid="7991481648444066703">"ಸ್ಥಳ"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"ಮೈಕ್ರೋಫೋನ್"</string> diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml index 2b6e2d556864..362c0bc08707 100644 --- a/packages/SystemUI/res/values-ko/strings.xml +++ b/packages/SystemUI/res/values-ko/strings.xml @@ -416,10 +416,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"화면 녹화"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"시작"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"중지"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"계속하려면 <b><xliff:g id="APP">%s</xliff:g></b>에서 기기 마이크에 액세스해야 합니다."</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"계속하려면 <b><xliff:g id="APP">%s</xliff:g></b>에서 기기 카메라에 액세스해야 합니다."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"기기"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"위로 스와이프하여 앱 전환"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"앱을 빠르게 전환하려면 오른쪽으로 드래그"</string> @@ -442,8 +440,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"다시 탭하여 열기"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"위로 스와이프하여 열기"</string> <string name="keyguard_retry" msgid="886802522584053523">"위로 스와이프하여 다시 시도해 주세요"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"잠금 해제하여 NFC 사용"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"내 조직에 속한 기기입니다."</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"<xliff:g id="ORGANIZATION_NAME">%s</xliff:g>에 속한 기기입니다."</string> <string name="phone_hint" msgid="6682125338461375925">"전화 기능을 사용하려면 아이콘에서 스와이프하세요."</string> @@ -970,6 +967,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"애플리케이션이 <xliff:g id="TYPES_LIST">%s</xliff:g>을(를) 사용 중입니다."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" 및 "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g>에서 <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> 사용 중"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g>에서 최근에 <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>을(를) 사용함"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(기업용)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"전화 통화"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(<xliff:g id="ATTRIBUTION">%s</xliff:g> 사용)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"카메라"</string> <string name="privacy_type_location" msgid="7991481648444066703">"위치"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"마이크"</string> diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml index ffb66f945d63..fe69443c069a 100644 --- a/packages/SystemUI/res/values-ky/strings.xml +++ b/packages/SystemUI/res/values-ky/strings.xml @@ -418,10 +418,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Экранды жаздыруу"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Баштадык"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Токтотуу"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"Улантуу үчүн <b><xliff:g id="APP">%s</xliff:g></b> колдонмосуна түзмөгүңүздүн микрофонун пайдаланууга уруксат беришиңиз керек."</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"Улантуу үчүн <b><xliff:g id="APP">%s</xliff:g></b> колдонмосуна түзмөгүңүздүн камерасын пайдаланууга уруксат беришиңиз керек."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"Түзмөк"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Башка колдонмого которулуу үчүн,, өйдө сүрүңүз"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Колдонмолорду тез которуштуруу үчүн, оңго сүйрөңүз"</string> @@ -444,8 +442,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"Ачуу үчүн кайра таптап коюңуз"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"Ачуу үчүн өйдө сүрүңүз"</string> <string name="keyguard_retry" msgid="886802522584053523">"Кайталоо үчүн экранды өйдө сүрүңүз"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC технологиясын колдонуу үчүн кулпуcун ачыңыз"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Бул түзмөк уюмуңузга таандык"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Бул түзмөк төмөнкүгө таандык: <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> <string name="phone_hint" msgid="6682125338461375925">"Сүрөтчөнү серпип телефонго өтүңүз"</string> @@ -972,6 +969,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Колдонмолор төмөнкүлөрдү пайдаланып жатышат: <xliff:g id="TYPES_LIST">%s</xliff:g>."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" жана "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> колдонуп жатат"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"Жакында <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> колдонулду"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(корпоративдик)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Телефон чалуу"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(<xliff:g id="ATTRIBUTION">%s</xliff:g> аркылуу)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"камера"</string> <string name="privacy_type_location" msgid="7991481648444066703">"жайгашкан жер"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"микрофон"</string> diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml index 6e367a123b52..e5e89e44b4df 100644 --- a/packages/SystemUI/res/values-lo/strings.xml +++ b/packages/SystemUI/res/values-lo/strings.xml @@ -416,10 +416,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"ການບັນທຶກໜ້າຈໍ"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"ເລີ່ມ"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"ຢຸດ"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"ເພື່ອດຳເນີນການຕໍ່, <b><xliff:g id="APP">%s</xliff:g></b> ຕ້ອງການສິດເຂົ້າເຖິງໄມໂຄຣໂຟນອຸປະກອນຂອງທ່ານ."</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"ເພື່ອດຳເນີນການຕໍ່, <b><xliff:g id="APP">%s</xliff:g></b> ຕ້ອງການສິດເຂົ້າເຖິງກ້ອງຖ່າຍຮູບຂອງອຸປະກອນທ່ານ."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"ອຸປະກອນ"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"ປັດຂື້ນເພື່ອສະຫຼັບແອັບ"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"ລາກໄປຂວາເພື່ອສະຫຼັບແອັບດ່ວນ"</string> @@ -442,8 +440,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"ແຕະອີກຄັ້ງເພື່ອເປີດ"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"ປັດຂຶ້ນເພື່ອເປີດ"</string> <string name="keyguard_retry" msgid="886802522584053523">"ປັດຂຶ້ນເພື່ອລອງໃໝ່"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"ປົດລັອກເພື່ອໃຊ້ NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"ອຸປະກອນນີ້ເປັນຂອງອົງການທ່ານ"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"ອຸປະກອນນີ້ເປັນຂອງ <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> <string name="phone_hint" msgid="6682125338461375925">"ປັດຈາກໄອຄອນສຳລັບໂທລະສັບ"</string> @@ -970,6 +967,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"ແອັບພລິເຄຊັນກຳລັງໃຊ້ <xliff:g id="TYPES_LIST">%s</xliff:g> ຂອງທ່ານ."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" ແລະ "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> ກຳລັງໃຊ້ <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> ຢູ່"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> ໃຊ້ <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> ເມື່ອບໍ່ດົນມານີ້"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(ອົງກອນ)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"ໂທລະສັບ"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(ຜ່ານ <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"ກ້ອງຖ່າຍຮູບ"</string> <string name="privacy_type_location" msgid="7991481648444066703">"ສະຖານທີ່"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"ໄມໂຄຣໂຟນ"</string> diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml index 34275f4a0228..a5de09533f23 100644 --- a/packages/SystemUI/res/values-lt/strings.xml +++ b/packages/SystemUI/res/values-lt/strings.xml @@ -420,10 +420,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Ekrano įrašas"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Pradėti"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Stabdyti"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"Kad būtų galima tęsti, <b><xliff:g id="APP">%s</xliff:g></b> reikalinga prieiga prie įrenginio mikrofono."</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"Kad būtų galima tęsti, <b><xliff:g id="APP">%s</xliff:g></b> reikalinga prieiga prie įrenginio fotoaparato."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"Įrenginys"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Perbraukite aukštyn, kad perjungtumėte programas"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Vilkite į dešinę, kad greitai perjungtumėte programas"</string> @@ -446,8 +444,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"Palieskite dar kartą, kad atidarytumėte"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"Perbraukite aukštyn, kad atidarytumėte"</string> <string name="keyguard_retry" msgid="886802522584053523">"Jei norite bandyti dar kartą, perbraukite aukštyn"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Norėdami naudoti NFC, atrakinkite"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Šis įrenginys priklauso jūsų organizacijai"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Šis įrenginys priklauso „<xliff:g id="ORGANIZATION_NAME">%s</xliff:g>“"</string> <string name="phone_hint" msgid="6682125338461375925">"Perbraukite iš telefono piktogramos"</string> @@ -980,6 +977,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Programos naudoja: <xliff:g id="TYPES_LIST">%s</xliff:g>."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" ir "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"Programa „<xliff:g id="APPLICATION_NAME">%1$s</xliff:g>“ naudoja: <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"Programa „<xliff:g id="APPLICATION_NAME">%1$s</xliff:g>“ neseniai naudojo: <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(įmonės versija)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Telefono skambutis"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(naud. <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"fotoaparatą"</string> <string name="privacy_type_location" msgid="7991481648444066703">"vietovę"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofoną"</string> diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml index 2d427b748b57..019810fe9f84 100644 --- a/packages/SystemUI/res/values-lv/strings.xml +++ b/packages/SystemUI/res/values-lv/strings.xml @@ -418,10 +418,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Ekrāna ierakstīšana"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Sākt"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Apturēt"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"Lai turpinātu, lietotnei <b><xliff:g id="APP">%s</xliff:g></b> nepieciešama piekļuve jūsu ierīces mikrofonam."</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"Lai turpinātu, lietotnei <b><xliff:g id="APP">%s</xliff:g></b> nepieciešama piekļuve jūsu ierīces kamerai."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"Ierīce"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Velciet augšup, lai pārslēgtu lietotnes"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Lai ātri pārslēgtu lietotnes, velciet pa labi"</string> @@ -444,8 +442,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"Pieskarieties vēlreiz, lai atvērtu"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"Velciet augšup, lai atvērtu"</string> <string name="keyguard_retry" msgid="886802522584053523">"Velciet augšup, lai mēģinātu vēlreiz"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Atbloķējiet ierīci, lai izmantotu NFC."</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Šī ierīce pieder jūsu organizācijai."</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Šī ierīce pieder organizācijai <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>."</string> <string name="phone_hint" msgid="6682125338461375925">"Lai lietotu tālruni, velciet no ikonas"</string> @@ -975,6 +972,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Lietojumprogrammas izmanto šādas funkcijas: <xliff:g id="TYPES_LIST">%s</xliff:g>."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" un "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> pašlaik izmanto šādu darbību: <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> nesen izmantoja šādu darbību: <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(uzņēmumiem)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Tālruņa zvaniem"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(izmantojot lietotni <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"kamera"</string> <string name="privacy_type_location" msgid="7991481648444066703">"atrašanās vieta"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofons"</string> diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml index 17d6e10a7d6f..c124eefb52cd 100644 --- a/packages/SystemUI/res/values-mk/strings.xml +++ b/packages/SystemUI/res/values-mk/strings.xml @@ -416,10 +416,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Снимање екран"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Започни"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Сопри"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"За да продолжи, на <b><xliff:g id="APP">%s</xliff:g></b> ѝ е потребен пристап до микрофонот на уредот."</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"За да продолжи, на <b><xliff:g id="APP">%s</xliff:g></b> ѝ е потребен пристап до камерата на уредот."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"Уред"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Повлечете нагоре за да се префрлите од една на друга апликација"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Повлечете надесно за брзо префрлање меѓу апликациите"</string> @@ -442,8 +440,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"Допрете повторно за да се отвори"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"Повлечете за да отворите"</string> <string name="keyguard_retry" msgid="886802522584053523">"Повлечете нагоре за да се обидете повторно"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Отклучете за да користите NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Уредов е во сопственост на организацијата"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Уредов е во сопственост на <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> <string name="phone_hint" msgid="6682125338461375925">"Повлечете од иконата за телефонот"</string> @@ -970,6 +967,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Апликациите користат <xliff:g id="TYPES_LIST">%s</xliff:g>."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" и "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> користи <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> користеше <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> неодамна"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(претпријатие)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Телефонски повик"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(преку <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"камера"</string> <string name="privacy_type_location" msgid="7991481648444066703">"локација"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"микрофон"</string> diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml index 916fbe1103bf..965f4df71d7f 100644 --- a/packages/SystemUI/res/values-ml/strings.xml +++ b/packages/SystemUI/res/values-ml/strings.xml @@ -416,10 +416,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"സ്ക്രീൻ റെക്കോർഡ്"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"ആരംഭിക്കുക"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"നിര്ത്തുക"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"തുടരാൻ, <b><xliff:g id="APP">%s</xliff:g></b> ആപ്പിന് നിങ്ങളുടെ ഉപകരണത്തിന്റെ മൈക്രോഫോണിലേക്ക് ആക്സസ് നൽകേണ്ടതുണ്ട്."</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"തുടരാൻ, <b><xliff:g id="APP">%s</xliff:g></b> ആപ്പിന് നിങ്ങളുടെ ഉപകരണത്തിന്റെ ക്യാമറയിലേക്ക് ആക്സസ് നൽകേണ്ടതുണ്ട്."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"ഉപകരണം"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"ആപ്പുകൾ മാറാൻ മുകളിലേക്ക് സ്വൈപ്പ് ചെയ്യുക"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"ആപ്പുകൾ പെട്ടെന്ന് മാറാൻ വലത്തോട്ട് വലിച്ചിടുക"</string> @@ -442,8 +440,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"തുറക്കുന്നതിന് വീണ്ടും ടാപ്പുചെയ്യുക"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"തുറക്കാൻ മുകളിലോട്ട് സ്വൈപ്പ് ചെയ്യുക"</string> <string name="keyguard_retry" msgid="886802522584053523">"വീണ്ടും ശ്രമിക്കാൻ മുകളിലേക്ക് സ്വൈപ്പ് ചെയ്യുക"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC ഉപയോഗിക്കാൻ അൺലോക്ക് ചെയ്യുക"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"ഈ ഉപകരണം നിങ്ങളുടെ സ്ഥാപനത്തിന്റേതാണ്"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"ഈ ഉപകരണം <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> എന്ന സ്ഥാപനത്തിന്റേതാണ്"</string> <string name="phone_hint" msgid="6682125338461375925">"ഫോൺ ഐക്കണിൽ നിന്ന് സ്വൈപ്പുചെയ്യുക"</string> @@ -970,6 +967,16 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"ആപ്പുകൾ നിങ്ങളുടെ <xliff:g id="TYPES_LIST">%s</xliff:g> ഉപയോഗിക്കുന്നു."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" കൂടാതെ "</string> + <!-- no translation found for ongoing_privacy_dialog_using_op (4125175620929701569) --> + <skip /> + <!-- no translation found for ongoing_privacy_dialog_recent_op (4255923947334262404) --> + <skip /> + <!-- no translation found for ongoing_privacy_dialog_enterprise (4082735415905550729) --> + <skip /> + <!-- no translation found for ongoing_privacy_dialog_phonecall (3526223335298089311) --> + <skip /> + <!-- no translation found for ongoing_privacy_dialog_attribution_text (9186683306719924646) --> + <skip /> <string name="privacy_type_camera" msgid="7974051382167078332">"ക്യാമറ"</string> <string name="privacy_type_location" msgid="7991481648444066703">"ലൊക്കേഷന്"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"മൈക്രോഫോൺ"</string> diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml index 38bb386f9ca1..400352b6473a 100644 --- a/packages/SystemUI/res/values-mn/strings.xml +++ b/packages/SystemUI/res/values-mn/strings.xml @@ -416,10 +416,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Дэлгэцийн бичлэг хийх"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Эхлүүлэх"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Зогсоох"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"Үргэлжлүүлэхийн тулд <b><xliff:g id="APP">%s</xliff:g></b> таны төхөөрөмжийн микрофонд хандах шаардлагатай."</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"Үргэлжлүүлэхийн тулд <b><xliff:g id="APP">%s</xliff:g></b> таны төхөөрөмжийн камерт хандах шаардлагатай."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"Төхөөрөмж"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Апп сэлгэхийн тулд дээш шударна уу"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Аппуудыг хурдан сэлгэхийн тулд баруун тийш чирнэ үү"</string> @@ -442,8 +440,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"Нээхийн тулд дахин товшино уу"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"Нээхийн тулд дээш шударна уу"</string> <string name="keyguard_retry" msgid="886802522584053523">"Дахин оролдохын тулд дээш шударна уу"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC-г ашиглахын тулд түгжээг тайлна уу"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Энэ төхөөрөмж танай байгууллагад харьяалагддаг"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Энэ төхөөрөмж <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>-д харьяалагддаг"</string> <string name="phone_hint" msgid="6682125338461375925">"Утсыг гаргахын тулд дүрс тэмдгээс шудрах"</string> @@ -970,6 +967,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Аппууд таны <xliff:g id="TYPES_LIST">%s</xliff:g>-г ашиглаж байна."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" болон "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>-г ашиглаж байна"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>-г саяхан ашигласан"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(байгууллага)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Утасны дуудлага"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(<xliff:g id="ATTRIBUTION">%s</xliff:g>-р)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"камер"</string> <string name="privacy_type_location" msgid="7991481648444066703">"байршил"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"микрофон"</string> diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml index 1c9cbd2ba6a8..fe1c910c74ed 100644 --- a/packages/SystemUI/res/values-mr/strings.xml +++ b/packages/SystemUI/res/values-mr/strings.xml @@ -344,10 +344,8 @@ <string name="quick_settings_ime_label" msgid="3351174938144332051">"इनपुट पद्धत"</string> <string name="quick_settings_location_label" msgid="2621868789013389163">"स्थान"</string> <string name="quick_settings_location_off_label" msgid="7923929131443915919">"स्थान बंद"</string> - <!-- no translation found for quick_settings_camera_label (1367149596242401934) --> - <skip /> - <!-- no translation found for quick_settings_mic_label (8245831073612564953) --> - <skip /> + <string name="quick_settings_camera_label" msgid="1367149596242401934">"कॅमेरा ब्लॉक करा"</string> + <string name="quick_settings_mic_label" msgid="8245831073612564953">"मायक्रोफोन म्यूट करा"</string> <string name="quick_settings_media_device_label" msgid="8034019242363789941">"मीडिया डिव्हाइस"</string> <string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string> <string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"फक्त आणीबाणीचे कॉल"</string> @@ -418,10 +416,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"स्क्रीन रेकॉर्ड"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"सुरू"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"थांबा"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"पुढे सुरू ठेवण्यासाठी, <b><xliff:g id="APP">%s</xliff:g></b> ला तुमच्या डिव्हाइसचा मायक्रोफोन अॅक्सेस करण्याची आवश्यकता आहे."</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"पुढे सुरू ठेवण्यासाठी, <b><xliff:g id="APP">%s</xliff:g></b> ला तुमच्या डिव्हाइसचा कॅमेरा अॅक्सेस करण्याची आवश्यकता आहे."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"डिव्हाइस"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"अॅप्स स्विच करण्यासाठी वर स्वाइप करा"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"अॅप्स वर झटपट स्विच करण्यासाठी उजवीकडे ड्रॅग करा"</string> @@ -444,8 +440,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"उघडण्यासाठी पुन्हा टॅप करा"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"उघडण्यासाठी वर स्वाइप करा"</string> <string name="keyguard_retry" msgid="886802522584053523">"पुन्हा प्रयत्न करण्यासाठी वर स्वाइप करा"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC वापरण्यासाठी स्क्रीन अनलॉक करा"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"हे डिव्हाइस तुमच्या संस्थेचे आहे"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"हे डिव्हाइस <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> चे आहे"</string> <string name="phone_hint" msgid="6682125338461375925">"फोनसाठी चिन्हावरून स्वाइप करा"</string> @@ -972,6 +967,16 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"ॲप्लिकेशन्स तुमचे <xliff:g id="TYPES_LIST">%s</xliff:g> वापरत आहे."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" आणि "</string> + <!-- no translation found for ongoing_privacy_dialog_using_op (4125175620929701569) --> + <skip /> + <!-- no translation found for ongoing_privacy_dialog_recent_op (4255923947334262404) --> + <skip /> + <!-- no translation found for ongoing_privacy_dialog_enterprise (4082735415905550729) --> + <skip /> + <!-- no translation found for ongoing_privacy_dialog_phonecall (3526223335298089311) --> + <skip /> + <!-- no translation found for ongoing_privacy_dialog_attribution_text (9186683306719924646) --> + <skip /> <string name="privacy_type_camera" msgid="7974051382167078332">"कॅमेरा"</string> <string name="privacy_type_location" msgid="7991481648444066703">"स्थान"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"मायक्रोफोन"</string> diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml index 4751f409c870..b1d0b4748b85 100644 --- a/packages/SystemUI/res/values-ms/strings.xml +++ b/packages/SystemUI/res/values-ms/strings.xml @@ -416,10 +416,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Rakam Skrin"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Mula"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Berhenti"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"Untuk meneruskan proses, <b><xliff:g id="APP">%s</xliff:g></b> memerlukan akses kepada mikrofon peranti anda."</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"Untuk meneruskan proses, <b><xliff:g id="APP">%s</xliff:g></b> memerlukan akses kepada kamera peranti anda."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"Peranti"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Leret ke atas untuk menukar apl"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Seret ke kanan untuk beralih apl dengan pantas"</string> @@ -442,8 +440,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"Ketik lagi untuk membuka"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"Leret ke atas untuk buka"</string> <string name="keyguard_retry" msgid="886802522584053523">"Leret ke atas untuk mencuba lagi"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Buka kunci untuk menggunakan NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Peranti ini milik organisasi anda"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Peranti ini milik <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> <string name="phone_hint" msgid="6682125338461375925">"Leret dari ikon untuk telefon"</string> @@ -970,6 +967,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Aplikasi sedang menggunakan <xliff:g id="TYPES_LIST">%s</xliff:g> anda."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" dan "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> sedang menggunakan <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> menggunakan <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> baru-baru ini"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(perusahaan)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Panggilan telefon"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(melalui <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"kamera"</string> <string name="privacy_type_location" msgid="7991481648444066703">"lokasi"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofon"</string> diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml index abd2b2338d59..42b5b230eb6f 100644 --- a/packages/SystemUI/res/values-my/strings.xml +++ b/packages/SystemUI/res/values-my/strings.xml @@ -416,10 +416,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"ဖန်သားပြင် မှတ်တမ်းတင်ရန်"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"စတင်ရန်"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"ရပ်ရန်"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"ဆက်လက်လုပ်ဆောင်ရန် <b><xliff:g id="APP">%s</xliff:g></b> က သင့်စက်၏ မိုက်ခရိုဖုန်းကို အသုံးပြုခွင့်ရရန် လိုအပ်သည်။"</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"ဆက်လက်လုပ်ဆောင်ရန် <b><xliff:g id="APP">%s</xliff:g></b> က သင့်စက်၏ ကင်မရာကို အသုံးပြုခွင့်ရရန် လိုအပ်သည်။"</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"စက်"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"အက်ပ်များကို ဖွင့်ရန် အပေါ်သို့ ပွတ်ဆွဲပါ"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"အက်ပ်များကို ပြောင်းရန် ညာဘက်သို့ ဖိဆွဲပါ"</string> @@ -442,8 +440,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"ဖွင့်ရန် ထပ်ပြီး ပုတ်ပါ"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"ဖွင့်ရန် အပေါ်သို့ပွတ်ဆွဲပါ"</string> <string name="keyguard_retry" msgid="886802522584053523">"ထပ်စမ်းကြည့်ရန် အပေါ်သို့ပွတ်ဆွဲပါ"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC ကို အသုံးပြုရန် လော့ခ်ဖွင့်ပါ"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"ဤစက်ကို သင့်အဖွဲ့အစည်းက ပိုင်ဆိုင်သည်"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"ဤစက်ကို <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> က ပိုင်ဆိုင်သည်"</string> <string name="phone_hint" msgid="6682125338461375925">"ဖုန်းအတွက် သင်္ကေတပုံအား ပွတ်ဆွဲပါ"</string> @@ -970,6 +967,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"အပလီကေးရှင်းများက သင်၏ <xliff:g id="TYPES_LIST">%s</xliff:g> ကို အသုံးပြုနေသည်။"</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">"၊ "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" နှင့် "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> က <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> ကို အသုံးပြုနေသည်"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> က <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> ကို မကြာသေးမီက အသုံးပြုထားသည်"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(လုပ်ငန်းသုံး)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"ဖုန်းခေါ်ဆိုမှု"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(<xliff:g id="ATTRIBUTION">%s</xliff:g> မှတစ်ဆင့်)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"ကင်မရာ"</string> <string name="privacy_type_location" msgid="7991481648444066703">"တည်နေရာ"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"မိုက်ခရိုဖုန်း"</string> diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml index e914399d5f8a..ef48f8fb37c5 100644 --- a/packages/SystemUI/res/values-nb/strings.xml +++ b/packages/SystemUI/res/values-nb/strings.xml @@ -416,10 +416,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Skjermopptak"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Start"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Stopp"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"For å fortsette må <b><xliff:g id="APP">%s</xliff:g></b> ha tilgang til enhetsmikrofonen."</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"For å fortsette må <b><xliff:g id="APP">%s</xliff:g></b> ha tilgang til enhetskameraet."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"Enhet"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Sveip opp for å bytte apper"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Dra til høyre for å bytte apper raskt"</string> @@ -442,8 +440,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"Trykk på nytt for å åpne"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"Sveip opp for å åpne"</string> <string name="keyguard_retry" msgid="886802522584053523">"Sveip opp for å prøve igjen"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Lås opp for å bruke NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Denne enheten tilhører organisasjonen din"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Denne enheten tilhører <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> <string name="phone_hint" msgid="6682125338461375925">"Sveip ikonet for å åpne telefon"</string> @@ -970,6 +967,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Apper bruker <xliff:g id="TYPES_LIST">%s</xliff:g>."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" og "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> bruker <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> har brukt <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> nylig"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(enterprise)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Telefonsamtale"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(til og med <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"kamera"</string> <string name="privacy_type_location" msgid="7991481648444066703">"posisjon"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofon"</string> diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml index ad087c5e2ceb..2594e8c923dd 100644 --- a/packages/SystemUI/res/values-ne/strings.xml +++ b/packages/SystemUI/res/values-ne/strings.xml @@ -416,10 +416,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"स्रिनको रेकर्ड"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"सुरु गर्नुहोस्"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"रोक्नुहोस्"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"जारी राख्न <b><xliff:g id="APP">%s</xliff:g></b> लाई तपाईंको यन्त्रको माइक्रोफोन प्रयोग गर्ने अनुमति दिनु पर्ने हुन्छ।"</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"जारी राख्न <b><xliff:g id="APP">%s</xliff:g></b> लाई तपाईंको यन्त्रको क्यामेरा प्रयोग गर्ने अनुमति दिनु पर्ने हुन्छ।"</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"यन्त्र"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"एपहरू बदल्न माथितिर स्वाइप गर्नुहोस्"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"एपहरू बदल्न द्रुत गतिमा दायाँतिर ड्र्याग गर्नुहोस्"</string> @@ -442,8 +440,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"खोल्न पुनः ट्याप गर्नुहोस्"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"खोल्न माथितिर स्वाइप गर्नुहोस्"</string> <string name="keyguard_retry" msgid="886802522584053523">"फेरि प्रयास गर्न माथितिर स्वाइप गर्नुहोस्"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC प्रयोग गर्न स्क्रिन अनलक गर्नुहोस्"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"यो यन्त्र तपाईंको सङ्गठनको स्वामित्वमा छ"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"यो यन्त्र <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> को स्वामित्वमा छ"</string> <string name="phone_hint" msgid="6682125338461375925">"फोनको लागि आइकनबाट स्वाइप गर्नुहोस्"</string> @@ -970,6 +967,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"एपहरूले तपाईंको <xliff:g id="TYPES_LIST">%s</xliff:g> प्रयोग गर्दै छन्।"</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" र "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> ले <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> प्रयोग गरिरहेको छ"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> ले हालसालै <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> प्रयोग गरेको छ"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(इन्टरप्राइज)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"फोन कल"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(<xliff:g id="ATTRIBUTION">%s</xliff:g> मार्फत)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"क्यामेरा"</string> <string name="privacy_type_location" msgid="7991481648444066703">"स्थान"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"माइक्रोफोन"</string> diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml index 614d37413962..02741322f5ac 100644 --- a/packages/SystemUI/res/values-nl/strings.xml +++ b/packages/SystemUI/res/values-nl/strings.xml @@ -416,10 +416,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Schermopname"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Starten"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Stoppen"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"<b><xliff:g id="APP">%s</xliff:g></b> heeft toegang tot de microfoon van je apparaat nodig om door te gaan."</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"<b><xliff:g id="APP">%s</xliff:g></b> heeft toegang tot de camera van je apparaat nodig om door te gaan."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"Apparaat"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Swipe omhoog om te schakelen tussen apps"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Sleep naar rechts om snel tussen apps te schakelen"</string> @@ -442,8 +440,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"Tik nog eens om te openen"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"Swipe omhoog om te openen"</string> <string name="keyguard_retry" msgid="886802522584053523">"Swipe omhoog om het opnieuw te proberen"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Ontgrendel het apparaat om NFC te gebruiken"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Dit apparaat is eigendom van je organisatie"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Dit apparaat is eigendom van <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> <string name="phone_hint" msgid="6682125338461375925">"Swipen voor telefoon"</string> @@ -970,6 +967,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Apps gebruiken je <xliff:g id="TYPES_LIST">%s</xliff:g>."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" en "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> gebruikt de <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> heeft de <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> recent gebruikt"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(zakelijke versie)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Telefoongesprek"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(via <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"camera"</string> <string name="privacy_type_location" msgid="7991481648444066703">"locatie"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"microfoon"</string> diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml index 97af29b38301..16d8a2969e27 100644 --- a/packages/SystemUI/res/values-or/strings.xml +++ b/packages/SystemUI/res/values-or/strings.xml @@ -416,10 +416,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"ସ୍କ୍ରିନ୍ ରେକର୍ଡ"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"ଆରମ୍ଭ କରନ୍ତୁ"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"ବନ୍ଦ କରନ୍ତୁ"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"ଜାରି ରଖିବାକୁ, <b><xliff:g id="APP">%s</xliff:g></b> ଆପଣଙ୍କ ଡିଭାଇସର ମାଇକ୍ରୋଫୋନକୁ ଆକ୍ସେସ୍ ଆବଶ୍ୟକ କରେ।"</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"ଜାରି ରଖିବାକୁ, <b><xliff:g id="APP">%s</xliff:g></b> ଆପଣଙ୍କ ଡିଭାଇସର କ୍ୟାମେରାକୁ ଆକ୍ସେସ୍ ଆବଶ୍ୟକ କରେ।"</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"ଡିଭାଇସ୍"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"ଆପ୍କୁ ବଦଳ କରିବା ପାଇଁ ସ୍ଵାଇପ୍ କରନ୍ତୁ"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"ଆପ୍ଗୁଡ଼ିକ ମଧ୍ୟରେ ଶୀଘ୍ର ବଦଳ କରିବା ପାଇଁ ଡାହାଣକୁ ଡ୍ରାଗ୍ କରନ୍ତୁ"</string> @@ -442,8 +440,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"ଖୋଲିବା ପାଇଁ ପୁଣି ଟାପ୍ କରନ୍ତୁ"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"ଖୋଲିବା ପାଇଁ ଉପରକୁ ସ୍ୱାଇପ୍ କରନ୍ତୁ"</string> <string name="keyguard_retry" msgid="886802522584053523">"ପୁଣି ଚେଷ୍ଟା କରିବା ପାଇଁ ଉପରକୁ ସ୍ୱାଇପ୍ କରନ୍ତୁ"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC ବ୍ୟବହାର କରିବାକୁ ଅନଲକ୍ କରନ୍ତୁ"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"ଏହି ଡିଭାଇସଟି ଆପଣଙ୍କ ସଂସ୍ଥାର ଅଟେ"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"ଏହି ଡିଭାଇସଟି <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>ର ଅଟେ"</string> <string name="phone_hint" msgid="6682125338461375925">"ଫୋନ୍ ପାଇଁ ଆଇକନରୁ ସ୍ୱାଇପ୍ କରନ୍ତୁ"</string> @@ -970,6 +967,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"ଆପ୍ଲିକେସନ୍ଗୁଡିକ ଆପଣଙ୍କ <xliff:g id="TYPES_LIST">%s</xliff:g> ବ୍ୟବହାର କରୁଛନ୍ତି।"</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" ଏବଂ "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> ବ୍ୟବହାର କରୁଛି"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> ଏବେ <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> ବ୍ୟବହାର କରିଛି"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(ଏଣ୍ଟରପ୍ରାଇଜ୍)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"ଫୋନକଲ୍"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(<xliff:g id="ATTRIBUTION">%s</xliff:g> ମାଧ୍ୟମରେ)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"କ୍ୟାମେରା"</string> <string name="privacy_type_location" msgid="7991481648444066703">"ଲୋକେସନ୍"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"ମାଇକ୍ରୋଫୋନ୍"</string> diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml index e7ffe492c196..d33455d2c82c 100644 --- a/packages/SystemUI/res/values-pa/strings.xml +++ b/packages/SystemUI/res/values-pa/strings.xml @@ -344,10 +344,8 @@ <string name="quick_settings_ime_label" msgid="3351174938144332051">"ਇਨਪੁੱਟ ਵਿਧੀ"</string> <string name="quick_settings_location_label" msgid="2621868789013389163">"ਟਿਕਾਣਾ"</string> <string name="quick_settings_location_off_label" msgid="7923929131443915919">"ਨਿਰਧਾਰਿਤ ਸਥਾਨ ਬੰਦ"</string> - <!-- no translation found for quick_settings_camera_label (1367149596242401934) --> - <skip /> - <!-- no translation found for quick_settings_mic_label (8245831073612564953) --> - <skip /> + <string name="quick_settings_camera_label" msgid="1367149596242401934">"ਕੈਮਰਾ ਬਲਾਕ ਕਰੋ"</string> + <string name="quick_settings_mic_label" msgid="8245831073612564953">"ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਮਿਊਟ ਕਰੋ"</string> <string name="quick_settings_media_device_label" msgid="8034019242363789941">"ਮੀਡੀਆ ਡੀਵਾਈਸ"</string> <string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string> <string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"ਸਿਰਫ਼ ਸੰਕਟਕਾਲੀਨ ਕਾਲਾਂ"</string> @@ -418,10 +416,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"ਸਕ੍ਰੀਨ ਰਿਕਾਰਡਰ"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"ਸ਼ੁਰੂ ਕਰੋ"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"ਰੋਕੋ"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"ਜਾਰੀ ਰੱਖਣ ਲਈ, <b><xliff:g id="APP">%s</xliff:g></b> ਨੂੰ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਤੱਕ ਪਹੁੰਚ ਦੀ ਲੋੜ ਹੈ।"</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"ਜਾਰੀ ਰੱਖਣ ਲਈ, <b><xliff:g id="APP">%s</xliff:g></b> ਨੂੰ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਦੇ ਕੈਮਰਾ ਤੱਕ ਪਹੁੰਚ ਦੀ ਲੋੜ ਹੈ।"</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"ਡੀਵਾਈਸ"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"ਐਪਾਂ ਵਿਚਾਲੇ ਅਦਲਾ-ਬਦਲੀ ਕਰਨ ਲਈ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰੋ"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"ਐਪਾਂ ਵਿਚਾਲੇ ਤੇਜ਼ੀ ਨਾਲ ਅਦਲਾ-ਬਦਲੀ ਕਰਨ ਲਈ ਸੱਜੇ ਪਾਸੇ ਵੱਲ ਘਸੀਟੋ"</string> @@ -444,8 +440,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"ਖੋਲ੍ਹਣ ਲਈ ਦੁਬਾਰਾ ਟੈਪ ਕਰੋ"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"ਖੋਲ੍ਹਣ ਲਈ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰੋ"</string> <string name="keyguard_retry" msgid="886802522584053523">"ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰਨ ਲਈ ਉੱਤੇ ਵੱਲ ਸਵਾਈਪ ਕਰੋ"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC ਵਰਤਣ ਲਈ ਅਣਲਾਕ ਕਰੋ"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"ਇਹ ਡੀਵਾਈਸ ਤੁਹਾਡੀ ਸੰਸਥਾ ਨਾਲ ਸੰਬੰਧਿਤ ਹੈ"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"ਇਹ ਡੀਵਾਈਸ <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> ਨਾਲ ਸੰਬੰਧਿਤ ਹੈ"</string> <string name="phone_hint" msgid="6682125338461375925">"ਫ਼ੋਨ ਲਈ ਪ੍ਰਤੀਕ ਤੋਂ ਸਵਾਈਪ ਕਰੋ"</string> @@ -972,6 +967,16 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"ਐਪਲੀਕੇਸ਼ਨਾਂ ਤੁਹਾਡੇ <xliff:g id="TYPES_LIST">%s</xliff:g> ਦੀ ਵਰਤੋਂ ਕਰ ਰਹੀਆਂ ਹਨ।"</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" ਅਤੇ "</string> + <!-- no translation found for ongoing_privacy_dialog_using_op (4125175620929701569) --> + <skip /> + <!-- no translation found for ongoing_privacy_dialog_recent_op (4255923947334262404) --> + <skip /> + <!-- no translation found for ongoing_privacy_dialog_enterprise (4082735415905550729) --> + <skip /> + <!-- no translation found for ongoing_privacy_dialog_phonecall (3526223335298089311) --> + <skip /> + <!-- no translation found for ongoing_privacy_dialog_attribution_text (9186683306719924646) --> + <skip /> <string name="privacy_type_camera" msgid="7974051382167078332">"ਕੈਮਰਾ"</string> <string name="privacy_type_location" msgid="7991481648444066703">"ਟਿਕਾਣਾ"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"ਮਾਈਕ੍ਰੋਫ਼ੋਨ"</string> diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml index 0275626b0a34..6440a65a9eaf 100644 --- a/packages/SystemUI/res/values-pl/strings.xml +++ b/packages/SystemUI/res/values-pl/strings.xml @@ -420,10 +420,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Nagrywanie ekranu"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Rozpocznij"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Zatrzymaj"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"Aby kontynuować, musisz przyznać aplikacji „<xliff:g id="APP">%s</xliff:g>” dostęp do mikrofonu urządzenia."</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"Aby kontynuować, musisz przyznać aplikacji „<xliff:g id="APP">%s</xliff:g>” dostęp do aparatu urządzenia."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"Urządzenie"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Przesuń w górę, by przełączyć aplikacje"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Szybko przeciągnij w prawo, by przełączyć aplikacje"</string> @@ -446,8 +444,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"Kliknij ponownie, by otworzyć"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"Przesuń w górę, by otworzyć"</string> <string name="keyguard_retry" msgid="886802522584053523">"Przesuń w górę, by spróbować ponownie"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Odblokuj, by użyć NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"To urządzenie należy do Twojej organizacji"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Właściciel tego urządzenia: <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> <string name="phone_hint" msgid="6682125338461375925">"Aby włączyć telefon, przesuń palcem od ikony"</string> @@ -980,6 +977,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Aplikacje używają: <xliff:g id="TYPES_LIST">%s</xliff:g>."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" i "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"Aplikacja <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> używa: <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"Aplikacja <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> używała ostatnio: <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(wersja firmowa)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Rozmowa telefoniczna"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(przez: <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"aparat"</string> <string name="privacy_type_location" msgid="7991481648444066703">"lokalizacja"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofon"</string> diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml index b629b64fc2cf..40dc2de30ac4 100644 --- a/packages/SystemUI/res/values-pt-rBR/strings.xml +++ b/packages/SystemUI/res/values-pt-rBR/strings.xml @@ -967,6 +967,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Aplicativos estão usando <xliff:g id="TYPES_LIST">%s</xliff:g>."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" e "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"O app <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> está usando <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"O app <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> usou <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> recentemente"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(empresarial)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Chamada telefônica"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(pelo app <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"câmera"</string> <string name="privacy_type_location" msgid="7991481648444066703">"localização"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"microfone"</string> diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml index 43933a4b19f7..22241f8fc280 100644 --- a/packages/SystemUI/res/values-pt-rPT/strings.xml +++ b/packages/SystemUI/res/values-pt-rPT/strings.xml @@ -967,6 +967,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"As aplicações estão a utilizar o(a) <xliff:g id="TYPES_LIST">%s</xliff:g>."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" e "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"A app <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> está a utilizar a app <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>."</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"Recentemente, a app <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> utilizou a app <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>."</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(empresarial)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Chamada telefónica"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(através de <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"câmara"</string> <string name="privacy_type_location" msgid="7991481648444066703">"localização"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"microfone"</string> diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml index b629b64fc2cf..40dc2de30ac4 100644 --- a/packages/SystemUI/res/values-pt/strings.xml +++ b/packages/SystemUI/res/values-pt/strings.xml @@ -967,6 +967,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Aplicativos estão usando <xliff:g id="TYPES_LIST">%s</xliff:g>."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" e "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"O app <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> está usando <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"O app <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> usou <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> recentemente"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(empresarial)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Chamada telefônica"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(pelo app <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"câmera"</string> <string name="privacy_type_location" msgid="7991481648444066703">"localização"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"microfone"</string> diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml index 5197de3c061c..f32453b9a4d8 100644 --- a/packages/SystemUI/res/values-ro/strings.xml +++ b/packages/SystemUI/res/values-ro/strings.xml @@ -418,10 +418,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Înregistrarea ecranului"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Începeți"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Opriți"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"Pentru a continua, <b><xliff:g id="APP">%s</xliff:g></b> necesită acces la microfonul dispozitivului."</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"Pentru a continua, <b><xliff:g id="APP">%s</xliff:g></b> necesită acces la camera dispozitivului."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"Dispozitiv"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Glisați în sus pentru a comuta între aplicații"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Glisați la dreapta pentru a comuta rapid între aplicații"</string> @@ -444,8 +442,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"Atingeți din nou pentru a deschide"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"Glisați în sus pentru a deschide"</string> <string name="keyguard_retry" msgid="886802522584053523">"Glisați pentru a încerca din nou"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Deblocați pentru a folosi NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Dispozitivul aparține organizației dvs."</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Acest dispozitiv aparține organizației <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> <string name="phone_hint" msgid="6682125338461375925">"Glisați dinspre telefon"</string> @@ -975,6 +972,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Aplicațiile folosesc <xliff:g id="TYPES_LIST">%s</xliff:g>."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" și "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> folosește <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> a folosit recent <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(enterprise)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Phonecall"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(prin <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"cameră foto"</string> <string name="privacy_type_location" msgid="7991481648444066703">"locație"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"microfon"</string> diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml index 17221c9e4170..40fb25865a7c 100644 --- a/packages/SystemUI/res/values-ru/strings.xml +++ b/packages/SystemUI/res/values-ru/strings.xml @@ -420,10 +420,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Запись экрана"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Начать"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Остановить"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"Чтобы продолжить, предоставьте приложению <b><xliff:g id="APP">%s</xliff:g></b> доступ к микрофону устройства."</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"Чтобы продолжить, предоставьте приложению <b><xliff:g id="APP">%s</xliff:g></b> доступ к камере устройства."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"Устройство"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Чтобы переключиться между приложениями, проведите по экрану вверх."</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Перетащите вправо, чтобы быстро переключиться между приложениями"</string> @@ -446,8 +444,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"Нажмите ещё раз, чтобы открыть"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"Проведите вверх, чтобы открыть"</string> <string name="keyguard_retry" msgid="886802522584053523">"Чтобы повторить попытку, проведите вверх"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Чтобы использовать NFC, разблокируйте устройство."</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Это устройство принадлежит вашей организации"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Этим устройством владеет организация \"<xliff:g id="ORGANIZATION_NAME">%s</xliff:g>\""</string> <string name="phone_hint" msgid="6682125338461375925">"Телефон: проведите от значка"</string> @@ -980,6 +977,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"В приложениях используется <xliff:g id="TYPES_LIST">%s</xliff:g>."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" и "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"Приложение \"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g>\" использует другое (<xliff:g id="APP_OPP_NAME">%2$s</xliff:g>)."</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"Приложение \"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g>\" недавно использовало другое (<xliff:g id="APP_OPP_NAME">%2$s</xliff:g>)."</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(корпоративная версия)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Приложение для звонков"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(через приложение \"<xliff:g id="ATTRIBUTION">%s</xliff:g>\")"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"камера"</string> <string name="privacy_type_location" msgid="7991481648444066703">"местоположение"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"микрофон"</string> diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml index 20bc15050ae2..f3d04091f096 100644 --- a/packages/SystemUI/res/values-si/strings.xml +++ b/packages/SystemUI/res/values-si/strings.xml @@ -416,10 +416,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"තිර පටිගත කිරීම"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"ආරම්භ කරන්න"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"නතර කරන්න"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"දිගටම කර ගෙන යාමට, <b><xliff:g id="APP">%s</xliff:g></b> හට ඔබගේ උපාංගයෙහි මයික්රෆෝනයට ප්රවේශය අවශ්යයි."</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"දිගටම කර ගෙන යාමට, <b><xliff:g id="APP">%s</xliff:g></b> හට ඔබගේ උපාංගයෙහි කැමරාවට ප්රවේශය අවශ්යයි."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"උපාංගය"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"යෙදුම් මාරු කිරීමට ස්වයිප් කරන්න"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"ඉක්මනින් යෙදුම් මාරු කිරීමට දකුණට අදින්න"</string> @@ -442,8 +440,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"විවෘත කිරීමට නැවත තට්ටු කරන්න"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"විවෘත කිරීමට ස්වයිප් කරන්න"</string> <string name="keyguard_retry" msgid="886802522584053523">"නැවත උත්සාහ කිරීමට ඉහළට ස්වයිප් කරන්න"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC භාවිත කිරීමට අගුලු හරින්න"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"මෙම උපාංගය ඔබේ සංවිධානයට අයිතිය"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"මෙම උපාංගය <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> සංවිධානයට අයිතිය"</string> <string name="phone_hint" msgid="6682125338461375925">"දුරකථනය සඳහා නිරූපකය වෙතින් ස්වයිප් කරන්න"</string> @@ -970,6 +967,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"යෙදුම් ඔබේ <xliff:g id="TYPES_LIST">%s</xliff:g> භාවිත කරමින් සිටී."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" සහ "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> භාවිත කරමින් ඇත"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> මෑතකදී <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> භාවිත කළේය"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(ව්යවසාය)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"දුරකථන ඇමතුම"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(<xliff:g id="ATTRIBUTION">%s</xliff:g> හරහා)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"කැමරාව"</string> <string name="privacy_type_location" msgid="7991481648444066703">"ස්ථානය"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"මයික්රෝෆෝනය"</string> diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml index 4984f0f76b9f..7e3f3c010d68 100644 --- a/packages/SystemUI/res/values-sk/strings.xml +++ b/packages/SystemUI/res/values-sk/strings.xml @@ -420,10 +420,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Záznam obrazovky"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Začať"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Ukončiť"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"Ak chcete pokračovať, <b><xliff:g id="APP">%s</xliff:g></b> požaduje prístup k mikrofónu zariadenia."</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"Ak chcete pokračovať, <b><xliff:g id="APP">%s</xliff:g></b> požaduje prístup k fotoaparátu zariadenia."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"Zariadenie"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Potiahnutím nahor prepnete aplikácie"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Presunutím doprava rýchlo prepnete aplikácie"</string> @@ -446,8 +444,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"Upozornenie otvoríte opätovným klepnutím"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"Otvorte potiahnutím prstom nahor"</string> <string name="keyguard_retry" msgid="886802522584053523">"Potiahnutím nahor to skúste znova"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Ak chcete použiť NFC, odomknite"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Toto zariadenie patrí vašej organizácii"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Toto zariadení patrí organizácii <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> <string name="phone_hint" msgid="6682125338461375925">"Telefón otvoríte prejdením prstom od ikony"</string> @@ -980,6 +977,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Aplikácie používajú zoznam <xliff:g id="TYPES_LIST">%s</xliff:g>."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" a "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> používa aplikáciu <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"Aplikácia <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> použila nedávno aplikáciu <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(podniková verzia)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Telefonický hovor"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(prostredníctvom aplikácie <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"fotoaparát"</string> <string name="privacy_type_location" msgid="7991481648444066703">"poloha"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofón"</string> diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml index ffc6c6683b9d..b7ebea9ebb19 100644 --- a/packages/SystemUI/res/values-sl/strings.xml +++ b/packages/SystemUI/res/values-sl/strings.xml @@ -420,10 +420,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Snemanje zaslona"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Začni"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Ustavi"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"Za nadaljevanje potrebuje aplikacija <b><xliff:g id="APP">%s</xliff:g></b> dostop do mikrofona v napravi."</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"Za nadaljevanje potrebuje aplikacija <b><xliff:g id="APP">%s</xliff:g></b> dostop do fotoaparata v napravi."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"Naprava"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Za preklop aplikacij povlecite navzgor"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Povlecite v desno za hiter preklop med aplikacijami"</string> @@ -446,8 +444,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"Znova se dotaknite, da odprete"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"Povlecite navzgor, da odprete"</string> <string name="keyguard_retry" msgid="886802522584053523">"Povlecite navzgor za vnovičen poskus"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Odklenite napravo, če želite uporabljati vmesnik NFC."</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Ta naprava pripada vaši organizaciji"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Ta naprava pripada organizaciji <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> <string name="phone_hint" msgid="6682125338461375925">"Povlecite z ikone za telefon"</string> @@ -980,6 +977,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Aplikacije uporabljajo <xliff:g id="TYPES_LIST">%s</xliff:g>."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" in "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"Aplikacija <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> uporablja: <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"Aplikacija <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> je nedavno uporabila: <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(za podjetja)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Telefonski klici"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(prek aplikacije <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"fotoaparat"</string> <string name="privacy_type_location" msgid="7991481648444066703">"lokacijo"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofon"</string> diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml index 21ac1e05a073..fede55cd86d8 100644 --- a/packages/SystemUI/res/values-sq/strings.xml +++ b/packages/SystemUI/res/values-sq/strings.xml @@ -416,10 +416,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Regjistrimi i ekranit"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Nis"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Ndalo"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"Për të vazhduar, <b><xliff:g id="APP">%s</xliff:g></b> ka nevojë të qaset në mikrofonin e pajisjes sate."</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"Për të vazhduar, <b><xliff:g id="APP">%s</xliff:g></b> ka nevojë të qaset në kamerën e pajisjes sate."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"Pajisja"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Rrëshqit shpejt lart për të ndërruar aplikacionet"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Zvarrit djathtas për të ndërruar aplikacionet me shpejtësi"</string> @@ -442,8 +440,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"Trokit përsëri për ta hapur"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"Rrëshqit lart për ta hapur"</string> <string name="keyguard_retry" msgid="886802522584053523">"Rrëshqit lart për të provuar përsëri"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Shkyçe për të përdorur NFC-në"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Kjo pajisje i përket organizatës sate"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Kjo pajisje i përket <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> <string name="phone_hint" msgid="6682125338461375925">"Rrëshqit për të hapur telefonin"</string> @@ -970,6 +967,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Aplikacionet po përdorin <xliff:g id="TYPES_LIST">%s</xliff:g>."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" dhe "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> po përdor <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> ka përdorur <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> së fundi"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(ndërmarrje)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Phonecall"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(nëpërmjet <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"kamerën"</string> <string name="privacy_type_location" msgid="7991481648444066703">"vendndodhjen"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofonin"</string> diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml index e154cc5e3931..0d822464611a 100644 --- a/packages/SystemUI/res/values-sr/strings.xml +++ b/packages/SystemUI/res/values-sr/strings.xml @@ -418,10 +418,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Снимак екрана"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Почните"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Зауставите"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"<b><xliff:g id="APP">%s</xliff:g></b> захтева приступ микрофону уређаја ради настављања."</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"<b><xliff:g id="APP">%s</xliff:g></b> захтева приступ камери уређаја ради настављања."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"Уређај"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Превуците нагоре да бисте мењали апликације"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Превуците удесно да бисте брзо променили апликације"</string> @@ -444,8 +442,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"Додирните поново да бисте отворили"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"Превуците нагоре да бисте отворили"</string> <string name="keyguard_retry" msgid="886802522584053523">"Превуците нагоре да бисте пробали поново"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Откључајте да бисте користили NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Овај уређај припада организацији"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Овај уређај припада организацији <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> <string name="phone_hint" msgid="6682125338461375925">"Превуците од иконе за телефон"</string> @@ -975,6 +972,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Апликације користе <xliff:g id="TYPES_LIST">%s</xliff:g>."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" и "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"Апликација <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> користи: <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"Апликација <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> је недавно користила: <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(за предузећа)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Телефонски позив"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(преко: <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"камеру"</string> <string name="privacy_type_location" msgid="7991481648444066703">"локацију"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"микрофон"</string> diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml index 66ae2276fc8f..969bdcd7eb17 100644 --- a/packages/SystemUI/res/values-sv/strings.xml +++ b/packages/SystemUI/res/values-sv/strings.xml @@ -416,10 +416,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Skärminspelning"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Starta"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Stoppa"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"<b><xliff:g id="APP">%s</xliff:g></b> behöver behörighet till enhetens mikrofon för att fortsätta."</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"<b><xliff:g id="APP">%s</xliff:g></b> behöver behörighet till enhetens kamera för att fortsätta."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"Enhet"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Byt appar genom att svepa uppåt"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Tryck och dra åt höger för att snabbt byta mellan appar"</string> @@ -442,8 +440,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"Tryck igen för att öppna"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"Öppna genom att svepa uppåt"</string> <string name="keyguard_retry" msgid="886802522584053523">"Svep uppåt om du vill försöka igen"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Lås upp om du vill använda NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Den här enheten tillhör organisationen"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Den här enheten tillhör <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> <string name="phone_hint" msgid="6682125338461375925">"Svep från ikonen och öppna telefonen"</string> @@ -970,6 +967,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"<xliff:g id="TYPES_LIST">%s</xliff:g> används av appar."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" och "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> använder <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> använde <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> nyligen"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(företag)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Telefonsamtal"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(genom <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"kamera"</string> <string name="privacy_type_location" msgid="7991481648444066703">"plats"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofon"</string> diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml index 26e6b8c94a52..4055e8da981d 100644 --- a/packages/SystemUI/res/values-sw/strings.xml +++ b/packages/SystemUI/res/values-sw/strings.xml @@ -416,10 +416,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Rekodi ya Skrini"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Anza kurekodi"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Acha kurekodi"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"Ili uendelee, <b><xliff:g id="APP">%s</xliff:g></b> inahitaji ruhusa ya kufikia maikrofoni ya kifaa chako."</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"Ili uendelee, <b><xliff:g id="APP">%s</xliff:g></b> inahitaji ruhusa ya kufikia kamera ya kifaa chako."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"Kifaa"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Telezesha kidole juu ili ubadilishe programu"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Buruta kulia ili ubadilishe programu haraka"</string> @@ -442,8 +440,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"Gusa tena ili ufungue"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"Telezesha kidole juu ili ufungue"</string> <string name="keyguard_retry" msgid="886802522584053523">"Telezesha kidole juu ili ujaribu tena"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Fungua ili utumie NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Kifaa hiki kinamilikiwa na shirika lako"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Kifaa hiki kinamilikiwa na <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> <string name="phone_hint" msgid="6682125338461375925">"Telezesha kidole kutoka kwa aikoni ili ufikie simu"</string> @@ -970,6 +967,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Programu zinatumia <xliff:g id="TYPES_LIST">%s</xliff:g> yako."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" na "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> inatumia <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> ilitumia <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> hivi majuzi"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(biashara)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Simu"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(kupitia <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"kamera"</string> <string name="privacy_type_location" msgid="7991481648444066703">"mahali"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"maikrofoni"</string> diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml index 132713bc1931..cbac87e6390a 100644 --- a/packages/SystemUI/res/values-ta/strings.xml +++ b/packages/SystemUI/res/values-ta/strings.xml @@ -416,10 +416,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"ஸ்கிரீன் ரெக்கார்டு"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"தொடங்கு"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"நிறுத்து"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"தொடர, உங்கள் சாதனத்தின் மைக்ரோஃபோனை அணுகுவதற்கு <b><xliff:g id="APP">%s</xliff:g></b> ஆப்ஸுக்கு அனுமதி வேண்டும்."</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"தொடர, உங்கள் சாதனத்தின் கேமராவை அணுகுவதற்கு <b><xliff:g id="APP">%s</xliff:g></b> ஆப்ஸுக்கு அனுமதி வேண்டும்."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"சாதனம்"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"ஆப்ஸிற்கு இடையே மாற்றுவதற்கு, மேல்நோக்கி ஸ்வைப் செய்க"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"ஆப்ஸை வேகமாக மாற்ற, வலப்புறம் இழுக்கவும்"</string> @@ -442,8 +440,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"திறக்க, மீண்டும் தட்டவும்"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"திறப்பதற்கு மேல் நோக்கி ஸ்வைப் செய்யவும்"</string> <string name="keyguard_retry" msgid="886802522584053523">"மீண்டும் முயல மேல்நோக்கி ஸ்வைப் செய்யவும்"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFCயைப் பயன்படுத்த அன்லாக் செய்யவும்"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"இந்த சாதனம் உங்கள் நிறுவனத்துக்கு சொந்தமானது"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"இந்த சாதனம் <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> நிறுவனத்துக்கு சொந்தமானது"</string> <string name="phone_hint" msgid="6682125338461375925">"ஃபோனிற்கு ஐகானிலிருந்து ஸ்வைப் செய்யவும்"</string> @@ -970,6 +967,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"உங்கள் <xliff:g id="TYPES_LIST">%s</xliff:g> ஆகியவற்றை ஆப்ஸ் பயன்படுத்துகின்றன."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" மற்றும் "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> ஆப்ஸ் <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> பயன்படுத்துகிறது"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"சமீபத்தில் <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> ஆப்ஸ் <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> பயன்படுத்தியுள்ளது"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(நிறுவனப் பதிப்பு)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"மொபைல் அழைப்பு"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(<xliff:g id="ATTRIBUTION">%s</xliff:g> மூலம்)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"கேமரா"</string> <string name="privacy_type_location" msgid="7991481648444066703">"இருப்பிடம்"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"மைக்ரோஃபோன்"</string> diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml index 13758d9be98f..45ef33900ccd 100644 --- a/packages/SystemUI/res/values-te/strings.xml +++ b/packages/SystemUI/res/values-te/strings.xml @@ -416,10 +416,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"స్క్రీన్ రికార్డ్"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"ప్రారంభించు"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"ఆపు"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"కొనసాగించడానికి, <b><xliff:g id="APP">%s</xliff:g></b>కు మీ పరికరం యొక్క మైక్రోఫోన్ యాక్సెస్ అవసరం."</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"కొనసాగించడానికి, <b><xliff:g id="APP">%s</xliff:g></b&gtకు మీ పరికరం యొక్క కెమెరా యాక్సెస్ అవసరం."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"పరికరం"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"యాప్లను మార్చడం కోసం ఎగువకు స్వైప్ చేయండి"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"యాప్లను శీఘ్రంగా స్విచ్ చేయడానికి కుడి వైపుకు లాగండి"</string> @@ -442,8 +440,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"తెరవడానికి మళ్లీ నొక్కండి"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"తెరవడానికి, పైకి స్వైప్ చేయండి"</string> <string name="keyguard_retry" msgid="886802522584053523">"మళ్ళీ ప్రయత్నించడానికి పైకి స్వైప్ చేయండి"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFCను ఉపయోగించడానికి అన్లాక్ చేయండి"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"ఈ పరికరం మీ సంస్థకు చెందినది"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"ఈ పరికరం <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>కు చెందినది"</string> <string name="phone_hint" msgid="6682125338461375925">"ఫోన్ కోసం చిహ్నాన్ని స్వైప్ చేయండి"</string> @@ -970,6 +967,16 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"అప్లికేషన్లు మీ <xliff:g id="TYPES_LIST">%s</xliff:g>ని ఉపయోగిస్తున్నాయి."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" మరియు "</string> + <!-- no translation found for ongoing_privacy_dialog_using_op (4125175620929701569) --> + <skip /> + <!-- no translation found for ongoing_privacy_dialog_recent_op (4255923947334262404) --> + <skip /> + <!-- no translation found for ongoing_privacy_dialog_enterprise (4082735415905550729) --> + <skip /> + <!-- no translation found for ongoing_privacy_dialog_phonecall (3526223335298089311) --> + <skip /> + <!-- no translation found for ongoing_privacy_dialog_attribution_text (9186683306719924646) --> + <skip /> <string name="privacy_type_camera" msgid="7974051382167078332">"కెమెరా"</string> <string name="privacy_type_location" msgid="7991481648444066703">"లొకేషన్"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"మైక్రోఫోన్"</string> diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml index 5c082931ea2b..8b197acb1958 100644 --- a/packages/SystemUI/res/values-th/strings.xml +++ b/packages/SystemUI/res/values-th/strings.xml @@ -416,10 +416,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"บันทึกหน้าจอ"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"เริ่ม"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"หยุด"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"<b><xliff:g id="APP">%s</xliff:g></b> ต้องได้รับสิทธิ์เข้าถึงไมโครโฟนของอุปกรณ์เพื่อดำเนินการต่อ"</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"<b><xliff:g id="APP">%s</xliff:g></b> ต้องได้รับสิทธิ์เข้าถึงกล้องของอุปกรณ์เพื่อดำเนินการต่อ"</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"อุปกรณ์"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"เลื่อนขึ้นเพื่อสลับแอป"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"ลากไปทางขวาเพื่อสลับแอปอย่างรวดเร็ว"</string> @@ -442,8 +440,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"แตะอีกครั้งเพื่อเปิด"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"เลื่อนขึ้นเพื่อเปิด"</string> <string name="keyguard_retry" msgid="886802522584053523">"เลื่อนขึ้นเพื่อลองอีกครั้ง"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"ปลดล็อกเพื่อใช้ NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"องค์กรของคุณเป็นเจ้าของอุปกรณ์นี้"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"<xliff:g id="ORGANIZATION_NAME">%s</xliff:g> เป็นเจ้าของอุปกรณ์นี้"</string> <string name="phone_hint" msgid="6682125338461375925">"เลื่อนไอคอนโทรศัพท์"</string> @@ -970,6 +967,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"หลายแอปพลิเคชันใช้<xliff:g id="TYPES_LIST">%s</xliff:g>ของคุณอยู่"</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" และ "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> กำลังใช้<xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> ใช้<xliff:g id="APP_OPP_NAME">%2$s</xliff:g>เมื่อเร็วๆ นี้"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(องค์กร)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"โทรศัพท์"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(ผ่านทาง <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"กล้องถ่ายรูป"</string> <string name="privacy_type_location" msgid="7991481648444066703">"ตำแหน่ง"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"ไมโครโฟน"</string> diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml index 9f322325af5f..a4a768bdc959 100644 --- a/packages/SystemUI/res/values-tl/strings.xml +++ b/packages/SystemUI/res/values-tl/strings.xml @@ -416,10 +416,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Pag-record ng Screen"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Magsimula"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Ihinto"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"Para magpatuloy, kailangan ng <b><xliff:g id="APP">%s</xliff:g></b> ng access sa mikropono ng iyong device."</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"Para magpatuloy, kailangan ng <b><xliff:g id="APP">%s</xliff:g></b> ng access sa camera ng iyong device."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"Device"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Mag-swipe pataas upang lumipat ng app"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"I-drag pakanan para mabilisang magpalipat-lipat ng app"</string> @@ -442,8 +440,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"I-tap ulit upang buksan"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"Mag-swipe pataas para buksan"</string> <string name="keyguard_retry" msgid="886802522584053523">"Mag-swipe pataas para subukan ulit"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"I-unlock para magamit ang NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Pagmamay-ari ng iyong organisasyon ang device na ito"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Pagmamay-ari ng <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> ang device na ito"</string> <string name="phone_hint" msgid="6682125338461375925">"Mag-swipe mula sa icon para sa telepono"</string> @@ -970,6 +967,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Ginagamit ng mga application ang iyong <xliff:g id="TYPES_LIST">%s</xliff:g>."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" at "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"Ginagamit ng <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> ang <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"Kamakailang ginamit ng <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> ang <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(enterprise)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Tawag sa telepono"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(sa pamamagitan ng <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"camera"</string> <string name="privacy_type_location" msgid="7991481648444066703">"lokasyon"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"mikropono"</string> diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml index 8c1016d631fa..3040ea0a2c3d 100644 --- a/packages/SystemUI/res/values-tr/strings.xml +++ b/packages/SystemUI/res/values-tr/strings.xml @@ -416,10 +416,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Ekran Kaydı"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Başlat"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Durdur"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"Devam etmek için <b><xliff:g id="APP">%s</xliff:g></b> uygulamasının cihazınızın mikrofonuna erişmesi gerekiyor."</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"Devam etmek için <b><xliff:g id="APP">%s</xliff:g></b> uygulamasının cihazınızın kamerasına erişmesi gerekiyor."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"Cihaz"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Uygulamalar arasında geçiş yapmak için yukarı kaydırın"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Uygulamaları hızlıca değiştirmek için sağa kaydırın"</string> @@ -442,8 +440,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"Açmak için tekrar dokunun"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"Açmak için yukarı kaydırın"</string> <string name="keyguard_retry" msgid="886802522584053523">"Tekrar denemek için yukarı kaydırın"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC\'yi kullanmak için kilidi açın"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Bu cihaz, kuruluşunuza ait"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Bu cihaz <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> adlı kuruluşa ait"</string> <string name="phone_hint" msgid="6682125338461375925">"Telefon için, simgeden hızlıca kaydırın"</string> @@ -970,6 +967,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Uygulamalar şunları kullanıyor: <xliff:g id="TYPES_LIST">%s</xliff:g>."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" ve "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g>, <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> uygulamasını kullanıyor"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g>, yakın zamanda <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> uygulamasını kullandı"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(kurumsal)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Telefon çağrısı"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(<xliff:g id="ATTRIBUTION">%s</xliff:g> aracılığıyla)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"kamera"</string> <string name="privacy_type_location" msgid="7991481648444066703">"konum"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofon"</string> diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml index 45d4ad98d411..b6b7cee5c4f9 100644 --- a/packages/SystemUI/res/values-uk/strings.xml +++ b/packages/SystemUI/res/values-uk/strings.xml @@ -420,10 +420,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Запис екрана"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Почати"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Зупинити"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"Щоб продовжити, надайте додатку <b><xliff:g id="APP">%s</xliff:g></b> доступ до мікрофона пристрою."</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"Щоб продовжити, надайте додатку <b><xliff:g id="APP">%s</xliff:g></b> доступ до камери пристрою."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"Пристрій"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Проводьте пальцем угору, щоб переходити між додатками"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Перетягуйте праворуч, щоб швидко переходити між додатками"</string> @@ -446,8 +444,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"Торкніться знову, щоб відкрити"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"Проведіть пальцем угору, щоб відкрити"</string> <string name="keyguard_retry" msgid="886802522584053523">"Проведіть пальцем угору, щоб повторити спробу"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Розблокуйте екран, щоб скористатись NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Цей пристрій належить вашій організації"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Цей пристрій належить організації \"<xliff:g id="ORGANIZATION_NAME">%s</xliff:g>\""</string> <string name="phone_hint" msgid="6682125338461375925">"Телефон: проведіть пальцем від значка"</string> @@ -980,6 +977,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Додатки використовують <xliff:g id="TYPES_LIST">%s</xliff:g>."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" і "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"Додаток <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> використовує функцію \"<xliff:g id="APP_OPP_NAME">%2$s</xliff:g>\""</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"Додаток <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> нещодавно використав функцію \"<xliff:g id="APP_OPP_NAME">%2$s</xliff:g>\""</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(корпоративний додаток)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Додаток для телефонних дзвінків"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(через <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"камеру"</string> <string name="privacy_type_location" msgid="7991481648444066703">"місце"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"мікрофон"</string> diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml index 021679724d4e..15c9607aa78f 100644 --- a/packages/SystemUI/res/values-ur/strings.xml +++ b/packages/SystemUI/res/values-ur/strings.xml @@ -416,10 +416,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"اسکرین ریکارڈر کریں"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"آغاز"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"روکیں"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"جاری رکھنے کیلئے <b><xliff:g id="APP">%s</xliff:g></b> کو آپ کے آلے کے مائیکروفون تک رسائی درکار ہے۔"</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"جاری رکھنے کیلئے <b><xliff:g id="APP">%s</xliff:g></b> کو آپ کے آلے کے کیمرے تک رسائی درکار ہے۔"</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"آلہ"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"ایپس سوئچ کرنے کیلئے اوپر سوائپ کریں"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"تیزی سے ایپس کو سوئچ کرنے کے لیے دائیں طرف گھسیٹیں"</string> @@ -442,8 +440,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"کھولنے کیلئے دوبارہ تھپتھپائیں"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"کھولنے کے لیے اوپر سوائپ کريں"</string> <string name="keyguard_retry" msgid="886802522584053523">"دوبارہ کوشش کرنے کے لیے اوپر سوائپ کريں"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC استعمال کرنے کیلئے غیر مقفل کریں"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"یہ آلہ آپ کی تنظیم کا ہے"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"یہ آلہ <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> کا ہے"</string> <string name="phone_hint" msgid="6682125338461375925">"فون کیلئے آئیکن سے سوائپ کریں"</string> @@ -970,6 +967,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"ایپلیکیشنز آپ کی <xliff:g id="TYPES_LIST">%s</xliff:g> کا استعمال کر رہی ہیں۔"</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">"، "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" اور "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> کا استعمال کر رہی ہے"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> نے حال ہی میں <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> کا استعمال کیا"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(انٹرپرائز)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"فون کال"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(<xliff:g id="ATTRIBUTION">%s</xliff:g> کے ذریعے)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"کیمرا"</string> <string name="privacy_type_location" msgid="7991481648444066703">"مقام"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"مائیکروفون"</string> diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml index e9bc22ac48c6..3044a98ad814 100644 --- a/packages/SystemUI/res/values-uz/strings.xml +++ b/packages/SystemUI/res/values-uz/strings.xml @@ -345,7 +345,7 @@ <string name="quick_settings_location_label" msgid="2621868789013389163">"Joylashuv"</string> <string name="quick_settings_location_off_label" msgid="7923929131443915919">"Joylashuvni aniqlash xizmati yoqilmagan"</string> <string name="quick_settings_camera_label" msgid="1367149596242401934">"Kamerani bloklash"</string> - <string name="quick_settings_mic_label" msgid="8245831073612564953">"Mikrofonni oʻchirish"</string> + <string name="quick_settings_mic_label" msgid="8245831073612564953">"Mikrofonni ovozsiz qilish"</string> <string name="quick_settings_media_device_label" msgid="8034019242363789941">"Media qurilma"</string> <string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string> <string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Favqulodda chaqiruvlar"</string> @@ -416,10 +416,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Ekranni yozib olish"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Boshlash"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Toʻxtatish"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"Davom etish uchun <b> <xliff:g id="APP">%s</xliff:g></b> mikrofoningizdan foydalanishi kerak."</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"Davom etish uchun <b><xliff:g id="APP">%s</xliff:g></b> qurilmangiz kamerasiga kirishi kerak."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"Qurilma"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Ilovalarni almashtirish uchun ekranni tepaga suring"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Ilovalarni tezkor almashtirish uchun o‘ngga torting"</string> @@ -442,8 +440,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"Ochish uchun yana bosing"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"Ochish uchun tepaga suring"</string> <string name="keyguard_retry" msgid="886802522584053523">"Qayta urinish uchun tepaga suring"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC ishlatish uchun qurilma qulfini oching"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Bu qurilma tashkilotingizga tegishli"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Bu qurilma <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> tashkilotiga tegishli"</string> <string name="phone_hint" msgid="6682125338461375925">"Telefonni ochish uchun suring"</string> @@ -970,6 +967,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Ilovalarda ishlatilmoqda: <xliff:g id="TYPES_LIST">%s</xliff:g>."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" va "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> hozir <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> ishlatmoqda"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> yaqinda <xliff:g id="APP_OPP_NAME">%2$s</xliff:g> ishlatgan"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(korporativ)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Telefon chaqiruvi"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(<xliff:g id="ATTRIBUTION">%s</xliff:g> orqali)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"kamera"</string> <string name="privacy_type_location" msgid="7991481648444066703">"joylashuv"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofon"</string> diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml index e62a33bc8bc9..4913be4f9565 100644 --- a/packages/SystemUI/res/values-vi/strings.xml +++ b/packages/SystemUI/res/values-vi/strings.xml @@ -416,10 +416,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Ghi lại nội dung trên màn hình"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Bắt đầu"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Dừng"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"Để tiếp tục, <b><xliff:g id="APP">%s</xliff:g></b> cần quyền truy cập vào micrô trên thiết bị của bạn."</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"Để tiếp tục, <b><xliff:g id="APP">%s</xliff:g></b> cần quyền truy cập vào máy ảnh trên thiết bị của bạn."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"Thiết bị"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Vuốt lên để chuyển đổi ứng dụng"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Kéo sang phải để chuyển đổi nhanh giữa các ứng dụng"</string> @@ -442,8 +440,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"Nhấn lại để mở"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"Vuốt lên để mở"</string> <string name="keyguard_retry" msgid="886802522584053523">"Vuốt lên để thử lại"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Mở khóa để sử dụng NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Thiết bị này thuộc về tổ chức của bạn"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Thiết bị này thuộc về <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> <string name="phone_hint" msgid="6682125338461375925">"Vuốt từ biểu tượng để mở điện thoại"</string> @@ -970,6 +967,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Các ứng dụng đang dùng <xliff:g id="TYPES_LIST">%s</xliff:g> của bạn."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" và "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> đang sử dụng <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"Gần đây, <xliff:g id="APPLICATION_NAME">%1$s</xliff:g> đã sử dụng <xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(doanh nghiệp)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Gọi điện thoại"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(thông qua <xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"máy ảnh"</string> <string name="privacy_type_location" msgid="7991481648444066703">"vị trí"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"micrô"</string> diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml index 050eea515f74..3479d009804c 100644 --- a/packages/SystemUI/res/values-zh-rCN/strings.xml +++ b/packages/SystemUI/res/values-zh-rCN/strings.xml @@ -416,10 +416,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"屏幕录制"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"开始"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"停止"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"如要继续操作,请向<b><xliff:g id="APP">%s</xliff:g></b>授予设备的麦克风使用权。"</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"如要继续操作,请向<b><xliff:g id="APP">%s</xliff:g></b>授予设备的相机使用权。"</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"设备"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"向上滑动可切换应用"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"向右拖动可快速切换应用"</string> @@ -442,8 +440,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"再次点按即可打开"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"向上滑动即可打开"</string> <string name="keyguard_retry" msgid="886802522584053523">"向上滑动即可重试"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"需要解锁才能使用 NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"此设备归贵单位所有"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"此设备归<xliff:g id="ORGANIZATION_NAME">%s</xliff:g>所有"</string> <string name="phone_hint" msgid="6682125338461375925">"滑动图标即可拨打电话"</string> @@ -970,6 +967,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"有多个应用正在使用您的<xliff:g id="TYPES_LIST">%s</xliff:g>。"</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">"、 "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" 和 "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g>正在使用<xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g>最近曾使用<xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(企业版)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"电话"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(通过<xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"相机"</string> <string name="privacy_type_location" msgid="7991481648444066703">"位置信息"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"麦克风"</string> diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml index 15709f78a8e0..314b728071af 100644 --- a/packages/SystemUI/res/values-zh-rHK/strings.xml +++ b/packages/SystemUI/res/values-zh-rHK/strings.xml @@ -416,10 +416,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"畫面錄影"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"開始"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"停"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"如要繼續,<b><xliff:g id="APP">%s</xliff:g></b> 需要裝置的麥克風存取權。"</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"如要繼續,<b><xliff:g id="APP">%s</xliff:g></b> 需要裝置的相機存取權。"</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"裝置"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"向上滑動即可切換應用程式"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"向右拖曳即可快速切換應用程式"</string> @@ -442,8 +440,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"再次輕按即可開啟"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"向上滑動即可開啟"</string> <string name="keyguard_retry" msgid="886802522584053523">"請向上滑動以再試一次"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"解鎖以使用 NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"此裝置屬於您的機構"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"此裝置屬於「<xliff:g id="ORGANIZATION_NAME">%s</xliff:g>」"</string> <string name="phone_hint" msgid="6682125338461375925">"從圖示滑動即可使用手機功能"</string> @@ -970,6 +967,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"有多個應用程式正在使用<xliff:g id="TYPES_LIST">%s</xliff:g>。"</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">"、 "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" 和 "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"「<xliff:g id="APPLICATION_NAME">%1$s</xliff:g>」正在使用<xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"「<xliff:g id="APPLICATION_NAME">%1$s</xliff:g>」最近曾使用<xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(企業版本)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"電話"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(透過「<xliff:g id="ATTRIBUTION">%s</xliff:g>」)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"相機"</string> <string name="privacy_type_location" msgid="7991481648444066703">"位置"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"麥克風"</string> diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml index 90cf0b16387b..68b631fff5da 100644 --- a/packages/SystemUI/res/values-zh-rTW/strings.xml +++ b/packages/SystemUI/res/values-zh-rTW/strings.xml @@ -416,10 +416,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"螢幕畫面錄製"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"開始"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"停止"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"如要繼續操作,請將裝置的麥克風存取權授予「<xliff:g id="APP">%s</xliff:g>」<b></b>。"</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"如要繼續操作,請將裝置的相機存取權授予「<xliff:g id="APP">%s</xliff:g>」<b></b>。"</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"裝置"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"向上滑動即可切換應用程式"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"向右拖曳即可快速切換應用程式"</string> @@ -442,8 +440,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"再次輕觸即可開啟"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"向上滑動即可開啟"</string> <string name="keyguard_retry" msgid="886802522584053523">"向上滑動即可重試"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"如要使用 NFC,請先解鎖"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"這部裝置的擁有者為貴機構"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"這部裝置的擁有者為「<xliff:g id="ORGANIZATION_NAME">%s</xliff:g>」"</string> <string name="phone_hint" msgid="6682125338461375925">"滑動手機圖示即可啟用"</string> @@ -970,6 +967,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"有多個應用程式正在使用<xliff:g id="TYPES_LIST">%s</xliff:g>。"</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">"、 "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" 和 "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"「<xliff:g id="APPLICATION_NAME">%1$s</xliff:g>」正在使用<xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"「<xliff:g id="APPLICATION_NAME">%1$s</xliff:g>」最近曾使用<xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(企業版)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"電話"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(透過「<xliff:g id="ATTRIBUTION">%s</xliff:g>」)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"相機"</string> <string name="privacy_type_location" msgid="7991481648444066703">"位置"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"麥克風"</string> diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml index 3a77730a9421..78c4f17edf2d 100644 --- a/packages/SystemUI/res/values-zu/strings.xml +++ b/packages/SystemUI/res/values-zu/strings.xml @@ -416,10 +416,8 @@ <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Irekhodi lesikrini"</string> <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Qala"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Misa"</string> - <!-- no translation found for sensor_privacy_start_use_mic_dialog_content (8643239110815357707) --> - <skip /> - <!-- no translation found for sensor_privacy_start_use_camera_dialog_content (7773612142162829116) --> - <skip /> + <string name="sensor_privacy_start_use_mic_dialog_content" msgid="8643239110815357707">"Ukuze uqhubeke, <b>i-<xliff:g id="APP">%s</xliff:g></b> idinga ukufinyelela imakrofoni yedivayisi yakho."</string> + <string name="sensor_privacy_start_use_camera_dialog_content" msgid="7773612142162829116">"Ukuze uqhubeke, <b>i-<xliff:g id="APP">%s</xliff:g></b> idinga ukufinyelela ikhamera yakho."</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"Idivayisi"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Swayiphela phezulu ukuze ushintshe izinhlelo zokusebenza"</string> <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Hudula ngqo ukuze ushintshe ngokushesha izinhlelo zokusebenza"</string> @@ -442,8 +440,7 @@ <string name="notification_tap_again" msgid="4477318164947497249">"Thepha futhi ukuze uvule"</string> <string name="keyguard_unlock" msgid="8031975796351361601">"Swayiphela phezulu ukuze uvule"</string> <string name="keyguard_retry" msgid="886802522584053523">"Swayiphela phezulu ukuze uzame futhi"</string> - <!-- no translation found for require_unlock_for_nfc (1305686454823018831) --> - <skip /> + <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Vula ukuze usebenzise i-NFC"</string> <string name="do_disclosure_generic" msgid="4896482821974707167">"Le divayisi eyenhlangano yakho"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"Le divayisi ngeye-<xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> <string name="phone_hint" msgid="6682125338461375925">"Swayiphela ifoni kusukela kusithonjana"</string> @@ -970,6 +967,11 @@ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Izinhlelo zokusebenza zisebenzisa i-<xliff:g id="TYPES_LIST">%s</xliff:g> yakho."</string> <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string> <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" kanye "</string> + <string name="ongoing_privacy_dialog_using_op" msgid="4125175620929701569">"I-<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> isebenzisa i-<xliff:g id="APP_OPP_NAME">%2$s</xliff:g>"</string> + <string name="ongoing_privacy_dialog_recent_op" msgid="4255923947334262404">"I-<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> isebenzise i-<xliff:g id="APP_OPP_NAME">%2$s</xliff:g> kamuva nje"</string> + <string name="ongoing_privacy_dialog_enterprise" msgid="4082735415905550729">"(ibhizinisi)"</string> + <string name="ongoing_privacy_dialog_phonecall" msgid="3526223335298089311">"Ikholi yefoni"</string> + <string name="ongoing_privacy_dialog_attribution_text" msgid="9186683306719924646">"(kuya ku-<xliff:g id="ATTRIBUTION">%s</xliff:g>)"</string> <string name="privacy_type_camera" msgid="7974051382167078332">"ikhamera"</string> <string name="privacy_type_location" msgid="7991481648444066703">"indawo"</string> <string name="privacy_type_microphone" msgid="9136763906797732428">"imakrofoni"</string> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index e5109307c4f4..1fac96bb181d 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -1181,6 +1181,12 @@ <dimen name="ongoing_appops_dialog_side_margins">@dimen/notification_shade_content_margin_horizontal</dimen> + <dimen name="ongoing_appops_dialog_circle_size">32dp</dimen> + + <dimen name="ongoing_appops_dialog_icon_size">20dp</dimen> + + <dimen name="ongoing_appops_dialog_side_padding">16dp</dimen> + <!-- Size of the RAT type for CellularTile --> <dimen name="celltile_rat_type_size">10sp</dimen> diff --git a/packages/SystemUI/res/values/flags.xml b/packages/SystemUI/res/values/flags.xml index 49f91096543a..01e54ff60582 100644 --- a/packages/SystemUI/res/values/flags.xml +++ b/packages/SystemUI/res/values/flags.xml @@ -31,4 +31,9 @@ <!-- AOD/Lockscreen alternate layout --> <bool name="flag_keyguard_layout">false</bool> + + <bool name="flag_brightness_slider">false</bool> + + <!-- People Tile flag --> + <bool name="flag_conversations">false</bool> </resources> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 4baa06a393a8..cb7327f7629c 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -2556,8 +2556,8 @@ <!-- Text for privacy dialog, indicating that the application is the enterprise version [CHAR LIMIT=NONE] --> <string name="ongoing_privacy_dialog_enterprise">(enterprise)</string> - <!-- Text for privacy dialog, identifying the phonecall app [CHAR LIMIT=NONE]--> - <string name="ongoing_privacy_dialog_phonecall">Phonecall</string> + <!-- Text for privacy dialog, identifying the phone call app [CHAR LIMIT=NONE]--> + <string name="ongoing_privacy_dialog_phonecall">Phone call</string> <!-- Text for privacy dialog, indicating that an app is using an op on behalf of another [CHAR LIMIT=NONE] --> <string name="ongoing_privacy_dialog_attribution_text">(through <xliff:g id="attribution" example="Special app">%s</xliff:g>)</string> diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml index db260ce1b7b4..ad4e78e8e507 100644 --- a/packages/SystemUI/res/values/styles.xml +++ b/packages/SystemUI/res/values/styles.xml @@ -745,4 +745,9 @@ * Title: headline, medium 20sp * Message: body, 16 sp --> <style name="Theme.ControlsRequestDialog" parent="@*android:style/Theme.DeviceDefault.Dialog.Alert"/> + + <style name="TextAppearance.PrivacyDialog"> + <item name="android:textSize">14sp</item> + <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item> + </style> </resources> diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java index 2a0715ed764c..87f6b8202ded 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java @@ -118,9 +118,9 @@ public class RemoteAnimationTargetCompat { } public static RemoteAnimationTargetCompat[] wrap(RemoteAnimationTarget[] apps) { - final RemoteAnimationTargetCompat[] appsCompat = - new RemoteAnimationTargetCompat[apps != null ? apps.length : 0]; - for (int i = 0; i < apps.length; i++) { + final int length = apps != null ? apps.length : 0; + final RemoteAnimationTargetCompat[] appsCompat = new RemoteAnimationTargetCompat[length]; + for (int i = 0; i < length; i++) { appsCompat[i] = new RemoteAnimationTargetCompat(apps[i]); } return appsCompat; diff --git a/packages/SystemUI/src/com/android/keyguard/AnimatableClockView.java b/packages/SystemUI/src/com/android/keyguard/AnimatableClockView.java index 62d30935dd5c..ca99563986b4 100644 --- a/packages/SystemUI/src/com/android/keyguard/AnimatableClockView.java +++ b/packages/SystemUI/src/com/android/keyguard/AnimatableClockView.java @@ -38,7 +38,7 @@ import kotlin.Unit; * The time's text color is a gradient that changes its colors based on its controller. */ public class AnimatableClockView extends TextView { - private static final CharSequence FORMAT_12_HOUR = "h\nmm"; + private static final CharSequence FORMAT_12_HOUR = "hh\nmm"; private static final CharSequence FORMAT_24_HOUR = "HH\nmm"; private static final long ANIM_DURATION = 300; diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index 9908e672535f..d9a1eb6c0b28 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -1909,12 +1909,14 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab } /** - * Whether to show the lock icon on lock screen and bouncer. This depends on the enrolled - * biometrics to the device. + * Whether to show the lock icon on lock screen and bouncer. */ - public boolean shouldShowLockIcon() { - return isFaceAuthEnabledForUser(KeyguardUpdateMonitor.getCurrentUser()) - && !isUdfpsEnrolled(); + public boolean canShowLockIcon() { + if (mLockScreenMode == LOCK_SCREEN_MODE_LAYOUT_1) { + return isFaceAuthEnabledForUser(KeyguardUpdateMonitor.getCurrentUser()) + && !isUdfpsEnrolled(); + } + return true; } /** diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java index 036fcf3bec27..78f7966558ab 100644 --- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java +++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java @@ -127,7 +127,7 @@ public class SystemUIApplication extends Application implements } // If SHOW_PEOPLE_SPACE is true, enable People Space widget provider. - // TODO(b/170396074): Remove this when we don't need a widget anymore. + // TODO(b/170396074): Migrate to new feature flag (go/silk-flags-howto) try { int showPeopleSpace = Settings.Global.getInt(context.getContentResolver(), Settings.Global.SHOW_PEOPLE_SPACE, 1); diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java index b373cff489f6..008e8f506e0f 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java @@ -22,29 +22,22 @@ import static com.android.internal.util.Preconditions.checkNotNull; import android.annotation.SuppressLint; import android.content.Context; import android.content.res.Resources; -import android.content.res.TypedArray; import android.graphics.PixelFormat; import android.graphics.Point; import android.graphics.RectF; -import android.hardware.display.DisplayManager; import android.hardware.fingerprint.FingerprintManager; import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; import android.hardware.fingerprint.IUdfpsOverlayController; -import android.os.PowerManager; -import android.os.UserHandle; -import android.provider.Settings; -import android.text.TextUtils; import android.util.Log; -import android.util.MathUtils; -import android.util.Spline; +import android.view.Gravity; import android.view.LayoutInflater; import android.view.MotionEvent; +import android.view.Surface; import android.view.WindowManager; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import com.android.internal.BrightnessSynchronizer; import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.R; import com.android.systemui.dagger.SysUISingleton; @@ -53,10 +46,6 @@ import com.android.systemui.doze.DozeReceiver; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.phone.ScrimController; import com.android.systemui.util.concurrency.DelayableExecutor; -import com.android.systemui.util.settings.SystemSettings; - -import java.io.FileWriter; -import java.io.IOException; import javax.inject.Inject; @@ -73,16 +62,13 @@ import javax.inject.Inject; */ @SuppressWarnings("deprecation") @SysUISingleton -public class UdfpsController implements DozeReceiver { +public class UdfpsController implements UdfpsView.HbmCallback, DozeReceiver { private static final String TAG = "UdfpsController"; - // Gamma approximation for the sRGB color space. - private static final float DISPLAY_GAMMA = 2.2f; private static final long AOD_INTERRUPT_TIMEOUT_MILLIS = 1000; private final Context mContext; private final FingerprintManager mFingerprintManager; private final WindowManager mWindowManager; - private final SystemSettings mSystemSettings; private final DelayableExecutor mFgExecutor; private final StatusBarStateController mStatusBarStateController; // Currently the UdfpsController supports a single UDFPS sensor. If devices have multiple @@ -90,23 +76,6 @@ public class UdfpsController implements DozeReceiver { @VisibleForTesting final FingerprintSensorPropertiesInternal mSensorProps; private final WindowManager.LayoutParams mCoreLayoutParams; private final UdfpsView mView; - // Debugfs path to control the high-brightness mode. - private final String mHbmPath; - private final String mHbmEnableCommand; - private final String mHbmDisableCommand; - private final boolean mHbmSupported; - // Brightness in nits in the high-brightness mode. - private final float mMaxNits; - // A spline mapping from the device's backlight value, normalized to the range [0, 1.0], to a - // brightness in nits. - private final Spline mBacklightToNitsSpline; - // A spline mapping from a value in nits to a backlight value of a hypothetical panel whose - // maximum backlight value corresponds to our panel's high-brightness mode. - // The output is normalized to the range [0, 1.0]. - private Spline mNitsToHbmBacklightSpline; - // Default non-HBM backlight value normalized to the range [0, 1.0]. Used as a fallback when the - // actual brightness value cannot be retrieved. - private final float mDefaultBrightness; // Indicates whether the overlay is currently showing. Even if it has been requested, it might // not be showing. private boolean mIsOverlayShowing; @@ -152,7 +121,7 @@ public class UdfpsController implements DozeReceiver { @SuppressLint("ClickableViewAccessibility") private final UdfpsView.OnTouchListener mOnTouchListener = (v, event) -> { UdfpsView view = (UdfpsView) v; - final boolean isFingerDown = view.isShowScrimAndDot(); + final boolean isFingerDown = view.isIlluminationRequested(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_MOVE: @@ -183,9 +152,7 @@ public class UdfpsController implements DozeReceiver { @Main Resources resources, LayoutInflater inflater, @Nullable FingerprintManager fingerprintManager, - DisplayManager displayManager, WindowManager windowManager, - SystemSettings systemSettings, @NonNull StatusBarStateController statusBarStateController, @Main DelayableExecutor fgExecutor, @NonNull ScrimController scrimController) { @@ -194,7 +161,6 @@ public class UdfpsController implements DozeReceiver { // fingerprint manager should never be null. mFingerprintManager = checkNotNull(fingerprintManager); mWindowManager = windowManager; - mSystemSettings = systemSettings; mFgExecutor = fgExecutor; mStatusBarStateController = statusBarStateController; @@ -211,72 +177,18 @@ public class UdfpsController implements DozeReceiver { PixelFormat.TRANSLUCENT); mCoreLayoutParams.setTitle(TAG); mCoreLayoutParams.setFitInsetsTypes(0); + mCoreLayoutParams.gravity = Gravity.TOP | Gravity.LEFT; mCoreLayoutParams.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; mCoreLayoutParams.privateFlags = WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY; mView = (UdfpsView) inflater.inflate(R.layout.udfps_view, null, false); mView.setSensorProperties(mSensorProps); + mView.setHbmCallback(this); - mHbmPath = resources.getString(R.string.udfps_hbm_sysfs_path); - mHbmEnableCommand = resources.getString(R.string.udfps_hbm_enable_command); - mHbmDisableCommand = resources.getString(R.string.udfps_hbm_disable_command); - - mHbmSupported = !TextUtils.isEmpty(mHbmPath); - mView.setHbmSupported(mHbmSupported); scrimController.addScrimChangedListener(mView); statusBarStateController.addCallback(mView); - // This range only consists of the minimum and maximum values, which only cover - // non-high-brightness mode. - float[] nitsRange = toFloatArray(resources.obtainTypedArray( - com.android.internal.R.array.config_screenBrightnessNits)); - if (nitsRange.length < 2) { - throw new IllegalArgumentException( - String.format("nitsRange.length: %d. Must be >= 2", nitsRange.length)); - } - - // The last value of this range corresponds to the high-brightness mode. - float[] nitsAutoBrightnessValues = toFloatArray(resources.obtainTypedArray( - com.android.internal.R.array.config_autoBrightnessDisplayValuesNits)); - if (nitsAutoBrightnessValues.length < 2) { - throw new IllegalArgumentException( - String.format("nitsAutoBrightnessValues.length: %d. Must be >= 2", - nitsAutoBrightnessValues.length)); - } - - mMaxNits = nitsAutoBrightnessValues[nitsAutoBrightnessValues.length - 1]; - float[] hbmNitsRange = nitsRange.clone(); - hbmNitsRange[hbmNitsRange.length - 1] = mMaxNits; - - // This range only consists of the minimum and maximum backlight values, which only apply - // in non-high-brightness mode. - float[] normalizedBacklightRange = normalizeBacklightRange( - resources.getIntArray( - com.android.internal.R.array.config_screenBrightnessBacklight)); - if (normalizedBacklightRange.length < 2) { - throw new IllegalArgumentException( - String.format("normalizedBacklightRange.length: %d. Must be >= 2", - normalizedBacklightRange.length)); - } - if (normalizedBacklightRange.length != nitsRange.length) { - throw new IllegalArgumentException( - "normalizedBacklightRange.length != nitsRange.length"); - } - - mBacklightToNitsSpline = Spline.createSpline(normalizedBacklightRange, nitsRange); - mNitsToHbmBacklightSpline = Spline.createSpline(hbmNitsRange, normalizedBacklightRange); - mDefaultBrightness = obtainDefaultBrightness(mContext); - - // TODO(b/160025856): move to the "dump" method. - Log.v(TAG, String.format("ctor | mNitsRange: [%f, %f]", nitsRange[0], - nitsRange[nitsRange.length - 1])); - Log.v(TAG, String.format("ctor | mHbmNitsRange: [%f, %f]", hbmNitsRange[0], - hbmNitsRange[hbmNitsRange.length - 1])); - Log.v(TAG, String.format("ctor | mNormalizedBacklightRange: [%f, %f]", - normalizedBacklightRange[0], - normalizedBacklightRange[normalizedBacklightRange.length - 1])); - mFingerprintManager.setUdfpsOverlayController(new UdfpsOverlayController()); mIsOverlayShowing = false; } @@ -331,13 +243,33 @@ public class UdfpsController implements DozeReceiver { } private WindowManager.LayoutParams computeLayoutParams() { + // Default dimensions assume portrait mode. + mCoreLayoutParams.x = mSensorProps.sensorLocationX - mSensorProps.sensorRadius; + mCoreLayoutParams.y = mSensorProps.sensorLocationY - mSensorProps.sensorRadius; + mCoreLayoutParams.height = 2 * mSensorProps.sensorRadius; + mCoreLayoutParams.width = 2 * mSensorProps.sensorRadius; + Point p = new Point(); // Gets the size based on the current rotation of the display. mContext.getDisplay().getRealSize(p); - mCoreLayoutParams.width = p.x; - mCoreLayoutParams.x = p.x; - mCoreLayoutParams.height = p.y; - mCoreLayoutParams.y = p.y; + + // Transform dimensions if the device is in landscape mode. + switch (mContext.getDisplay().getRotation()) { + case Surface.ROTATION_90: + mCoreLayoutParams.x = mSensorProps.sensorLocationY - mSensorProps.sensorRadius; + mCoreLayoutParams.y = + p.y - mSensorProps.sensorLocationX - mSensorProps.sensorRadius; + break; + + case Surface.ROTATION_270: + mCoreLayoutParams.x = + p.x - mSensorProps.sensorLocationY - mSensorProps.sensorRadius; + mCoreLayoutParams.y = mSensorProps.sensorLocationX - mSensorProps.sensorRadius; + break; + + default: + // Do nothing to stay in portrait mode. + } return mCoreLayoutParams; } @@ -402,36 +334,10 @@ public class UdfpsController implements DozeReceiver { }); } - // Returns a value in the range of [0, 255]. - private int computeScrimOpacity() { - // Backlight setting can be NaN, -1.0f, and [0.0f, 1.0f]. - float backlightSetting = mSystemSettings.getFloatForUser( - Settings.System.SCREEN_BRIGHTNESS_FLOAT, mDefaultBrightness, - UserHandle.USER_CURRENT); - - // Constrain the backlight setting to [0.0f, 1.0f]. - float backlightValue = MathUtils.constrain(backlightSetting, - PowerManager.BRIGHTNESS_MIN, - PowerManager.BRIGHTNESS_MAX); - - // Interpolate the backlight value to nits. - float nits = mBacklightToNitsSpline.interpolate(backlightValue); - - // Interpolate nits to a backlight value for a panel with enabled HBM. - float interpolatedHbmBacklightValue = mNitsToHbmBacklightSpline.interpolate(nits); - - float gammaCorrectedHbmBacklightValue = (float) Math.pow(interpolatedHbmBacklightValue, - 1.0f / DISPLAY_GAMMA); - float scrimOpacity = PowerManager.BRIGHTNESS_MAX - gammaCorrectedHbmBacklightValue; - - // Interpolate the opacity value from [0.0f, 1.0f] to [0, 255]. - return BrightnessSynchronizer.brightnessFloatToInt(scrimOpacity); - } - /** * Request fingerprint scan. * - * This is intented to be called in response to a sensor that triggers an AOD interrupt for the + * This is intended to be called in response to a sensor that triggers an AOD interrupt for the * fingerprint sensor. */ void onAodInterrupt(int screenX, int screenY, float major, float minor) { @@ -451,7 +357,7 @@ public class UdfpsController implements DozeReceiver { /** * Cancel fingerprint scan. * - * This is intented to be called after the fingerprint scan triggered by the AOD interrupt + * This is intended to be called after the fingerprint scan triggered by the AOD interrupt * either succeeds or fails. */ void onCancelAodInterrupt() { @@ -466,65 +372,28 @@ public class UdfpsController implements DozeReceiver { onFingerUp(); } - protected void onFingerDown(int x, int y, float minor, float major) { - if (mHbmSupported) { - try { - FileWriter fw = new FileWriter(mHbmPath); - fw.write(mHbmEnableCommand); - fw.close(); - } catch (IOException e) { - mView.hideScrimAndDot(); - Log.e(TAG, "onFingerDown | failed to enable HBM: " + e.getMessage()); - } - } - mView.setScrimAlpha(computeScrimOpacity()); - mView.setRunAfterShowingScrimAndDot(() -> { - mFingerprintManager.onPointerDown(mSensorProps.sensorId, x, y, minor, major); - }); - mView.showScrimAndDot(); + // This method can be called from the UI thread. + private void onFingerDown(int x, int y, float minor, float major) { + mView.setOnIlluminatedRunnable( + () -> mFingerprintManager.onPointerDown(mSensorProps.sensorId, x, y, minor, major)); + mView.startIllumination(); } - protected void onFingerUp() { + // This method can be called from the UI thread. + private void onFingerUp() { mFingerprintManager.onPointerUp(mSensorProps.sensorId); - // Hiding the scrim before disabling HBM results in less noticeable flicker. - mView.hideScrimAndDot(); - if (mHbmSupported) { - try { - FileWriter fw = new FileWriter(mHbmPath); - fw.write(mHbmDisableCommand); - fw.close(); - } catch (IOException e) { - mView.showScrimAndDot(); - Log.e(TAG, "onFingerUp | failed to disable HBM: " + e.getMessage()); - } - } - } - - private static float obtainDefaultBrightness(Context context) { - return MathUtils.constrain(context.getDisplay().getBrightnessDefault(), - PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX); + mView.stopIllumination(); } - private static float[] toFloatArray(TypedArray array) { - final int n = array.length(); - float[] vals = new float[n]; - for (int i = 0; i < n; i++) { - vals[i] = array.getFloat(i, PowerManager.BRIGHTNESS_OFF_FLOAT); - } - array.recycle(); - return vals; - } - - private static float[] normalizeBacklightRange(int[] backlight) { - final int n = backlight.length; - float[] normalizedBacklight = new float[n]; - for (int i = 0; i < n; i++) { - normalizedBacklight[i] = BrightnessSynchronizer.brightnessIntToFloat(backlight[i]); - } - return normalizedBacklight; + @Override + public void enableHbm(Surface surface) { + // Do nothing. This method can be implemented for devices that require the high-brightness + // mode for fingerprint illumination. } - protected UdfpsView getView() { - return mView; + @Override + public void disableHbm(Surface surface) { + // Do nothing. This method can be implemented for devices that require the high-brightness + // mode for fingerprint illumination. } } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java index 96ecc7bdb017..4c05b886f8a8 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java @@ -28,7 +28,7 @@ import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.PixelFormat; -import android.graphics.Rect; +import android.graphics.PorterDuff; import android.graphics.RectF; import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; import android.text.TextUtils; @@ -37,7 +37,6 @@ import android.util.Log; import android.view.Surface; import android.view.SurfaceHolder; import android.view.SurfaceView; -import android.view.ViewTreeObserver; import com.android.systemui.R; import com.android.systemui.doze.DozeReceiver; @@ -48,68 +47,64 @@ import com.android.systemui.statusbar.phone.ScrimController; * A full screen view with a configurable illumination dot and scrim. */ public class UdfpsView extends SurfaceView implements DozeReceiver, - StatusBarStateController.StateListener, ScrimController.ScrimChangedListener { + StatusBarStateController.StateListener, ScrimController.ScrimChangedListener { private static final String TAG = "UdfpsView"; - // Values in pixels. + /** + * Interface for controlling the high-brightness mode (HBM). UdfpsView can use this callback to + * enable the HBM while showing the fingerprint illumination, and to disable the HBM after the + * illumination is no longer necessary. + */ + interface HbmCallback { + /** + * UdfpsView will call this to enable the HBM before drawing the illumination dot. + * + * @param surface A valid surface for which the HBM should be enabled. + */ + void enableHbm(@NonNull Surface surface); + + /** + * UdfpsView will call this to disable the HBM when the illumination is not longer needed. + * + * @param surface A valid surface for which the HBM should be disabled. + */ + void disableHbm(@NonNull Surface surface); + } + + /** + * This is used instead of {@link android.graphics.drawable.Drawable}, because the latter has + * several abstract methods that are not used here but require implementation. + */ + private interface SimpleDrawable { + void draw(Canvas canvas); + } + + // Radius in pixels. private static final float SENSOR_SHADOW_RADIUS = 2.0f; private static final int DEBUG_TEXT_SIZE_PX = 32; - @NonNull private final Rect mScrimRect; - @NonNull private final Paint mScrimPaint; - @NonNull private final Paint mDebugTextPaint; - + @NonNull private final SurfaceHolder mHolder; @NonNull private final RectF mSensorRect; @NonNull private final Paint mSensorPaint; - private final float mSensorTouchAreaCoefficient; + @NonNull private final Paint mDebugTextPaint; + @NonNull private final SimpleDrawable mIlluminationDotDrawable; + @NonNull private final SimpleDrawable mClearSurfaceDrawable; - // Stores rounded up values from mSensorRect. Necessary for APIs that only take Rect (not RecF). - @NonNull private final Rect mTouchableRegion; - // mInsetsListener is used to set the touchable region for our window. Our window covers the - // whole screen, and by default its touchable region is the whole screen. We use - // mInsetsListener to restrict the touchable region and allow the touches outside of the sensor - // to propagate to the rest of the UI. - @NonNull private final ViewTreeObserver.OnComputeInternalInsetsListener mInsetsListener; @Nullable private UdfpsAnimation mUdfpsAnimation; + @Nullable private HbmCallback mHbmCallback; + @Nullable private Runnable mOnIlluminatedRunnable; // Used to obtain the sensor location. @NonNull private FingerprintSensorPropertiesInternal mSensorProps; - private boolean mShowScrimAndDot; - private boolean mIsHbmSupported; + private final float mSensorTouchAreaCoefficient; @Nullable private String mDebugMessage; + private boolean mIlluminationRequested; private int mStatusBarState; private boolean mNotificationShadeExpanded; private int mNotificationPanelAlpha; - // Runnable that will be run after the illumination dot and scrim are shown. - // The runnable is reset to null after it's executed once. - @Nullable private Runnable mRunAfterShowingScrimAndDot; - - @NonNull private final SurfaceHolder.Callback mSurfaceCallback = new SurfaceHolder.Callback() { - @Override - public void surfaceCreated(@NonNull SurfaceHolder holder) { - Log.d(TAG, "Surface created"); - // SurfaceView sets this to true by default. We must set it to false to allow - // onDraw to be called - setWillNotDraw(false); - } - - @Override - public void surfaceChanged(@NonNull SurfaceHolder holder, int format, - int width, int height) { - - } - - @Override - public void surfaceDestroyed(@NonNull SurfaceHolder holder) { - Log.d(TAG, "Surface destroyed"); - // Must not draw when the surface is destroyed - setWillNotDraw(true); - } - }; - public UdfpsView(Context context, AttributeSet attrs) { super(context, attrs); @@ -126,18 +121,13 @@ public class UdfpsView extends SurfaceView implements DozeReceiver, a.recycle(); } - getHolder().addCallback(mSurfaceCallback); - getHolder().setFormat(PixelFormat.TRANSLUCENT); - - mScrimRect = new Rect(); - mScrimPaint = new Paint(0 /* flags */); - mScrimPaint.setColor(Color.BLACK); + mHolder = getHolder(); + mHolder.setFormat(PixelFormat.RGBA_8888); mSensorRect = new RectF(); mSensorPaint = new Paint(0 /* flags */); mSensorPaint.setAntiAlias(true); - mSensorPaint.setColor(Color.WHITE); - mSensorPaint.setShadowLayer(SENSOR_SHADOW_RADIUS, 0, 0, Color.BLACK); + mSensorPaint.setARGB(255, 255, 255, 255); mSensorPaint.setStyle(Paint.Style.FILL); mDebugTextPaint = new Paint(); @@ -145,16 +135,13 @@ public class UdfpsView extends SurfaceView implements DozeReceiver, mDebugTextPaint.setColor(Color.BLUE); mDebugTextPaint.setTextSize(DEBUG_TEXT_SIZE_PX); - mTouchableRegion = new Rect(); - // When the device is rotated, it's important that mTouchableRegion is updated before - // this listener is called. This listener is usually called shortly after onLayout. - mInsetsListener = internalInsetsInfo -> { - internalInsetsInfo.setTouchableInsets( - ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION); - internalInsetsInfo.touchableRegion.set(mTouchableRegion); - }; + mIlluminationDotDrawable = canvas -> canvas.drawOval(mSensorRect, mSensorPaint); + mClearSurfaceDrawable = canvas -> canvas.drawColor(0, PorterDuff.Mode.CLEAR); - mShowScrimAndDot = false; + mIlluminationRequested = false; + // SurfaceView sets this to true by default. We must set it to false to allow + // onDraw to be called. + setWillNotDraw(false); } void setSensorProperties(@NonNull FingerprintSensorPropertiesInternal properties) { @@ -165,6 +152,20 @@ public class UdfpsView extends SurfaceView implements DozeReceiver, mUdfpsAnimation = animation; } + /** + * Sets a callback that can be used to enable and disable the high-brightness mode (HBM). + */ + void setHbmCallback(@Nullable HbmCallback callback) { + mHbmCallback = callback; + } + + /** + * Sets a runnable that will be run when the first illumination frame reaches the panel. + * The runnable is reset to null after it is executed once. + */ + void setOnIlluminatedRunnable(Runnable runnable) { + mOnIlluminatedRunnable = runnable; + } @Override public void dozeTimeTick() { @@ -189,50 +190,13 @@ public class UdfpsView extends SurfaceView implements DozeReceiver, postInvalidate(); } - // The "h" and "w" are the display's height and width relative to its current rotation. - protected void updateSensorRect(int h, int w) { - // mSensorProps coordinates assume portrait mode. - mSensorRect.set(mSensorProps.sensorLocationX - mSensorProps.sensorRadius, - mSensorProps.sensorLocationY - mSensorProps.sensorRadius, - mSensorProps.sensorLocationX + mSensorProps.sensorRadius, - mSensorProps.sensorLocationY + mSensorProps.sensorRadius); - - // Transform mSensorRect if the device is in landscape mode. - switch (mContext.getDisplay().getRotation()) { - case Surface.ROTATION_90: - //noinspection SuspiciousNameCombination - mSensorRect.set(mSensorRect.top, h - mSensorRect.right, mSensorRect.bottom, - h - mSensorRect.left); - break; - case Surface.ROTATION_270: - //noinspection SuspiciousNameCombination - mSensorRect.set(w - mSensorRect.bottom, mSensorRect.left, w - mSensorRect.top, - mSensorRect.right); - break; - default: - // Do nothing to stay in portrait mode. - } - - if (mUdfpsAnimation != null) { - mUdfpsAnimation.onSensorRectUpdated(new RectF(mSensorRect)); - } - } - @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); - // Always re-compute the layout regardless of whether "changed" is true. It is usually false - // when the device goes from landscape to seascape and vice versa, but mSensorRect and - // its dependencies need to be recalculated to stay at the same physical location on the - // screen. - final int w = getLayoutParams().width; - final int h = getLayoutParams().height; - mScrimRect.set(0 /* left */, 0 /* top */, w, h); - updateSensorRect(h, w); - // Update mTouchableRegion with the rounded up values from mSensorRect. After "onLayout" - // is finished, mTouchableRegion will be used by mInsetsListener to compute the touch - // insets. - mSensorRect.roundOut(mTouchableRegion); + mSensorRect.set(0, 0, 2 * mSensorProps.sensorRadius, 2 * mSensorProps.sensorRadius); + if (mUdfpsAnimation != null) { + mUdfpsAnimation.onSensorRectUpdated(new RectF(mSensorRect)); + } } @Override @@ -242,8 +206,6 @@ public class UdfpsView extends SurfaceView implements DozeReceiver, // Retrieve the colors each time, since it depends on day/night mode updateColor(); - - getViewTreeObserver().addOnComputeInternalInsetsListener(mInsetsListener); } private void updateColor() { @@ -256,56 +218,51 @@ public class UdfpsView extends SurfaceView implements DozeReceiver, protected void onDetachedFromWindow() { super.onDetachedFromWindow(); Log.v(TAG, "onDetachedFromWindow"); - getViewTreeObserver().removeOnComputeInternalInsetsListener(mInsetsListener); } + /** + * Immediately draws the provided drawable on this SurfaceView's surface. + */ + private void drawImmediately(@NonNull SimpleDrawable drawable) { + Canvas canvas = null; + try { + canvas = mHolder.lockCanvas(); + drawable.draw(canvas); + } finally { + // Make sure the surface is never left in a bad state. + if (canvas != null) { + mHolder.unlockCanvasAndPost(canvas); + } + } + } + + /** + * This onDraw will not execute if setWillNotDraw(true) is called. + */ @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); - - if (mShowScrimAndDot && mIsHbmSupported) { - // Only draw the scrim if HBM is supported. - canvas.drawRect(mScrimRect, mScrimPaint); - } - - if (!TextUtils.isEmpty(mDebugMessage)) { - canvas.drawText(mDebugMessage, 0, 160, mDebugTextPaint); - } - - if (mShowScrimAndDot) { - // draw dot (white circle) - canvas.drawOval(mSensorRect, mSensorPaint); - } else { + if (!mIlluminationRequested) { + if (!TextUtils.isEmpty(mDebugMessage)) { + canvas.drawText(mDebugMessage, 0, 160, mDebugTextPaint); + } if (mUdfpsAnimation != null) { final int alpha = shouldPauseAuth() ? 255 - mNotificationPanelAlpha : 255; mUdfpsAnimation.setAlpha(alpha); mUdfpsAnimation.draw(canvas); } } - - if (mShowScrimAndDot && mRunAfterShowingScrimAndDot != null) { - post(mRunAfterShowingScrimAndDot); - mRunAfterShowingScrimAndDot = null; - } } RectF getSensorRect() { return new RectF(mSensorRect); } - void setHbmSupported(boolean value) { - mIsHbmSupported = value; - } - void setDebugMessage(String message) { mDebugMessage = message; postInvalidate(); } - void setRunAfterShowingScrimAndDot(Runnable runnable) { - mRunAfterShowingScrimAndDot = runnable; - } - boolean isValidTouch(float x, float y, float pressure) { // The X and Y coordinates of the sensor's center. final float cx = mSensorRect.centerX(); @@ -332,21 +289,41 @@ public class UdfpsView extends SurfaceView implements DozeReceiver, || mStatusBarState == FULLSCREEN_USER_SWITCHER; } - void setScrimAlpha(int alpha) { - mScrimPaint.setAlpha(alpha); + boolean isIlluminationRequested() { + return mIlluminationRequested; } - boolean isShowScrimAndDot() { - return mShowScrimAndDot; - } + void startIllumination() { + mIlluminationRequested = true; - void showScrimAndDot() { - mShowScrimAndDot = true; - invalidate(); + // Disable onDraw to prevent overriding the illumination dot with the regular UI. + setWillNotDraw(true); + + if (mHbmCallback != null && mHolder.getSurface().isValid()) { + mHbmCallback.enableHbm(mHolder.getSurface()); + } + drawImmediately(mIlluminationDotDrawable); + + if (mOnIlluminatedRunnable != null) { + // No framework API can reliably tell when a frame reaches the panel. A timeout is the + // safest solution. The frame should be displayed within 3 refresh cycles, which on a + // 60 Hz panel equates to 50 milliseconds. + postDelayed(mOnIlluminatedRunnable, 50 /* delayMillis */); + mOnIlluminatedRunnable = null; + } } - void hideScrimAndDot() { - mShowScrimAndDot = false; + void stopIllumination() { + mIlluminationRequested = false; + + if (mHbmCallback != null && mHolder.getSurface().isValid()) { + mHbmCallback.disableHbm(mHolder.getSurface()); + } + // It may be necessary to clear the surface for the HBM changes to apply. + drawImmediately(mClearSurfaceDrawable); + + // Enable onDraw to allow the regular UI to be drawn. + setWillNotDraw(false); invalidate(); } diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java index 4d697005be7b..b0067cd15c1b 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java @@ -29,6 +29,7 @@ import com.android.systemui.appops.dagger.AppOpsModule; import com.android.systemui.assist.AssistModule; import com.android.systemui.classifier.FalsingModule; import com.android.systemui.controls.dagger.ControlsModule; +import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.demomode.dagger.DemoModeModule; import com.android.systemui.doze.dagger.DozeComponent; import com.android.systemui.dump.DumpManager; @@ -75,6 +76,7 @@ import com.android.systemui.wmshell.BubblesManager; import com.android.wm.shell.bubbles.Bubbles; import java.util.Optional; +import java.util.concurrent.Executor; import dagger.Binds; import dagger.BindsOptionalOf; @@ -153,6 +155,7 @@ public abstract class SystemUIModule { @Binds abstract SystemClock bindSystemClock(SystemClockImpl systemClock); + // TODO: This should provided by the WM component /** Provides Optional of BubbleManager */ @SysUISingleton @Provides @@ -166,11 +169,12 @@ public abstract class SystemUIModule { ZenModeController zenModeController, NotificationLockscreenUserManager notifUserManager, NotificationGroupManagerLegacy groupManager, NotificationEntryManager entryManager, NotifPipeline notifPipeline, SysUiState sysUiState, FeatureFlags featureFlags, - DumpManager dumpManager) { + DumpManager dumpManager, @Main Executor sysuiMainExecutor) { return Optional.ofNullable(BubblesManager.create(context, bubblesOptional, notificationShadeWindowController, statusBarStateController, shadeController, configurationController, statusBarService, notificationManager, interruptionStateProvider, zenModeController, notifUserManager, - groupManager, entryManager, notifPipeline, sysUiState, featureFlags, dumpManager)); + groupManager, entryManager, notifPipeline, sysUiState, featureFlags, dumpManager, + sysuiMainExecutor)); } } diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java index 34d1f6e1789c..fcb5da3f8c52 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java @@ -28,6 +28,7 @@ import static android.view.InsetsState.ITYPE_NAVIGATION_BAR; import static android.view.InsetsState.containsType; import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS; import static android.view.WindowInsetsController.APPEARANCE_OPAQUE_NAVIGATION_BARS; +import static android.view.WindowInsetsController.APPEARANCE_SEMI_TRANSPARENT_NAVIGATION_BARS; import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION; import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON; @@ -994,6 +995,8 @@ public class NavigationBar implements View.OnAttachStateChangeListener, return MODE_LIGHTS_OUT_TRANSPARENT; } else if ((appearance & APPEARANCE_OPAQUE_NAVIGATION_BARS) != 0) { return MODE_OPAQUE; + } else if ((appearance & APPEARANCE_SEMI_TRANSPARENT_NAVIGATION_BARS) != 0) { + return MODE_SEMI_TRANSPARENT; } else { return MODE_TRANSPARENT; } diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialog.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialog.kt index 66c535f869f0..c3d6a848202f 100644 --- a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialog.kt +++ b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialog.kt @@ -24,7 +24,6 @@ import android.view.Gravity import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import android.view.ViewGroup.LayoutParams.MATCH_PARENT import android.view.ViewGroup.LayoutParams.WRAP_CONTENT import android.view.WindowInsets import android.widget.ImageView @@ -66,9 +65,8 @@ class PrivacyDialog( super.onCreate(savedInstanceState) window?.apply { attributes.fitInsetsTypes = attributes.fitInsetsTypes or WindowInsets.Type.statusBars() - setLayout(MATCH_PARENT, WRAP_CONTENT) + setLayout(context.resources.getDimensionPixelSize(R.dimen.qs_panel_width), WRAP_CONTENT) setGravity(Gravity.TOP or Gravity.CENTER_HORIZONTAL) - setBackgroundDrawable(null) } setContentView(R.layout.privacy_dialog) @@ -130,7 +128,7 @@ class PrivacyDialog( ) } ?: firstLine newView.requireViewById<TextView>(R.id.text).text = finalText - newView.requireViewById<View>(R.id.link).apply { + newView.apply { tag = element.type.permGroupName setOnClickListener(clickListener) } @@ -154,9 +152,7 @@ class PrivacyDialog( } private val clickListener = View.OnClickListener { v -> - if (v.id == R.id.link) { - v.tag?.let { activityStarter(it as String) } - } + v.tag?.let { activityStarter(it as String) } } /** */ diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java index d6413ed63e6e..0a7eea487ee8 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java @@ -602,7 +602,7 @@ public class ScreenshotController { private void runScrollCapture(ScrollCaptureClient.Connection connection) { cancelTimeout(); ScrollCaptureController controller = new ScrollCaptureController(mContext, connection, - mMainExecutor, mBgExecutor, mImageExporter); + mMainExecutor, mBgExecutor, mImageExporter, mUiEventLogger); controller.attach(mWindow); controller.start(new TakeScreenshotService.RequestCallback() { @Override diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotEvent.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotEvent.java index f1fb6884188f..5cf018813133 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotEvent.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotEvent.java @@ -63,7 +63,15 @@ public enum ScreenshotEvent implements UiEventLogger.UiEventEnum { @UiEvent(doc = "screenshot swiped to dismiss") SCREENSHOT_SWIPE_DISMISSED(656), @UiEvent(doc = "screenshot reentered for new screenshot") - SCREENSHOT_REENTERED(640); + SCREENSHOT_REENTERED(640), + @UiEvent(doc = "Long screenshot button was shown to the user") + SCREENSHOT_LONG_SCREENSHOT_IMPRESSION(687), + @UiEvent(doc = "User has requested a long screenshot") + SCREENSHOT_LONG_SCREENSHOT_REQUESTED(688), + @UiEvent(doc = "User has shared a long screenshot") + SCREENSHOT_LONG_SCREENSHOT_SHARE(689), + @UiEvent(doc = "User has sent a long screenshot to the editor") + SCREENSHOT_LONG_SCREENSHOT_EDIT(690); private final int mId; diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java index bf86b68893c8..3bc5ebf8c64e 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java @@ -192,14 +192,14 @@ public class ScreenshotView extends FrameLayout implements if (DEBUG_SCROLL) { Log.d(TAG, "Showing Scroll option"); } + mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_LONG_SCREENSHOT_IMPRESSION); mScrollChip.setVisibility(VISIBLE); mScrollChip.setOnClickListener((v) -> { if (DEBUG_INPUT) { Log.d(TAG, "scroll chip tapped"); } + mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_LONG_SCREENSHOT_REQUESTED); onClick.run(); - // TODO Logging, store event consumer to a field - //onElementTapped.accept(ScreenshotEvent.SCREENSHOT_SCROLL_TAPPED); }); } diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureController.java index 9be3566e1f63..176a2c78796b 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureController.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureController.java @@ -29,6 +29,7 @@ import android.view.ViewTreeObserver.OnComputeInternalInsetsListener; import android.view.Window; import android.widget.ImageView; +import com.android.internal.logging.UiEventLogger; import com.android.systemui.R; import com.android.systemui.screenshot.ScrollCaptureClient.Connection; import com.android.systemui.screenshot.ScrollCaptureClient.Session; @@ -58,6 +59,7 @@ public class ScrollCaptureController implements OnComputeInternalInsetsListener private final Executor mBgExecutor; private final ImageExporter mImageExporter; private final ImageTileSet mImageTileSet; + private final UiEventLogger mUiEventLogger; private ZonedDateTime mCaptureTime; private UUID mRequestId; @@ -72,12 +74,13 @@ public class ScrollCaptureController implements OnComputeInternalInsetsListener private Runnable mPendingAction; public ScrollCaptureController(Context context, Connection connection, Executor uiExecutor, - Executor bgExecutor, ImageExporter exporter) { + Executor bgExecutor, ImageExporter exporter, UiEventLogger uiEventLogger) { mContext = context; mConnection = connection; mUiExecutor = uiExecutor; mBgExecutor = bgExecutor; mImageExporter = exporter; + mUiEventLogger = uiEventLogger; mImageTileSet = new ImageTileSet(); } @@ -136,10 +139,12 @@ public class ScrollCaptureController implements OnComputeInternalInsetsListener disableButtons(); finish(); } else if (id == R.id.edit) { + mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_LONG_SCREENSHOT_EDIT); v.setPressed(true); disableButtons(); edit(); } else if (id == R.id.share) { + mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_LONG_SCREENSHOT_SHARE); v.setPressed(true); disableButtons(); share(); diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessControllerSettings.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessControllerSettings.java index 11ee94c97d7c..8dcc8b46f024 100644 --- a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessControllerSettings.java +++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessControllerSettings.java @@ -17,6 +17,7 @@ package com.android.systemui.settings.brightness; import com.android.systemui.dagger.SysUISingleton; +import com.android.systemui.statusbar.FeatureFlags; import com.android.systemui.util.settings.SecureSettings; import javax.inject.Inject; @@ -28,11 +29,13 @@ import javax.inject.Inject; public class BrightnessControllerSettings { private static final String THICK_BRIGHTNESS_SLIDER = "sysui_thick_brightness"; + private final FeatureFlags mFeatureFlags; private final boolean mUseThickSlider; private final boolean mUseMirrorOnThickSlider; @Inject - public BrightnessControllerSettings(SecureSettings settings) { + public BrightnessControllerSettings(SecureSettings settings, FeatureFlags featureFlags) { + mFeatureFlags = featureFlags; mUseThickSlider = settings.getInt(THICK_BRIGHTNESS_SLIDER, 0) != 0; mUseMirrorOnThickSlider = settings.getInt(THICK_BRIGHTNESS_SLIDER, 0) != 2; } @@ -41,11 +44,11 @@ public class BrightnessControllerSettings { // restart systemui after changing it. /** */ boolean useThickSlider() { - return mUseThickSlider; + return mUseThickSlider && mFeatureFlags.useNewBrightnessSlider(); } /** */ boolean useMirrorOnThickSlider() { - return mUseMirrorOnThickSlider; + return !useThickSlider() || (useThickSlider() && mUseMirrorOnThickSlider); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/FeatureFlags.java b/packages/SystemUI/src/com/android/systemui/statusbar/FeatureFlags.java index 30b31580e130..e7b60c3a0d67 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/FeatureFlags.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/FeatureFlags.java @@ -61,4 +61,13 @@ public class FeatureFlags { public boolean isKeyguardLayoutEnabled() { return mFlagReader.isEnabled(R.bool.flag_keyguard_layout); } + + /** b/178485354 */ + public boolean useNewBrightnessSlider() { + return mFlagReader.isEnabled(R.bool.flag_brightness_slider); + } + + public boolean isPeopleTileEnabled() { + return mFlagReader.isEnabled(R.bool.flag_conversations); + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java index 7f30009cda6f..6023b7f6f4f7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java @@ -26,25 +26,41 @@ import android.graphics.PorterDuff; import android.graphics.PorterDuff.Mode; import android.graphics.PorterDuffColorFilter; import android.graphics.drawable.Drawable; +import android.os.Handler; +import android.os.Looper; import android.util.AttributeSet; import android.view.View; import androidx.core.graphics.ColorUtils; +import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.colorextraction.ColorExtractor; import com.android.internal.colorextraction.drawable.ScrimDrawable; +import java.util.concurrent.Executor; + + /** - * A view which can draw a scrim + * A view which can draw a scrim. This view maybe be used in multiple windows running on different + * threads, but is controlled by {@link com.android.systemui.statusbar.phone.ScrimController} so we + * need to be careful to synchronize when necessary. */ public class ScrimView extends View { + private final Object mColorLock = new Object(); + + @GuardedBy("mColorLock") private final ColorExtractor.GradientColors mColors; + // Used only for returning the colors + private final ColorExtractor.GradientColors mTmpColors = new ColorExtractor.GradientColors(); private float mViewAlpha = 1.0f; private Drawable mDrawable; private PorterDuffColorFilter mColorFilter; private int mTintColor; private Runnable mChangeRunnable; + private Executor mChangeRunnableExecutor; + private Executor mExecutor; + private Looper mExecutorLooper; public ScrimView(Context context) { this(context, null); @@ -64,7 +80,16 @@ public class ScrimView extends View { mDrawable = new ScrimDrawable(); mDrawable.setCallback(this); mColors = new ColorExtractor.GradientColors(); - updateColorWithTint(false); + mExecutorLooper = Looper.myLooper(); + mExecutor = Runnable::run; + executeOnExecutor(() -> { + updateColorWithTint(false); + }); + } + + public void setExecutor(Executor executor, Looper looper) { + mExecutor = executor; + mExecutorLooper = looper; } @Override @@ -75,11 +100,13 @@ public class ScrimView extends View { } public void setDrawable(Drawable drawable) { - mDrawable = drawable; - mDrawable.setCallback(this); - mDrawable.setBounds(getLeft(), getTop(), getRight(), getBottom()); - mDrawable.setAlpha((int) (255 * mViewAlpha)); - invalidate(); + executeOnExecutor(() -> { + mDrawable = drawable; + mDrawable.setCallback(this); + mDrawable.setBounds(getLeft(), getTop(), getRight(), getBottom()); + mDrawable.setAlpha((int) (255 * mViewAlpha)); + invalidate(); + }); } @Override @@ -99,6 +126,13 @@ public class ScrimView extends View { } } + @Override + public void setClickable(boolean clickable) { + executeOnExecutor(() -> { + super.setClickable(clickable); + }); + } + public void setColors(@NonNull ColorExtractor.GradientColors colors) { setColors(colors, false); } @@ -107,11 +141,15 @@ public class ScrimView extends View { if (colors == null) { throw new IllegalArgumentException("Colors cannot be null"); } - if (mColors.equals(colors)) { - return; - } - mColors.set(colors); - updateColorWithTint(animated); + executeOnExecutor(() -> { + synchronized(mColorLock) { + if (mColors.equals(colors)) { + return; + } + mColors.set(colors); + } + updateColorWithTint(animated); + }); } @VisibleForTesting @@ -120,7 +158,10 @@ public class ScrimView extends View { } public ColorExtractor.GradientColors getColors() { - return mColors; + synchronized(mColorLock) { + mTmpColors.set(mColors); + } + return mTmpColors; } public void setTint(int color) { @@ -128,11 +169,13 @@ public class ScrimView extends View { } public void setTint(int color, boolean animated) { - if (mTintColor == color) { - return; - } - mTintColor = color; - updateColorWithTint(animated); + executeOnExecutor(() -> { + if (mTintColor == color) { + return; + } + mTintColor = color; + updateColorWithTint(animated); + }); } private void updateColorWithTint(boolean animated) { @@ -160,7 +203,7 @@ public class ScrimView extends View { } if (mChangeRunnable != null) { - mChangeRunnable.run(); + mChangeRunnableExecutor.execute(mChangeRunnable); } } @@ -184,26 +227,37 @@ public class ScrimView extends View { if (isNaN(alpha)) { throw new IllegalArgumentException("alpha cannot be NaN: " + alpha); } - if (alpha != mViewAlpha) { - mViewAlpha = alpha; + executeOnExecutor(() -> { + if (alpha != mViewAlpha) { + mViewAlpha = alpha; - mDrawable.setAlpha((int) (255 * alpha)); - if (mChangeRunnable != null) { - mChangeRunnable.run(); + mDrawable.setAlpha((int) (255 * alpha)); + if (mChangeRunnable != null) { + mChangeRunnableExecutor.execute(mChangeRunnable); + } } - } + }); } public float getViewAlpha() { return mViewAlpha; } - public void setChangeRunnable(Runnable changeRunnable) { + public void setChangeRunnable(Runnable changeRunnable, Executor changeRunnableExecutor) { mChangeRunnable = changeRunnable; + mChangeRunnableExecutor = changeRunnableExecutor; } @Override protected boolean canReceivePointerEvents() { return false; } + + private void executeOnExecutor(Runnable r) { + if (mExecutor == null || Looper.myLooper() == mExecutorLooper) { + r.run(); + } else { + mExecutor.execute(r); + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SuperStatusBarViewFactory.java b/packages/SystemUI/src/com/android/systemui/statusbar/SuperStatusBarViewFactory.java index 1ec043cb7670..e4ae560ba69b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/SuperStatusBarViewFactory.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/SuperStatusBarViewFactory.java @@ -23,8 +23,6 @@ import android.view.ViewGroup; import com.android.systemui.R; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.statusbar.notification.row.dagger.NotificationShelfComponent; -import com.android.systemui.statusbar.phone.LockIcon; -import com.android.systemui.statusbar.phone.LockscreenLockIconController; import com.android.systemui.statusbar.phone.NotificationPanelView; import com.android.systemui.statusbar.phone.NotificationShadeWindowView; import com.android.systemui.statusbar.phone.StatusBarWindowView; @@ -41,7 +39,6 @@ public class SuperStatusBarViewFactory { private final Context mContext; private final InjectionInflationController mInjectionInflationController; - private final LockscreenLockIconController mLockIconController; private final NotificationShelfComponent.Builder mNotificationShelfComponentBuilder; private NotificationShadeWindowView mNotificationShadeWindowView; @@ -51,11 +48,9 @@ public class SuperStatusBarViewFactory { @Inject public SuperStatusBarViewFactory(Context context, InjectionInflationController injectionInflationController, - NotificationShelfComponent.Builder notificationShelfComponentBuilder, - LockscreenLockIconController lockIconController) { + NotificationShelfComponent.Builder notificationShelfComponentBuilder) { mContext = context; mInjectionInflationController = injectionInflationController; - mLockIconController = lockIconController; mNotificationShelfComponentBuilder = notificationShelfComponentBuilder; } @@ -77,10 +72,6 @@ public class SuperStatusBarViewFactory { throw new IllegalStateException( "R.layout.super_notification_shade could not be properly inflated"); } - LockIcon lockIcon = mNotificationShadeWindowView.findViewById(R.id.lock_icon); - if (lockIcon != null) { - mLockIconController.attach(lockIcon); - } return mNotificationShadeWindowView; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/NotifPipelineInitializer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/NotifPipelineInitializer.java index 4fde1187477c..db49e4476a99 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/NotifPipelineInitializer.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/NotifPipelineInitializer.java @@ -21,7 +21,6 @@ import android.util.Log; import com.android.systemui.Dumpable; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dump.DumpManager; -import com.android.systemui.people.widget.PeopleSpaceWidgetManager; import com.android.systemui.statusbar.FeatureFlags; import com.android.systemui.statusbar.NotificationListener; import com.android.systemui.statusbar.notification.collection.NotifCollection; @@ -50,7 +49,6 @@ public class NotifPipelineInitializer implements Dumpable { private final ShadeListBuilder mListBuilder; private final NotifCoordinators mNotifPluggableCoordinators; private final NotifInflaterImpl mNotifInflater; - private final PeopleSpaceWidgetManager mPeopleSpaceWidgetManager; private final DumpManager mDumpManager; private final ShadeViewManagerFactory mShadeViewManagerFactory; private final FeatureFlags mFeatureFlags; @@ -64,7 +62,6 @@ public class NotifPipelineInitializer implements Dumpable { ShadeListBuilder listBuilder, NotifCoordinators notifCoordinators, NotifInflaterImpl notifInflater, - PeopleSpaceWidgetManager peopleSpaceWidgetManager, DumpManager dumpManager, ShadeViewManagerFactory shadeViewManagerFactory, FeatureFlags featureFlags) { @@ -75,7 +72,6 @@ public class NotifPipelineInitializer implements Dumpable { mNotifPluggableCoordinators = notifCoordinators; mDumpManager = dumpManager; mNotifInflater = notifInflater; - mPeopleSpaceWidgetManager = peopleSpaceWidgetManager; mShadeViewManagerFactory = shadeViewManagerFactory; mFeatureFlags = featureFlags; } @@ -103,7 +99,6 @@ public class NotifPipelineInitializer implements Dumpable { mListBuilder.attach(mNotifCollection); mNotifCollection.attach(mGroupCoalescer); mGroupCoalescer.attach(notificationService); - mPeopleSpaceWidgetManager.attach(notificationService); Log.d(TAG, "Notif pipeline initialized"); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt index 54ce4ede9770..0ad6507fb01e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt @@ -18,6 +18,7 @@ package com.android.systemui.statusbar.notification.init import android.service.notification.StatusBarNotification import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.people.widget.PeopleSpaceWidgetManager import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption import com.android.systemui.statusbar.FeatureFlags import com.android.systemui.statusbar.NotificationListener @@ -73,7 +74,8 @@ class NotificationsControllerImpl @Inject constructor( private val headsUpController: HeadsUpController, private val headsUpViewBinder: HeadsUpViewBinder, private val clickerBuilder: NotificationClicker.Builder, - private val animatedImageNotificationManager: AnimatedImageNotificationManager + private val animatedImageNotificationManager: AnimatedImageNotificationManager, + private val peopleSpaceWidgetManager: PeopleSpaceWidgetManager ) : NotificationsController { override fun initialize( @@ -126,6 +128,10 @@ class NotificationsControllerImpl @Inject constructor( entryManager.attach(notificationListener) } + + if (featureFlags.isPeopleTileEnabled) { + peopleSpaceWidgetManager.attach(notificationListener) + } } override fun dump( diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java index e1eaf3c17357..f289b9f20211 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java @@ -71,7 +71,7 @@ public final class DozeServiceHost implements DozeHost { "persist.sysui.wake_performs_auth", true); private boolean mDozingRequested; private boolean mPulsing; - private WakefulnessLifecycle mWakefulnessLifecycle; + private final WakefulnessLifecycle mWakefulnessLifecycle; private final SysuiStatusBarStateController mStatusBarStateController; private final DeviceProvisionedController mDeviceProvisionedController; private final HeadsUpManagerPhone mHeadsUpManagerPhone; @@ -86,9 +86,8 @@ public final class DozeServiceHost implements DozeHost { private final NotificationShadeWindowController mNotificationShadeWindowController; private final NotificationWakeUpCoordinator mNotificationWakeUpCoordinator; private NotificationShadeWindowViewController mNotificationShadeWindowViewController; - private final LockscreenLockIconController mLockscreenLockIconController; private final AuthController mAuthController; - private NotificationIconAreaController mNotificationIconAreaController; + private final NotificationIconAreaController mNotificationIconAreaController; private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; private NotificationPanelViewController mNotificationPanel; private View mAmbientIndicationContainer; @@ -109,7 +108,6 @@ public final class DozeServiceHost implements DozeHost { PulseExpansionHandler pulseExpansionHandler, NotificationShadeWindowController notificationShadeWindowController, NotificationWakeUpCoordinator notificationWakeUpCoordinator, - LockscreenLockIconController lockscreenLockIconController, AuthController authController, NotificationIconAreaController notificationIconAreaController) { super(); @@ -129,7 +127,6 @@ public final class DozeServiceHost implements DozeHost { mPulseExpansionHandler = pulseExpansionHandler; mNotificationShadeWindowController = notificationShadeWindowController; mNotificationWakeUpCoordinator = notificationWakeUpCoordinator; - mLockscreenLockIconController = lockscreenLockIconController; mAuthController = authController; mNotificationIconAreaController = notificationIconAreaController; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenLockIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenLockIconController.java index eceac3240ebc..4b70de997906 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenLockIconController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenLockIconController.java @@ -37,12 +37,10 @@ import androidx.annotation.Nullable; import com.android.internal.logging.nano.MetricsProto; import com.android.internal.widget.LockPatternUtils; -import com.android.keyguard.KeyguardSecurityModel; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.KeyguardUpdateMonitorCallback; import com.android.settingslib.Utils; import com.android.systemui.R; -import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dock.DockManager; import com.android.systemui.plugins.statusbar.StatusBarStateController; @@ -52,18 +50,20 @@ import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator; import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator.WakeUpListener; import com.android.systemui.statusbar.phone.LockscreenGestureLogger.LockscreenUiEvent; +import com.android.systemui.statusbar.phone.dagger.StatusBarComponent; import com.android.systemui.statusbar.policy.AccessibilityController; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener; import com.android.systemui.statusbar.policy.KeyguardStateController; +import com.android.systemui.util.ViewController; import java.util.Optional; import javax.inject.Inject; -/** Controls the {@link LockIcon} in the lockscreen. */ -@SysUISingleton -public class LockscreenLockIconController { +/** Controls the {@link LockIcon} on the lockscreen. */ +@StatusBarComponent.StatusBarScope +public class LockscreenLockIconController extends ViewController<LockIcon> { private final LockscreenGestureLogger mLockscreenGestureLogger; private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; @@ -79,7 +79,6 @@ public class LockscreenLockIconController { private final KeyguardStateController mKeyguardStateController; private final Resources mResources; private final HeadsUpManagerPhone mHeadsUpManagerPhone; - private final KeyguardSecurityModel mKeyguardSecurityModel; private boolean mKeyguardShowing; private boolean mKeyguardJustShown; private boolean mBlockUpdates; @@ -92,231 +91,13 @@ public class LockscreenLockIconController { private boolean mBouncerShowingScrimmed; private boolean mFingerprintUnlock; private int mStatusBarState = StatusBarState.SHADE; - private LockIcon mLockIcon; - - private View.OnAttachStateChangeListener mOnAttachStateChangeListener = - new View.OnAttachStateChangeListener() { - @Override - public void onViewAttachedToWindow(View v) { - mStatusBarStateController.addCallback(mSBStateListener); - mConfigurationController.addCallback(mConfigurationListener); - mNotificationWakeUpCoordinator.addListener(mWakeUpListener); - mKeyguardUpdateMonitor.registerCallback(mUpdateMonitorCallback); - mKeyguardStateController.addCallback(mKeyguardMonitorCallback); - - mDockManager.ifPresent(dockManager -> dockManager.addListener(mDockEventListener)); - - mSimLocked = mKeyguardUpdateMonitor.isSimPinSecure(); - mConfigurationListener.onThemeChanged(); - - updateColor(); - update(); - } - - @Override - public void onViewDetachedFromWindow(View v) { - mStatusBarStateController.removeCallback(mSBStateListener); - mConfigurationController.removeCallback(mConfigurationListener); - mNotificationWakeUpCoordinator.removeListener(mWakeUpListener); - mKeyguardUpdateMonitor.removeCallback(mUpdateMonitorCallback); - mKeyguardStateController.removeCallback(mKeyguardMonitorCallback); - - mDockManager.ifPresent(dockManager -> dockManager.removeListener(mDockEventListener)); - } - }; - - private final StatusBarStateController.StateListener mSBStateListener = - new StatusBarStateController.StateListener() { - @Override - public void onDozingChanged(boolean isDozing) { - setDozing(isDozing); - } - - @Override - public void onDozeAmountChanged(float linear, float eased) { - if (mLockIcon != null) { - mLockIcon.setDozeAmount(eased); - } - } - - @Override - public void onStateChanged(int newState) { - setStatusBarState(newState); - } - }; - - private final ConfigurationListener mConfigurationListener = new ConfigurationListener() { - private int mDensity; - - @Override - public void onUiModeChanged() { - updateColor(); - } - - @Override - public void onOverlayChanged() { - updateColor(); - } - - @Override - public void onDensityOrFontScaleChanged() { - if (mLockIcon == null) { - return; - } - - ViewGroup.LayoutParams lp = mLockIcon.getLayoutParams(); - if (lp == null) { - return; - } - lp.width = mLockIcon.getResources().getDimensionPixelSize(R.dimen.keyguard_lock_width); - lp.height = mLockIcon.getResources().getDimensionPixelSize( - R.dimen.keyguard_lock_height); - mLockIcon.setLayoutParams(lp); - update(true /* force */); - } - - @Override - public void onLocaleListChanged() { - if (mLockIcon == null) { - return; - } - - mLockIcon.setContentDescription( - mLockIcon.getResources().getText(R.string.accessibility_unlock_button)); - update(true /* force */); - } - - @Override - public void onConfigChanged(Configuration newConfig) { - final int density = newConfig.densityDpi; - if (density != mDensity) { - mDensity = density; - update(); - } - } - }; - - private final WakeUpListener mWakeUpListener = new WakeUpListener() { - @Override - public void onPulseExpansionChanged(boolean expandingChanged) { - } - - @Override - public void onFullyHiddenChanged(boolean isFullyHidden) { - if (mKeyguardBypassController.getBypassEnabled()) { - boolean changed = updateIconVisibility(); - if (changed) { - update(); - } - } - } - }; - - private final KeyguardUpdateMonitorCallback mUpdateMonitorCallback = - new KeyguardUpdateMonitorCallback() { - @Override - public void onSimStateChanged(int subId, int slotId, int simState) { - mSimLocked = mKeyguardUpdateMonitor.isSimPinSecure(); - update(); - } - - @Override - public void onKeyguardVisibilityChanged(boolean showing) { - update(); - } - - @Override - public void onBiometricRunningStateChanged(boolean running, - BiometricSourceType biometricSourceType) { - update(); - } - - @Override - public void onStrongAuthStateChanged(int userId) { - update(); - } - }; - - private final DockManager.DockEventListener mDockEventListener = - event -> { - boolean docked = - event == DockManager.STATE_DOCKED || event == DockManager.STATE_DOCKED_HIDE; - if (docked != mDocked) { - mDocked = docked; - update(); - } - }; - - private final KeyguardStateController.Callback mKeyguardMonitorCallback = - new KeyguardStateController.Callback() { - @Override - public void onKeyguardShowingChanged() { - boolean force = false; - boolean wasShowing = mKeyguardShowing; - mKeyguardShowing = mKeyguardStateController.isShowing(); - if (!wasShowing && mKeyguardShowing && mBlockUpdates) { - mBlockUpdates = false; - force = true; - } - if (!wasShowing && mKeyguardShowing) { - setBouncerHideAmount(KeyguardBouncer.EXPANSION_HIDDEN); - mKeyguardJustShown = true; - } - update(force); - } - - @Override - public void onKeyguardFadingAwayChanged() { - if (!mKeyguardStateController.isKeyguardFadingAway()) { - if (mBlockUpdates) { - mBlockUpdates = false; - update(true /* force */); - } - } - } - - @Override - public void onUnlockedChanged() { - update(); - } - }; - - private final View.AccessibilityDelegate mAccessibilityDelegate = - new View.AccessibilityDelegate() { - @Override - public void onInitializeAccessibilityNodeInfo(View host, - AccessibilityNodeInfo info) { - super.onInitializeAccessibilityNodeInfo(host, info); - boolean fingerprintRunning = - mKeyguardUpdateMonitor.isFingerprintDetectionRunning(); - // Only checking if unlocking with Biometric is allowed (no matter strong or - // non-strong as long as primary auth, i.e. PIN/pattern/password, is not - // required), so it's ok to pass true for isStrongBiometric to - // isUnlockingWithBiometricAllowed() to bypass the check of whether non-strong - // biometric is allowed - boolean unlockingAllowed = mKeyguardUpdateMonitor - .isUnlockingWithBiometricAllowed(true /* isStrongBiometric */); - if (fingerprintRunning && unlockingAllowed) { - AccessibilityNodeInfo.AccessibilityAction unlock = - new AccessibilityNodeInfo.AccessibilityAction( - AccessibilityNodeInfo.ACTION_CLICK, - mResources.getString( - R.string.accessibility_unlock_without_fingerprint)); - info.addAction(unlock); - info.setHintText(mResources.getString( - R.string.accessibility_waiting_for_fingerprint)); - } else if (getState() == STATE_SCANNING_FACE) { - //Avoid 'button' to be spoken for scanning face - info.setClassName(LockIcon.class.getName()); - info.setContentDescription(mResources.getString( - R.string.accessibility_scanning_face)); - } - } - }; private int mLastState; + private boolean mDozing; @Inject - public LockscreenLockIconController(LockscreenGestureLogger lockscreenGestureLogger, + public LockscreenLockIconController( + @Nullable LockIcon view, + LockscreenGestureLogger lockscreenGestureLogger, KeyguardUpdateMonitor keyguardUpdateMonitor, LockPatternUtils lockPatternUtils, ShadeController shadeController, @@ -329,8 +110,8 @@ public class LockscreenLockIconController { @Nullable DockManager dockManager, KeyguardStateController keyguardStateController, @Main Resources resources, - HeadsUpManagerPhone headsUpManagerPhone, - KeyguardSecurityModel keyguardSecurityModel) { + HeadsUpManagerPhone headsUpManagerPhone) { + super(view); mLockscreenGestureLogger = lockscreenGestureLogger; mKeyguardUpdateMonitor = keyguardUpdateMonitor; mLockPatternUtils = lockPatternUtils; @@ -345,32 +126,52 @@ public class LockscreenLockIconController { mKeyguardStateController = keyguardStateController; mResources = resources; mHeadsUpManagerPhone = headsUpManagerPhone; - mKeyguardSecurityModel = keyguardSecurityModel; + + if (view == null) { + return; + } mKeyguardIndicationController.setLockIconController(this); } - /** - * Associate the controller with a {@link LockIcon} - * - * TODO: change to an init method and inject the view. - */ - public void attach(LockIcon lockIcon) { - mLockIcon = lockIcon; - - mLockIcon.setOnClickListener(this::handleClick); - mLockIcon.setOnLongClickListener(this::handleLongClick); - mLockIcon.setAccessibilityDelegate(mAccessibilityDelegate); - - if (mLockIcon.isAttachedToWindow()) { - mOnAttachStateChangeListener.onViewAttachedToWindow(mLockIcon); + @Override + protected void onInit() { + if (mView == null) { + return; } - mLockIcon.addOnAttachStateChangeListener(mOnAttachStateChangeListener); + mView.setOnClickListener(this::handleClick); + mView.setOnLongClickListener(this::handleLongClick); + mView.setAccessibilityDelegate(mAccessibilityDelegate); + } + + @Override + protected void onViewAttached() { setStatusBarState(mStatusBarStateController.getState()); + mDozing = mStatusBarStateController.isDozing(); + mStatusBarStateController.addCallback(mSBStateListener); + mConfigurationController.addCallback(mConfigurationListener); + mNotificationWakeUpCoordinator.addListener(mWakeUpListener); + mKeyguardUpdateMonitor.registerCallback(mUpdateMonitorCallback); + mKeyguardStateController.addCallback(mKeyguardMonitorCallback); + + mDockManager.ifPresent(dockManager -> dockManager.addListener(mDockEventListener)); + + mSimLocked = mKeyguardUpdateMonitor.isSimPinSecure(); + mConfigurationListener.onThemeChanged(); + + updateColor(); + update(); } - public LockIcon getView() { - return mLockIcon; + @Override + protected void onViewDetached() { + mStatusBarStateController.removeCallback(mSBStateListener); + mConfigurationController.removeCallback(mConfigurationListener); + mNotificationWakeUpCoordinator.removeListener(mWakeUpListener); + mKeyguardUpdateMonitor.removeCallback(mUpdateMonitorCallback); + mKeyguardStateController.removeCallback(mKeyguardMonitorCallback); + + mDockManager.ifPresent(dockManager -> dockManager.removeListener(mDockEventListener)); } /** @@ -430,31 +231,30 @@ public class LockscreenLockIconController { } private void updateColor() { - if (mLockIcon == null) { + if (mView == null) { return; } - int iconColor = -1; if (mBouncerHiddenAmount == KeyguardBouncer.EXPANSION_VISIBLE) { - TypedArray typedArray = mLockIcon.getContext().getTheme().obtainStyledAttributes( + TypedArray typedArray = mView.getContext().getTheme().obtainStyledAttributes( null, new int[]{ android.R.attr.textColorPrimary }, 0, 0); iconColor = typedArray.getColor(0, Color.WHITE); typedArray.recycle(); } else if (mBouncerHiddenAmount == KeyguardBouncer.EXPANSION_HIDDEN) { iconColor = Utils.getColorAttrDefaultColor( - mLockIcon.getContext(), com.android.systemui.R.attr.wallpaperTextColor); + mView.getContext(), com.android.systemui.R.attr.wallpaperTextColor); } else { // bouncer is transitioning - TypedArray typedArray = mLockIcon.getContext().getTheme().obtainStyledAttributes( + TypedArray typedArray = mView.getContext().getTheme().obtainStyledAttributes( null, new int[]{ android.R.attr.textColorPrimary }, 0, 0); int bouncerIconColor = typedArray.getColor(0, Color.WHITE); typedArray.recycle(); int keyguardIconColor = Utils.getColorAttrDefaultColor( - mLockIcon.getContext(), com.android.systemui.R.attr.wallpaperTextColor); + mView.getContext(), com.android.systemui.R.attr.wallpaperTextColor); iconColor = (int) new ArgbEvaluator().evaluate( mBouncerHiddenAmount, bouncerIconColor, keyguardIconColor); } - mLockIcon.updateColor(iconColor); + mView.updateColor(iconColor); } /** @@ -497,14 +297,16 @@ public class LockscreenLockIconController { } private void update(boolean force) { + if (mView == null) { + return; + } int state = getState(); boolean shouldUpdate = mLastState != state || force; if (mBlockUpdates && canBlockUpdates()) { shouldUpdate = false; } - if (shouldUpdate && mLockIcon != null && mLockIcon.getVisibility() != GONE) { - mLockIcon.update(state, - mStatusBarStateController.isDozing(), mKeyguardJustShown); + if (shouldUpdate && mView.getVisibility() != GONE) { + mView.update(state, mDozing, mKeyguardJustShown); } mLastState = state; mKeyguardJustShown = false; @@ -531,10 +333,6 @@ public class LockscreenLockIconController { return mKeyguardShowing || mKeyguardStateController.isKeyguardFadingAway(); } - private void setDozing(boolean isDozing) { - update(); - } - /** Set the StatusBarState. */ private void setStatusBarState(int statusBarState) { mStatusBarState = statusBarState; @@ -546,17 +344,16 @@ public class LockscreenLockIconController { * @return true if the visibility changed */ private boolean updateIconVisibility() { - if (mLockIcon == null) { + if (mView == null) { return false; } - - if (!mKeyguardUpdateMonitor.shouldShowLockIcon()) { - boolean changed = mLockIcon.getVisibility() != GONE; - mLockIcon.setVisibility(GONE); + if (!mKeyguardUpdateMonitor.canShowLockIcon()) { + boolean changed = mView.getVisibility() != GONE; + mView.setVisibility(GONE); return changed; } - boolean onAodOrDocked = mStatusBarStateController.isDozing() || mDocked; + boolean onAodOrDocked = mDozing || mDocked; boolean invisible = onAodOrDocked || mWakeAndUnlockRunning || mShowingLaunchAffordance; boolean fingerprintOrBypass = mFingerprintUnlock || mKeyguardBypassController.getBypassEnabled(); @@ -569,21 +366,202 @@ public class LockscreenLockIconController { invisible = true; } } - return mLockIcon.updateIconVisibility(!invisible); + return mView.updateIconVisibility(!invisible); } private void updateClickability() { - if (mAccessibilityController == null) { + if (mView == null) { return; } boolean canLock = mKeyguardStateController.isMethodSecure() && mKeyguardStateController.canDismissLockScreen(); boolean clickToUnlock = mAccessibilityController.isAccessibilityEnabled(); - if (mLockIcon != null) { - mLockIcon.setClickable(clickToUnlock); - mLockIcon.setLongClickable(canLock && !clickToUnlock); - mLockIcon.setFocusable(mAccessibilityController.isAccessibilityEnabled()); - } + mView.setClickable(clickToUnlock); + mView.setLongClickable(canLock && !clickToUnlock); + mView.setFocusable(mAccessibilityController.isAccessibilityEnabled()); } + private final StatusBarStateController.StateListener mSBStateListener = + new StatusBarStateController.StateListener() { + @Override + public void onDozingChanged(boolean isDozing) { + if (mDozing != isDozing) { + mDozing = isDozing; + update(); + } + } + + @Override + public void onDozeAmountChanged(float linear, float eased) { + if (mView != null) { + mView.setDozeAmount(eased); + } + } + + @Override + public void onStateChanged(int newState) { + setStatusBarState(newState); + } + }; + + private final ConfigurationListener mConfigurationListener = new ConfigurationListener() { + private int mDensity; + + @Override + public void onUiModeChanged() { + updateColor(); + } + + @Override + public void onOverlayChanged() { + updateColor(); + } + + @Override + public void onDensityOrFontScaleChanged() { + ViewGroup.LayoutParams lp = mView.getLayoutParams(); + if (lp == null) { + return; + } + lp.width = mView.getResources().getDimensionPixelSize(R.dimen.keyguard_lock_width); + lp.height = mView.getResources().getDimensionPixelSize( + R.dimen.keyguard_lock_height); + mView.setLayoutParams(lp); + update(true /* force */); + } + + @Override + public void onLocaleListChanged() { + mView.setContentDescription( + mView.getResources().getText(R.string.accessibility_unlock_button)); + update(true /* force */); + } + + @Override + public void onConfigChanged(Configuration newConfig) { + final int density = newConfig.densityDpi; + if (density != mDensity) { + mDensity = density; + update(); + } + } + }; + + private final WakeUpListener mWakeUpListener = new WakeUpListener() { + @Override + public void onPulseExpansionChanged(boolean expandingChanged) { + } + + @Override + public void onFullyHiddenChanged(boolean isFullyHidden) { + if (mKeyguardBypassController.getBypassEnabled()) { + boolean changed = updateIconVisibility(); + if (changed) { + update(); + } + } + } + }; + + private final KeyguardUpdateMonitorCallback mUpdateMonitorCallback = + new KeyguardUpdateMonitorCallback() { + @Override + public void onSimStateChanged(int subId, int slotId, int simState) { + mSimLocked = mKeyguardUpdateMonitor.isSimPinSecure(); + update(); + } + + @Override + public void onKeyguardVisibilityChanged(boolean showing) { + update(); + } + + @Override + public void onBiometricRunningStateChanged(boolean running, + BiometricSourceType biometricSourceType) { + update(); + } + + @Override + public void onStrongAuthStateChanged(int userId) { + update(); + } + }; + + private final DockManager.DockEventListener mDockEventListener = + event -> { + boolean docked = + event == DockManager.STATE_DOCKED || event == DockManager.STATE_DOCKED_HIDE; + if (docked != mDocked) { + mDocked = docked; + update(); + } + }; + + private final KeyguardStateController.Callback mKeyguardMonitorCallback = + new KeyguardStateController.Callback() { + @Override + public void onKeyguardShowingChanged() { + boolean force = false; + boolean wasShowing = mKeyguardShowing; + mKeyguardShowing = mKeyguardStateController.isShowing(); + if (!wasShowing && mKeyguardShowing && mBlockUpdates) { + mBlockUpdates = false; + force = true; + } + if (!wasShowing && mKeyguardShowing) { + setBouncerHideAmount(KeyguardBouncer.EXPANSION_HIDDEN); + mKeyguardJustShown = true; + } + update(force); + } + + @Override + public void onKeyguardFadingAwayChanged() { + if (!mKeyguardStateController.isKeyguardFadingAway()) { + if (mBlockUpdates) { + mBlockUpdates = false; + update(true /* force */); + } + } + } + + @Override + public void onUnlockedChanged() { + update(); + } + }; + + private final View.AccessibilityDelegate mAccessibilityDelegate = + new View.AccessibilityDelegate() { + @Override + public void onInitializeAccessibilityNodeInfo(View host, + AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(host, info); + boolean fingerprintRunning = + mKeyguardUpdateMonitor.isFingerprintDetectionRunning(); + // Only checking if unlocking with Biometric is allowed (no matter strong or + // non-strong as long as primary auth, i.e. PIN/pattern/password, is not + // required), so it's ok to pass true for isStrongBiometric to + // isUnlockingWithBiometricAllowed() to bypass the check of whether non-strong + // biometric is allowed + boolean unlockingAllowed = mKeyguardUpdateMonitor + .isUnlockingWithBiometricAllowed(true /* isStrongBiometric */); + if (fingerprintRunning && unlockingAllowed) { + AccessibilityNodeInfo.AccessibilityAction unlock = + new AccessibilityNodeInfo.AccessibilityAction( + AccessibilityNodeInfo.ACTION_CLICK, + mResources.getString( + R.string.accessibility_unlock_without_fingerprint)); + info.addAction(unlock); + info.setHintText(mResources.getString( + R.string.accessibility_waiting_for_fingerprint)); + } else if (getState() == STATE_SCANNING_FACE) { + //Avoid 'button' to be spoken for scanning face + info.setClassName(LockIcon.class.getName()); + info.setContentDescription(mResources.getString( + R.string.accessibility_scanning_face)); + } + } + }; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java index b24d0e7762ad..a5284f1421a7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java @@ -910,7 +910,7 @@ public class NotificationPanelViewController extends PanelViewController { clockPreferredY, hasCustomClock(), hasVisibleNotifications, mInterpolatedDarkAmount, mEmptyDragAmount, bypassEnabled, getUnlockedStackScrollerPadding(), - mUpdateMonitor.shouldShowLockIcon(), + mUpdateMonitor.canShowLockIcon(), getQsExpansionFraction(), mDisplayCutoutTopInset); mClockPositionAlgorithm.run(mClockPositionResult); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java index 19c0b6dc193a..e39065b6cc04 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java @@ -48,6 +48,7 @@ import com.android.systemui.DejankUtils; import com.android.systemui.Dumpable; import com.android.systemui.R; import com.android.systemui.dagger.SysUISingleton; +import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dock.DockManager; import com.android.systemui.statusbar.BlurUtils; import com.android.systemui.statusbar.FeatureFlags; @@ -65,6 +66,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.Executor; import java.util.function.Consumer; import javax.inject.Inject; @@ -150,6 +152,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump private final AlarmTimeout mTimeTicker; private final KeyguardVisibilityCallback mKeyguardVisibilityCallback; private final Handler mHandler; + private final Executor mMainExecutor; private final BlurUtils mBlurUtils; private GradientColors mColors; @@ -214,8 +217,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump DelayedWakeLock.Builder delayedWakeLockBuilder, Handler handler, KeyguardUpdateMonitor keyguardUpdateMonitor, DockManager dockManager, BlurUtils blurUtils, ConfigurationController configurationController, - FeatureFlags featureFlags) { - + FeatureFlags featureFlags, @Main Executor mainExecutor) { mScrimStateListener = lightBarController::setScrimState; mDefaultScrimAlpha = featureFlags.isShadeOpaque() ? BUSY_SCRIM_ALPHA : GAR_SCRIM_ALPHA; ScrimState.BUBBLE_EXPANDED.setBubbleAlpha(featureFlags.isShadeOpaque() @@ -228,6 +230,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump mKeyguardUpdateMonitor = keyguardUpdateMonitor; mKeyguardVisibilityCallback = new KeyguardVisibilityCallback(); mHandler = handler; + mMainExecutor = mainExecutor; mTimeTicker = new AlarmTimeout(alarmManager, this::onHideWallpaperTimeout, "hide_aod_wallpaper", mHandler); mWakeLock = delayedWakeLockBuilder.setHandler(mHandler).setTag("Scrims").build(); @@ -273,7 +276,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump updateThemeColors(); if (mScrimBehindChangeRunnable != null) { - mScrimBehind.setChangeRunnable(mScrimBehindChangeRunnable); + mScrimBehind.setChangeRunnable(mScrimBehindChangeRunnable, mMainExecutor); mScrimBehindChangeRunnable = null; } @@ -1022,7 +1025,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump if (mScrimBehind == null) { mScrimBehindChangeRunnable = changeRunnable; } else { - mScrimBehind.setChangeRunnable(changeRunnable); + mScrimBehind.setChangeRunnable(changeRunnable, mMainExecutor); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index b20c45780183..4a3d8d67e85d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -26,6 +26,7 @@ import static android.view.InsetsState.ITYPE_STATUS_BAR; import static android.view.InsetsState.containsType; import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS; import static android.view.WindowInsetsController.APPEARANCE_OPAQUE_STATUS_BARS; +import static android.view.WindowInsetsController.APPEARANCE_SEMI_TRANSPARENT_STATUS_BARS; import static androidx.lifecycle.Lifecycle.State.RESUMED; @@ -367,7 +368,6 @@ public class StatusBar extends SystemUI implements DemoMode, protected NotificationShadeWindowController mNotificationShadeWindowController; protected StatusBarWindowController mStatusBarWindowController; private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; - private final LockscreenLockIconController mLockscreenLockIconController; @VisibleForTesting DozeServiceHost mDozeServiceHost; private boolean mWakeUpComingFromTouch; @@ -414,6 +414,7 @@ public class StatusBar extends SystemUI implements DemoMode, // expanded notifications // the sliding/resizing panel within the notification window protected NotificationPanelViewController mNotificationPanelViewController; + protected LockscreenLockIconController mLockscreenLockIconController; // settings private QSPanelController mQSPanelController; @@ -724,7 +725,6 @@ public class StatusBar extends SystemUI implements DemoMode, Lazy<AssistManager> assistManagerLazy, ConfigurationController configurationController, NotificationShadeWindowController notificationShadeWindowController, - LockscreenLockIconController lockscreenLockIconController, DozeParameters dozeParameters, ScrimController scrimController, @Nullable KeyguardLiftController keyguardLiftController, @@ -806,7 +806,6 @@ public class StatusBar extends SystemUI implements DemoMode, mAssistManagerLazy = assistManagerLazy; mConfigurationController = configurationController; mNotificationShadeWindowController = notificationShadeWindowController; - mLockscreenLockIconController = lockscreenLockIconController; mDozeServiceHost = dozeServiceHost; mPowerManager = powerManager; mDozeParameters = dozeParameters; @@ -841,8 +840,10 @@ public class StatusBar extends SystemUI implements DemoMode, mBubbleExpandListener = (isExpanding, key) -> { - mNotificationsController.requestNotificationUpdate("onBubbleExpandChanged"); - updateScrimController(); + mContext.getMainExecutor().execute(() -> { + mNotificationsController.requestNotificationUpdate("onBubbleExpandChanged"); + updateScrimController(); + }); }; mActivityIntentHelper = new ActivityIntentHelper(mContext); @@ -1170,9 +1171,7 @@ public class StatusBar extends SystemUI implements DemoMode, mScrimController.setScrimVisibleListener(scrimsVisible -> { mNotificationShadeWindowController.setScrimsVisibility(scrimsVisible); - if (mNotificationShadeWindowView != null) { - mLockscreenLockIconController.onScrimVisibilityChanged(scrimsVisible); - } + mLockscreenLockIconController.onScrimVisibilityChanged(scrimsVisible); }); mScrimController.attachViews(scrimBehind, scrimInFront, scrimForBubble); @@ -1205,9 +1204,6 @@ public class StatusBar extends SystemUI implements DemoMode, createUserSwitcher(); } - mNotificationPanelViewController.setLaunchAffordanceListener( - mLockscreenLockIconController::onShowingLaunchAffordanceChanged); - // Set up the quick settings tile panel final View container = mNotificationShadeWindowView.findViewById(R.id.qs_frame); if (container != null) { @@ -1487,6 +1483,11 @@ public class StatusBar extends SystemUI implements DemoMode, mStatusBarWindowController = statusBarComponent.getStatusBarWindowController(); mPhoneStatusBarWindow = mSuperStatusBarViewFactory.getStatusBarWindowView(); mNotificationPanelViewController = statusBarComponent.getNotificationPanelViewController(); + mLockscreenLockIconController = statusBarComponent.getLockscreenLockIconController(); + mLockscreenLockIconController.init(); + + mNotificationPanelViewController.setLaunchAffordanceListener( + mLockscreenLockIconController::onShowingLaunchAffordanceChanged); } protected void startKeyguard() { @@ -2428,6 +2429,8 @@ public class StatusBar extends SystemUI implements DemoMode, return MODE_LIGHTS_OUT_TRANSPARENT; } else if ((appearance & APPEARANCE_OPAQUE_STATUS_BARS) != 0) { return MODE_OPAQUE; + } else if ((appearance & APPEARANCE_SEMI_TRANSPARENT_STATUS_BARS) != 0) { + return MODE_SEMI_TRANSPARENT; } else { return MODE_TRANSPARENT; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java index 5f90077640ec..f6165f666c89 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java @@ -316,11 +316,23 @@ public class StatusBarSignalPolicy implements NetworkControllerImpl.SignalCallba mIconController.removeAllIconsForSlot(mSlotMobile); mMobileStates.clear(); + List<NoCallingIconState> noCallingStates = new ArrayList<NoCallingIconState>(); + noCallingStates.addAll(mNoCallingStates); mNoCallingStates.clear(); final int n = subs.size(); for (int i = 0; i < n; i++) { mMobileStates.add(new MobileIconState(subs.get(i).getSubscriptionId())); - mNoCallingStates.add(new NoCallingIconState(subs.get(i).getSubscriptionId())); + boolean isNewSub = true; + for (NoCallingIconState state : noCallingStates) { + if (state.subId == subs.get(i).getSubscriptionId()) { + mNoCallingStates.add(state); + isNewSub = false; + break; + } + } + if (isNewSub) { + mNoCallingStates.add(new NoCallingIconState(subs.get(i).getSubscriptionId())); + } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarComponent.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarComponent.java index 802da3e8c21c..ecd9613f84b2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarComponent.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarComponent.java @@ -18,6 +18,7 @@ package com.android.systemui.statusbar.phone.dagger; import static java.lang.annotation.RetentionPolicy.RUNTIME; +import com.android.systemui.statusbar.phone.LockscreenLockIconController; import com.android.systemui.statusbar.phone.NotificationPanelViewController; import com.android.systemui.statusbar.phone.NotificationShadeWindowView; import com.android.systemui.statusbar.phone.NotificationShadeWindowViewController; @@ -73,4 +74,9 @@ public interface StatusBarComponent { @StatusBarScope NotificationPanelViewController getNotificationPanelViewController(); + /** + * Creates a LockscreenLockIconController. + */ + @StatusBarScope + LockscreenLockIconController getLockscreenLockIconController(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java index 26e19596b577..9e9533d0e199 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java @@ -77,7 +77,6 @@ import com.android.systemui.statusbar.phone.KeyguardDismissUtil; import com.android.systemui.statusbar.phone.KeyguardLiftController; import com.android.systemui.statusbar.phone.LightBarController; import com.android.systemui.statusbar.phone.LightsOutNotifController; -import com.android.systemui.statusbar.phone.LockscreenLockIconController; import com.android.systemui.statusbar.phone.LockscreenWallpaper; import com.android.systemui.statusbar.phone.NotificationIconAreaController; import com.android.systemui.statusbar.phone.PhoneStatusBarPolicy; @@ -167,7 +166,6 @@ public interface StatusBarPhoneModule { Lazy<AssistManager> assistManagerLazy, ConfigurationController configurationController, NotificationShadeWindowController notificationShadeWindowController, - LockscreenLockIconController lockscreenLockIconController, DozeParameters dozeParameters, ScrimController scrimController, @Nullable KeyguardLiftController keyguardLiftController, @@ -248,7 +246,6 @@ public interface StatusBarPhoneModule { assistManagerLazy, configurationController, notificationShadeWindowController, - lockscreenLockIconController, dozeParameters, scrimController, keyguardLiftController, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java index 37d8c9ae2958..781abe6cef3e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java @@ -16,6 +16,10 @@ package com.android.systemui.statusbar.phone.dagger; +import android.annotation.Nullable; + +import com.android.systemui.R; +import com.android.systemui.statusbar.phone.LockIcon; import com.android.systemui.statusbar.phone.NotificationPanelView; import com.android.systemui.statusbar.phone.NotificationShadeWindowView; @@ -32,4 +36,12 @@ public abstract class StatusBarViewModule { return notificationShadeWindowView.getNotificationPanelView(); } + /** */ + @Provides + @StatusBarComponent.StatusBarScope + @Nullable + public static LockIcon getLockIcon( + NotificationShadeWindowView notificationShadeWindowView) { + return notificationShadeWindowView.findViewById(R.id.lock_icon); + } } diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java b/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java index bf823b4b22b8..6e7aed064159 100644 --- a/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java +++ b/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java @@ -38,6 +38,7 @@ import android.app.NotificationChannel; import android.app.NotificationManager; import android.content.Context; import android.content.res.Configuration; +import android.os.Looper; import android.os.RemoteException; import android.os.ServiceManager; import android.service.notification.NotificationListenerService.RankingMap; @@ -83,10 +84,14 @@ import com.android.wm.shell.bubbles.Bubbles; import java.io.FileDescriptor; import java.io.PrintWriter; +import java.lang.reflect.Array; import java.util.ArrayList; import java.util.List; import java.util.Optional; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Executor; import java.util.function.IntConsumer; +import java.util.function.Supplier; /** * The SysUi side bubbles manager which communicate with other SysUi components. @@ -106,8 +111,9 @@ public class BubblesManager implements Dumpable { private final NotificationGroupManagerLegacy mNotificationGroupManager; private final NotificationEntryManager mNotificationEntryManager; private final NotifPipeline mNotifPipeline; + private final Executor mSysuiMainExecutor; - private final ScrimView mBubbleScrim; + private ScrimView mBubbleScrim; private final Bubbles.SysuiProxy mSysuiProxy; // TODO (b/145659174): allow for multiple callbacks to support the "shadow" new notif pipeline private final List<NotifCallback> mCallbacks = new ArrayList<>(); @@ -133,14 +139,15 @@ public class BubblesManager implements Dumpable { NotifPipeline notifPipeline, SysUiState sysUiState, FeatureFlags featureFlags, - DumpManager dumpManager) { + DumpManager dumpManager, + Executor sysuiMainExecutor) { if (bubblesOptional.isPresent()) { return new BubblesManager(context, bubblesOptional.get(), notificationShadeWindowController, statusBarStateController, shadeController, configurationController, statusBarService, notificationManager, interruptionStateProvider, zenModeController, notifUserManager, groupManager, entryManager, notifPipeline, sysUiState, featureFlags, - dumpManager); + dumpManager, sysuiMainExecutor); } else { return null; } @@ -163,7 +170,8 @@ public class BubblesManager implements Dumpable { NotifPipeline notifPipeline, SysUiState sysUiState, FeatureFlags featureFlags, - DumpManager dumpManager) { + DumpManager dumpManager, + Executor sysuiMainExecutor) { mContext = context; mBubbles = bubbles; mNotificationShadeWindowController = notificationShadeWindowController; @@ -173,6 +181,7 @@ public class BubblesManager implements Dumpable { mNotificationGroupManager = groupManager; mNotificationEntryManager = entryManager; mNotifPipeline = notifPipeline; + mSysuiMainExecutor = sysuiMainExecutor; mBarService = statusBarService == null ? IStatusBarService.Stub.asInterface( @@ -181,7 +190,9 @@ public class BubblesManager implements Dumpable { mBubbleScrim = new ScrimView(mContext); mBubbleScrim.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO); - mBubbles.setBubbleScrim(mBubbleScrim); + mBubbles.setBubbleScrim(mBubbleScrim, (executor, looper) -> { + mBubbleScrim.setExecutor(executor, looper); + }); if (featureFlags.isNewNotifPipelineRenderingEnabled()) { setupNotifPipeline(); @@ -237,128 +248,177 @@ public class BubblesManager implements Dumpable { }); mSysuiProxy = new Bubbles.SysuiProxy() { + private <T> T executeBlockingForResult(Supplier<T> runnable, Executor executor, + Class clazz) { + if (Looper.myLooper() == Looper.getMainLooper()) { + return runnable.get(); + } + final T[] result = (T[]) Array.newInstance(clazz, 1); + final CountDownLatch latch = new CountDownLatch(1); + executor.execute(() -> { + result[0] = runnable.get(); + latch.countDown(); + }); + try { + latch.await(); + return result[0]; + } catch (InterruptedException e) { + return null; + } + } + @Override @Nullable public BubbleEntry getPendingOrActiveEntry(String key) { - NotificationEntry entry = mNotificationEntryManager.getPendingOrActiveNotif(key); - return entry == null ? null : notifToBubbleEntry(entry); + return executeBlockingForResult(() -> { + NotificationEntry entry = + mNotificationEntryManager.getPendingOrActiveNotif(key); + return entry == null ? null : notifToBubbleEntry(entry); + }, sysuiMainExecutor, BubbleEntry.class); } @Override public List<BubbleEntry> getShouldRestoredEntries(ArraySet<String> savedBubbleKeys) { - List<BubbleEntry> result = new ArrayList<>(); - List<NotificationEntry> activeEntries = - mNotificationEntryManager.getActiveNotificationsForCurrentUser(); - for (int i = 0; i < activeEntries.size(); i++) { - NotificationEntry entry = activeEntries.get(i); - if (savedBubbleKeys.contains(entry.getKey()) - && mNotificationInterruptStateProvider.shouldBubbleUp(entry) - && entry.isBubble()) { - result.add(notifToBubbleEntry(entry)); + return executeBlockingForResult(() -> { + List<BubbleEntry> result = new ArrayList<>(); + List<NotificationEntry> activeEntries = + mNotificationEntryManager.getActiveNotificationsForCurrentUser(); + for (int i = 0; i < activeEntries.size(); i++) { + NotificationEntry entry = activeEntries.get(i); + if (savedBubbleKeys.contains(entry.getKey()) + && mNotificationInterruptStateProvider.shouldBubbleUp(entry) + && entry.isBubble()) { + result.add(notifToBubbleEntry(entry)); + } } - } - return result; + return result; + }, sysuiMainExecutor, List.class); } @Override public boolean isNotificationShadeExpand() { - return mNotificationShadeWindowController.getPanelExpanded(); + return executeBlockingForResult(() -> { + return mNotificationShadeWindowController.getPanelExpanded(); + }, sysuiMainExecutor, Boolean.class); } @Override public boolean shouldBubbleUp(String key) { - final NotificationEntry entry = mNotificationEntryManager.getPendingOrActiveNotif( - key); - if (entry != null) { - return mNotificationInterruptStateProvider.shouldBubbleUp(entry); - } - return false; + return executeBlockingForResult(() -> { + final NotificationEntry entry = + mNotificationEntryManager.getPendingOrActiveNotif(key); + if (entry != null) { + return mNotificationInterruptStateProvider.shouldBubbleUp(entry); + } + return false; + }, sysuiMainExecutor, Boolean.class); } @Override public void setNotificationInterruption(String key) { - final NotificationEntry entry = mNotificationEntryManager.getPendingOrActiveNotif( - key); - if (entry != null && entry.getImportance() >= NotificationManager.IMPORTANCE_HIGH) { - entry.setInterruption(); - } + sysuiMainExecutor.execute(() -> { + final NotificationEntry entry = + mNotificationEntryManager.getPendingOrActiveNotif(key); + if (entry != null + && entry.getImportance() >= NotificationManager.IMPORTANCE_HIGH) { + entry.setInterruption(); + } + }); } @Override public void requestNotificationShadeTopUi(boolean requestTopUi, String componentTag) { - mNotificationShadeWindowController.setRequestTopUi(requestTopUi, componentTag); + sysuiMainExecutor.execute(() -> { + mNotificationShadeWindowController.setRequestTopUi(requestTopUi, componentTag); + }); } @Override public void notifyRemoveNotification(String key, int reason) { - final NotificationEntry entry = mNotificationEntryManager.getPendingOrActiveNotif( - key); - if (entry != null) { - for (NotifCallback cb : mCallbacks) { - cb.removeNotification(entry, getDismissedByUserStats(entry, true), reason); + sysuiMainExecutor.execute(() -> { + final NotificationEntry entry = + mNotificationEntryManager.getPendingOrActiveNotif(key); + if (entry != null) { + for (NotifCallback cb : mCallbacks) { + cb.removeNotification(entry, getDismissedByUserStats(entry, true), + reason); + } } - } + }); } @Override public void notifyInvalidateNotifications(String reason) { - for (NotifCallback cb : mCallbacks) { - cb.invalidateNotifications(reason); - } + sysuiMainExecutor.execute(() -> { + for (NotifCallback cb : mCallbacks) { + cb.invalidateNotifications(reason); + } + }); } @Override public void notifyMaybeCancelSummary(String key) { - final NotificationEntry entry = mNotificationEntryManager.getPendingOrActiveNotif( - key); - if (entry != null) { - for (NotifCallback cb : mCallbacks) { - cb.maybeCancelSummary(entry); + sysuiMainExecutor.execute(() -> { + final NotificationEntry entry = + mNotificationEntryManager.getPendingOrActiveNotif(key); + if (entry != null) { + for (NotifCallback cb : mCallbacks) { + cb.maybeCancelSummary(entry); + } } - } + }); } @Override public void removeNotificationEntry(String key) { - final NotificationEntry entry = mNotificationEntryManager.getPendingOrActiveNotif( - key); - if (entry != null) { - mNotificationGroupManager.onEntryRemoved(entry); - } + sysuiMainExecutor.execute(() -> { + final NotificationEntry entry = + mNotificationEntryManager.getPendingOrActiveNotif(key); + if (entry != null) { + mNotificationGroupManager.onEntryRemoved(entry); + } + }); } @Override public void updateNotificationBubbleButton(String key) { - final NotificationEntry entry = mNotificationEntryManager.getPendingOrActiveNotif( - key); - if (entry != null && entry.getRow() != null) { - entry.getRow().updateBubbleButton(); - } + sysuiMainExecutor.execute(() -> { + final NotificationEntry entry = + mNotificationEntryManager.getPendingOrActiveNotif(key); + if (entry != null && entry.getRow() != null) { + entry.getRow().updateBubbleButton(); + } + }); } @Override public void updateNotificationSuppression(String key) { - final NotificationEntry entry = mNotificationEntryManager.getPendingOrActiveNotif( - key); - if (entry != null) { - mNotificationGroupManager.updateSuppression(entry); - } + sysuiMainExecutor.execute(() -> { + final NotificationEntry entry = + mNotificationEntryManager.getPendingOrActiveNotif(key); + if (entry != null) { + mNotificationGroupManager.updateSuppression(entry); + } + }); } @Override public void onStackExpandChanged(boolean shouldExpand) { - sysUiState - .setFlag(QuickStepContract.SYSUI_STATE_BUBBLES_EXPANDED, shouldExpand) - .commitUpdate(mContext.getDisplayId()); + sysuiMainExecutor.execute(() -> { + sysUiState.setFlag(QuickStepContract.SYSUI_STATE_BUBBLES_EXPANDED, shouldExpand) + .commitUpdate(mContext.getDisplayId()); + }); } @Override public void onUnbubbleConversation(String key) { - final NotificationEntry entry = - mNotificationEntryManager.getPendingOrActiveNotif(key); - if (entry != null) { - onUserChangedBubble(entry, false /* shouldBubble */); - } + sysuiMainExecutor.execute(() -> { + final NotificationEntry entry = + mNotificationEntryManager.getPendingOrActiveNotif(key); + if (entry != null) { + onUserChangedBubble(entry, false /* shouldBubble */); + } + }); } }; mBubbles.setSysuiProxy(mSysuiProxy); @@ -424,9 +484,8 @@ public class BubblesManager implements Dumpable { final String groupKey = group.summary != null ? group.summary.getSbn().getGroupKey() : null; - if (!suppressed && groupKey != null - && mBubbles.isSummarySuppressed(groupKey)) { - mBubbles.removeSuppressedSummary(groupKey); + if (!suppressed && groupKey != null) { + mBubbles.removeSuppressedSummaryIfNecessary(groupKey, null, null); } } }); @@ -449,19 +508,16 @@ public class BubblesManager implements Dumpable { // Check if removed bubble has an associated suppressed group summary that needs // to be removed now. final String groupKey = entry.getSbn().getGroupKey(); - if (mBubbles.isSummarySuppressed(groupKey)) { - mBubbles.removeSuppressedSummary(groupKey); - + mBubbles.removeSuppressedSummaryIfNecessary(groupKey, (summaryKey) -> { final NotificationEntry summary = - mNotificationEntryManager.getActiveNotificationUnfiltered( - mBubbles.getSummaryKey(groupKey)); + mNotificationEntryManager.getActiveNotificationUnfiltered(summaryKey); if (summary != null) { mNotificationEntryManager.performRemoveNotification( summary.getSbn(), getDismissedByUserStats(summary, false), UNDEFINED_DISMISS_REASON); } - } + }, mSysuiMainExecutor); // Check if we still need to remove the summary from NoManGroup because the summary // may not be in the mBubbleData.mSuppressedGroupKeys list and removed above. diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java index 103e6bb08ed4..c2e4e149f8e0 100644 --- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java +++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java @@ -331,6 +331,7 @@ public abstract class WMShellBaseModule { @BindsOptionalOf abstract AppPairs optionalAppPairs(); + // Note: Handler needed for LauncherApps.register @WMSingleton @Provides static Optional<Bubbles> provideBubbles(Context context, @@ -341,11 +342,12 @@ public abstract class WMShellBaseModule { LauncherApps launcherApps, UiEventLogger uiEventLogger, ShellTaskOrganizer organizer, - @ShellMainThread ShellExecutor mainExecutor) { + @ShellMainThread ShellExecutor mainExecutor, + @ShellMainThread Handler mainHandler) { return Optional.of(BubbleController.create(context, null /* synchronizer */, floatingContentCoordinator, statusBarService, windowManager, windowManagerShellWrapper, launcherApps, uiEventLogger, organizer, - mainExecutor)); + mainExecutor, mainHandler)); } // Needs the shell main handler for ContentObserver callbacks diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java index dd145e419321..72dd4421e9ca 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java @@ -27,7 +27,6 @@ import static org.mockito.Mockito.when; import android.content.res.Resources; import android.content.res.TypedArray; import android.hardware.biometrics.SensorProperties; -import android.hardware.display.DisplayManager; import android.hardware.fingerprint.FingerprintManager; import android.hardware.fingerprint.FingerprintSensorProperties; import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; @@ -47,7 +46,6 @@ import com.android.systemui.SysuiTestCase; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.phone.ScrimController; import com.android.systemui.util.concurrency.FakeExecutor; -import com.android.systemui.util.settings.FakeSettings; import com.android.systemui.util.time.FakeSystemClock; import org.junit.Before; @@ -86,15 +84,12 @@ public class UdfpsControllerTest extends SysuiTestCase { @Mock private FingerprintManager mFingerprintManager; @Mock - private DisplayManager mDisplayManager; - @Mock private WindowManager mWindowManager; @Mock private StatusBarStateController mStatusBarStateController; @Mock private ScrimController mScrimController; - private FakeSettings mSystemSettings; private FakeExecutor mFgExecutor; // Stuff for configuring mocks @@ -109,7 +104,7 @@ public class UdfpsControllerTest extends SysuiTestCase { @Captor private ArgumentCaptor<IUdfpsOverlayController> mOverlayCaptor; private IUdfpsOverlayController mOverlayController; @Captor private ArgumentCaptor<UdfpsView.OnTouchListener> mTouchListenerCaptor; - @Captor private ArgumentCaptor<Runnable> mRunAfterShowingScrimAndDotCaptor; + @Captor private ArgumentCaptor<Runnable> mOnIlluminatedRunnableCaptor; @Before public void setUp() { @@ -122,16 +117,13 @@ public class UdfpsControllerTest extends SysuiTestCase { FingerprintSensorProperties.TYPE_UDFPS_OPTICAL, true /* resetLockoutRequiresHardwareAuthToken */)); when(mFingerprintManager.getSensorPropertiesInternal()).thenReturn(props); - mSystemSettings = new FakeSettings(); mFgExecutor = new FakeExecutor(new FakeSystemClock()); mUdfpsController = new UdfpsController( mContext, mResources, mLayoutInflater, mFingerprintManager, - mDisplayManager, mWindowManager, - mSystemSettings, mStatusBarStateController, mFgExecutor, mScrimController); @@ -183,7 +175,7 @@ public class UdfpsControllerTest extends SysuiTestCase { @Test public void fingerDown() throws RemoteException { // Configure UdfpsView to accept the ACTION_DOWN event - when(mUdfpsView.isShowScrimAndDot()).thenReturn(false); + when(mUdfpsView.isIlluminationRequested()).thenReturn(false); when(mUdfpsView.isValidTouch(anyFloat(), anyFloat(), anyFloat())).thenReturn(true); // GIVEN that the overlay is showing @@ -195,12 +187,11 @@ public class UdfpsControllerTest extends SysuiTestCase { MotionEvent event = MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0, 0, 0); mTouchListenerCaptor.getValue().onTouch(mUdfpsView, event); event.recycle(); - // THEN the scrim and dot is shown - verify(mUdfpsView).showScrimAndDot(); - // AND a runnable that passes the event to FingerprintManager is set on the view - verify(mUdfpsView).setRunAfterShowingScrimAndDot( - mRunAfterShowingScrimAndDotCaptor.capture()); - mRunAfterShowingScrimAndDotCaptor.getValue().run(); + // THEN illumination begins + verify(mUdfpsView).startIllumination(); + // AND onIlluminatedRunnable that notifies FingerprintManager is set + verify(mUdfpsView).setOnIlluminatedRunnable(mOnIlluminatedRunnableCaptor.capture()); + mOnIlluminatedRunnableCaptor.getValue().run(); verify(mFingerprintManager).onPointerDown(eq(mUdfpsController.mSensorProps.sensorId), eq(0), eq(0), eq(0f), eq(0f)); } @@ -213,12 +204,11 @@ public class UdfpsControllerTest extends SysuiTestCase { mFgExecutor.runAllReady(); // WHEN fingerprint is requested because of AOD interrupt mUdfpsController.onAodInterrupt(0, 0, 2f, 3f); - // THEN the scrim and dot is shown - verify(mUdfpsView).showScrimAndDot(); - // AND a runnable that passes the event to FingerprintManager is set on the view - verify(mUdfpsView).setRunAfterShowingScrimAndDot( - mRunAfterShowingScrimAndDotCaptor.capture()); - mRunAfterShowingScrimAndDotCaptor.getValue().run(); + // THEN illumination begins + verify(mUdfpsView).startIllumination(); + // AND onIlluminatedRunnable that notifies FingerprintManager is set + verify(mUdfpsView).setOnIlluminatedRunnable(mOnIlluminatedRunnableCaptor.capture()); + mOnIlluminatedRunnableCaptor.getValue().run(); verify(mFingerprintManager).onPointerDown(eq(mUdfpsController.mSensorProps.sensorId), eq(0), eq(0), eq(3f) /* minor */, eq(2f) /* major */); } @@ -232,8 +222,8 @@ public class UdfpsControllerTest extends SysuiTestCase { mUdfpsController.onAodInterrupt(0, 0, 0f, 0f); // WHEN it is cancelled mUdfpsController.onCancelAodInterrupt(); - // THEN the scrim and dot is hidden - verify(mUdfpsView).hideScrimAndDot(); + // THEN the illumination is hidden + verify(mUdfpsView).stopIllumination(); } @Test @@ -246,8 +236,8 @@ public class UdfpsControllerTest extends SysuiTestCase { // WHEN it times out mFgExecutor.advanceClockToNext(); mFgExecutor.runAllReady(); - // THEN the scrim and dot is hidden - verify(mUdfpsView).hideScrimAndDot(); + // THEN the illumination is hidden + verify(mUdfpsView).stopIllumination(); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogTest.kt b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogTest.kt index 9762ffffb02e..eb5dd4e6fef6 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogTest.kt @@ -72,7 +72,7 @@ class PrivacyDialogTest : SysuiTestCase() { ) dialog = PrivacyDialog(context, list, starter) dialog.show() - dialog.requireViewById<View>(R.id.link).callOnClick() + dialog.requireViewById<View>(R.id.privacy_item).callOnClick() verify(starter).invoke(PrivacyType.TYPE_MICROPHONE.permGroupName) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java index 23c093033ae0..bdde82289e86 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java @@ -88,7 +88,6 @@ public class DozeServiceHostTest extends SysuiTestCase { @Mock private NotificationPanelViewController mNotificationPanel; @Mock private View mAmbientIndicationContainer; @Mock private BiometricUnlockController mBiometricUnlockController; - @Mock private LockscreenLockIconController mLockscreenLockIconController; @Mock private AuthController mAuthController; @Before @@ -100,7 +99,7 @@ public class DozeServiceHostTest extends SysuiTestCase { mKeyguardViewMediator, () -> mAssistManager, mDozeScrimController, mKeyguardUpdateMonitor, mPulseExpansionHandler, mNotificationShadeWindowController, mNotificationWakeUpCoordinator, - mLockscreenLockIconController, mAuthController, mNotificationIconAreaController); + mAuthController, mNotificationIconAreaController); mDozeServiceHost.initialize( mStatusBar, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LockscreenIconControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LockscreenIconControllerTest.java index 95a35050c09e..60af16acbb7e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LockscreenIconControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LockscreenIconControllerTest.java @@ -18,7 +18,6 @@ package com.android.systemui.statusbar.phone; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -30,12 +29,12 @@ import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import com.android.internal.widget.LockPatternUtils; -import com.android.keyguard.KeyguardSecurityModel; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.systemui.SysuiTestCase; import com.android.systemui.dock.DockManager; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.KeyguardIndicationController; +import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator; import com.android.systemui.statusbar.policy.AccessibilityController; import com.android.systemui.statusbar.policy.ConfigurationController; @@ -45,6 +44,7 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; +import org.mockito.Captor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; @@ -64,7 +64,7 @@ public class LockscreenIconControllerTest extends SysuiTestCase { @Mock private KeyguardIndicationController mKeyguardIndicationController; @Mock - private LockIcon mLockIcon; // TODO: make this not a mock once inject is removed. + private LockIcon mLockIcon; @Mock private StatusBarStateController mStatusBarStateController; @Mock @@ -81,34 +81,36 @@ public class LockscreenIconControllerTest extends SysuiTestCase { private Resources mResources; @Mock private HeadsUpManagerPhone mHeadsUpManagerPhone; - @Mock - private KeyguardSecurityModel mKeyguardSecurityModel; private LockscreenLockIconController mLockIconController; + + @Captor ArgumentCaptor<OnAttachStateChangeListener> mOnAttachStateChangeCaptor; + @Captor ArgumentCaptor<StatusBarStateController.StateListener> mStateListenerCaptor; + private OnAttachStateChangeListener mOnAttachStateChangeListener; + private StatusBarStateController.StateListener mStatusBarStateListener; @Before public void setUp() { MockitoAnnotations.initMocks(this); - when(mKeyguardUpdateMonitor.shouldShowLockIcon()).thenReturn(true); + when(mKeyguardUpdateMonitor.canShowLockIcon()).thenReturn(true); when(mLockIcon.getContext()).thenReturn(mContext); - mLockIconController = new LockscreenLockIconController( + mLockIconController = new LockscreenLockIconController(mLockIcon, mLockscreenGestureLogger, mKeyguardUpdateMonitor, mLockPatternUtils, mShadeController, mAccessibilityController, mKeyguardIndicationController, mStatusBarStateController, mConfigurationController, mNotificationWakeUpCoordinator, mKeyguardBypassController, mDockManager, mKeyguardStateController, mResources, - mHeadsUpManagerPhone, mKeyguardSecurityModel); + mHeadsUpManagerPhone); - ArgumentCaptor<OnAttachStateChangeListener> onAttachStateChangeListenerArgumentCaptor = - ArgumentCaptor.forClass(OnAttachStateChangeListener.class); + when(mLockIcon.isAttachedToWindow()).thenReturn(true); + mLockIconController.init(); - doNothing().when(mLockIcon) - .addOnAttachStateChangeListener( - onAttachStateChangeListenerArgumentCaptor.capture()); - mLockIconController.attach(mLockIcon); - - mOnAttachStateChangeListener = onAttachStateChangeListenerArgumentCaptor.getValue(); + verify(mLockIcon).addOnAttachStateChangeListener( + mOnAttachStateChangeCaptor.capture()); + mOnAttachStateChangeListener = mOnAttachStateChangeCaptor.getValue(); + verify(mStatusBarStateController).addCallback(mStateListenerCaptor.capture()); + mStatusBarStateListener = mStateListenerCaptor.getValue(); } @Test @@ -133,23 +135,17 @@ public class LockscreenIconControllerTest extends SysuiTestCase { @Test public void testVisibility_Dozing() { - ArgumentCaptor<StatusBarStateController.StateListener> sBStateListenerCaptor = - ArgumentCaptor.forClass(StatusBarStateController.StateListener.class); - - mOnAttachStateChangeListener.onViewAttachedToWindow(mLockIcon); - verify(mStatusBarStateController).addCallback(sBStateListenerCaptor.capture()); - when(mStatusBarStateController.isDozing()).thenReturn(true); - sBStateListenerCaptor.getValue().onDozingChanged(true); + mStatusBarStateListener.onDozingChanged(true); verify(mLockIcon).updateIconVisibility(false); } @Test public void testVisibility_doNotShowLockIcon() { - when(mKeyguardUpdateMonitor.shouldShowLockIcon()).thenReturn(false); + when(mKeyguardUpdateMonitor.canShowLockIcon()).thenReturn(false); + mStatusBarStateListener.onStateChanged(StatusBarState.KEYGUARD); - mOnAttachStateChangeListener.onViewAttachedToWindow(mLockIcon); verify(mLockIcon).setVisibility(View.GONE); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java index 3b2e0550b9e7..21368d6d5309 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java @@ -54,6 +54,8 @@ import com.android.systemui.statusbar.FeatureFlags; import com.android.systemui.statusbar.ScrimView; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.KeyguardStateController; +import com.android.systemui.util.concurrency.FakeExecutor; +import com.android.systemui.util.time.FakeSystemClock; import com.android.systemui.util.wakelock.DelayedWakeLock; import com.android.systemui.utils.os.FakeHandler; @@ -220,7 +222,8 @@ public class ScrimControllerTest extends SysuiTestCase { mScrimController = new ScrimController(mLightBarController, mDozeParamenters, mAlarmManager, mKeyguardStateController, mDelayedWakeLockBuilder, new FakeHandler(mLooper.getLooper()), mKeyguardUpdateMonitor, - mDockManager, mBlurUtils, mConfigurationController, mFeatureFlags); + mDockManager, mBlurUtils, mConfigurationController, mFeatureFlags, + new FakeExecutor(new FakeSystemClock())); mScrimController.setScrimVisibleListener(visible -> mScrimVisibility = visible); mScrimController.attachViews(mScrimBehind, mScrimInFront, mScrimForBubble); mScrimController.setAnimatorListener(mAnimatorListener); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java index 2c781bad10c2..cae488a561a2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java @@ -386,7 +386,6 @@ public class StatusBarTest extends SysuiTestCase { () -> mAssistManager, configurationController, mNotificationShadeWindowController, - mLockscreenLockIconController, mDozeParameters, mScrimController, mKeyguardLiftController, @@ -436,6 +435,7 @@ public class StatusBarTest extends SysuiTestCase { // initialized automatically. mStatusBar.mNotificationShadeWindowView = mNotificationShadeWindowView; mStatusBar.mNotificationPanelViewController = mNotificationPanelViewController; + mStatusBar.mLockscreenLockIconController = mLockscreenLockIconController; mStatusBar.mDozeScrimController = mDozeScrimController; mStatusBar.mPresenter = mNotificationPresenter; mStatusBar.mKeyguardIndicationController = mKeyguardIndicationController; diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java index da1f5d392872..f8b63835551f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java @@ -37,6 +37,7 @@ import static org.mockito.Mockito.when; import android.app.Instrumentation; import android.content.Intent; import android.net.ConnectivityManager; +import android.net.LinkProperties; import android.net.Network; import android.net.NetworkCapabilities; import android.net.NetworkRequest; @@ -343,6 +344,8 @@ public class NetworkControllerBaseTest extends SysuiTestCase { setConnectivityCommon(networkType, validated, isConnected); if (networkType == NetworkCapabilities.TRANSPORT_WIFI) { if (isConnected) { + mNetworkCallback.onAvailable(mock(Network.class), + new NetworkCapabilities(mNetCapabilities), new LinkProperties(), false); mNetworkCallback.onCapabilitiesChanged( mock(Network.class), new NetworkCapabilities(mNetCapabilities)); } else { @@ -357,6 +360,8 @@ public class NetworkControllerBaseTest extends SysuiTestCase { setConnectivityCommon(networkType, validated, isConnected); if (networkType == NetworkCapabilities.TRANSPORT_CELLULAR) { if (isConnected) { + mNetworkCallback.onAvailable(mock(Network.class), + new NetworkCapabilities(mNetCapabilities), new LinkProperties(), false); mNetworkCallback.onCapabilitiesChanged( mock(Network.class), new NetworkCapabilities(mNetCapabilities)); } else { diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java index ccc2eb328a04..76269dda8245 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java @@ -166,6 +166,7 @@ public class BubblesTest extends SysuiTestCase { private ArgumentCaptor<NotificationRemoveInterceptor> mRemoveInterceptorCaptor; private BubblesManager mBubblesManager; + // TODO(178618782): Move tests on the controller directly to the shell private TestableBubbleController mBubbleController; private NotificationShadeWindowControllerImpl mNotificationShadeWindowController; private NotificationEntryListener mEntryListener; @@ -221,6 +222,9 @@ public class BubblesTest extends SysuiTestCase { mTestableLooper = TestableLooper.get(this); + // For the purposes of this test, just run everything synchronously + ShellExecutor syncExecutor = new SyncExecutor(); + mContext.addMockSystemService(FaceManager.class, mFaceManager); when(mColorExtractor.getNeutralColors()).thenReturn(mGradientColors); @@ -257,8 +261,9 @@ public class BubblesTest extends SysuiTestCase { mSysUiStateBubblesExpanded = (sysUiFlags & QuickStepContract.SYSUI_STATE_BUBBLES_EXPANDED) != 0); + // TODO: Fix mPositioner = new TestableBubblePositioner(mContext, mWindowManager); - mBubbleData = new BubbleData(mContext, mBubbleLogger, mPositioner); + mBubbleData = new BubbleData(mContext, mBubbleLogger, mPositioner, syncExecutor); TestableNotificationInterruptStateProviderImpl interruptionStateProvider = new TestableNotificationInterruptStateProviderImpl(mContext.getContentResolver(), @@ -273,7 +278,7 @@ public class BubblesTest extends SysuiTestCase { ); when(mFeatureFlagsOldPipeline.isNewNotifPipelineRenderingEnabled()).thenReturn(false); - when(mShellTaskOrganizer.getExecutor()).thenReturn(new FakeExecutor(new FakeSystemClock())); + when(mShellTaskOrganizer.getExecutor()).thenReturn(syncExecutor); mBubbleController = new TestableBubbleController( mContext, mBubbleData, @@ -286,12 +291,13 @@ public class BubblesTest extends SysuiTestCase { mBubbleLogger, mShellTaskOrganizer, mPositioner, - mock(ShellExecutor.class)); + syncExecutor, + mock(Handler.class)); mBubbleController.setExpandListener(mBubbleExpandListener); mBubblesManager = new BubblesManager( mContext, - mBubbleController, + mBubbleController.getImpl(), mNotificationShadeWindowController, mStatusBarStateController, mShadeController, @@ -306,7 +312,8 @@ public class BubblesTest extends SysuiTestCase { mNotifPipeline, mSysUiState, mFeatureFlagsOldPipeline, - mDumpManager); + mDumpManager, + syncExecutor); // Get a reference to the BubbleController's entry listener verify(mNotificationEntryManager, atLeastOnce()) diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/NewNotifPipelineBubblesTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/NewNotifPipelineBubblesTest.java index 00f4e3a3f144..5340ff7e967c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/NewNotifPipelineBubblesTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/NewNotifPipelineBubblesTest.java @@ -83,8 +83,6 @@ import com.android.systemui.statusbar.policy.BatteryController; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.HeadsUpManager; import com.android.systemui.statusbar.policy.ZenModeController; -import com.android.systemui.util.concurrency.FakeExecutor; -import com.android.systemui.util.time.FakeSystemClock; import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.WindowManagerShellWrapper; import com.android.wm.shell.bubbles.BubbleData; @@ -203,6 +201,9 @@ public class NewNotifPipelineBubblesTest extends SysuiTestCase { mTestableLooper = TestableLooper.get(this); + // For the purposes of this test, just run everything synchronously + ShellExecutor syncExecutor = new SyncExecutor(); + when(mColorExtractor.getNeutralColors()).thenReturn(mGradientColors); mNotificationShadeWindowController = new NotificationShadeWindowControllerImpl(mContext, @@ -227,7 +228,7 @@ public class NewNotifPipelineBubblesTest extends SysuiTestCase { when(mZenModeController.getConfig()).thenReturn(mZenModeConfig); mPositioner = new TestableBubblePositioner(mContext, mWindowManager); - mBubbleData = new BubbleData(mContext, mBubbleLogger, mPositioner); + mBubbleData = new BubbleData(mContext, mBubbleLogger, mPositioner, syncExecutor); TestableNotificationInterruptStateProviderImpl interruptionStateProvider = new TestableNotificationInterruptStateProviderImpl(mContext.getContentResolver(), @@ -241,7 +242,7 @@ public class NewNotifPipelineBubblesTest extends SysuiTestCase { mock(Handler.class) ); when(mFeatureFlagsNewPipeline.isNewNotifPipelineRenderingEnabled()).thenReturn(true); - when(mShellTaskOrganizer.getExecutor()).thenReturn(new FakeExecutor(new FakeSystemClock())); + when(mShellTaskOrganizer.getExecutor()).thenReturn(syncExecutor); mBubbleController = new TestableBubbleController( mContext, mBubbleData, @@ -254,12 +255,13 @@ public class NewNotifPipelineBubblesTest extends SysuiTestCase { mBubbleLogger, mShellTaskOrganizer, mPositioner, - mock(ShellExecutor.class)); + syncExecutor, + mock(Handler.class)); mBubbleController.setExpandListener(mBubbleExpandListener); mBubblesManager = new BubblesManager( mContext, - mBubbleController, + mBubbleController.getImpl(), mNotificationShadeWindowController, mStatusBarStateController, mShadeController, @@ -274,7 +276,8 @@ public class NewNotifPipelineBubblesTest extends SysuiTestCase { mNotifPipeline, mSysUiState, mFeatureFlagsNewPipeline, - mDumpManager); + mDumpManager, + syncExecutor); mBubblesManager.addNotifCallback(mNotifCallback); // Get a reference to the BubbleController's entry listener diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/SyncExecutor.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/SyncExecutor.java new file mode 100644 index 000000000000..d40eecffb29e --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/SyncExecutor.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2021 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.wmshell; + +import com.android.wm.shell.common.ShellExecutor; + +/** + * And executor that just executes everything synchronously. To be removed once we move the + * tests of shell behavior over to the shell. + */ +public class SyncExecutor implements ShellExecutor { + @Override + public void execute(Runnable runnable) { + runnable.run(); + } + + @Override + public void executeDelayed(Runnable runnable, long delayMillis) { + runnable.run(); + } + + @Override + public void removeAllCallbacks() { + } + + @Override + public void removeCallbacks(Runnable runnable) { + } + + @Override + public boolean hasCallback(Runnable runnable) { + return false; + } +}
\ No newline at end of file diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/TestableBubbleController.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/TestableBubbleController.java index 3f918e8b8633..cdf47b82561e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/TestableBubbleController.java +++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/TestableBubbleController.java @@ -49,10 +49,11 @@ public class TestableBubbleController extends BubbleController { BubbleLogger bubbleLogger, ShellTaskOrganizer shellTaskOrganizer, BubblePositioner positioner, - ShellExecutor shellMainExecutor) { + ShellExecutor shellMainExecutor, + Handler shellMainHandler) { super(context, data, Runnable::run, floatingContentCoordinator, dataRepository, statusBarService, windowManager, windowManagerShellWrapper, launcherApps, - bubbleLogger, shellTaskOrganizer, positioner, shellMainExecutor); + bubbleLogger, shellTaskOrganizer, positioner, shellMainExecutor, shellMainHandler); setInflateSynchronously(true); } } diff --git a/proto/src/system_messages.proto b/proto/src/system_messages.proto index ae024ff6d043..5dd271c9dbb1 100644 --- a/proto/src/system_messages.proto +++ b/proto/src/system_messages.proto @@ -260,6 +260,10 @@ message SystemMessage { // Package: android NOTE_ADB_WIFI_ACTIVE = 62; + // Notify the user a carrier suggestion is available to get IMSI exemption. + // Package: android + NOTE_CARRIER_SUGGESTION_AVAILABLE = 63; + // ADD_NEW_IDS_ABOVE_THIS_LINE // Legacy IDs with arbitrary values appear below // Legacy IDs existed as stable non-conflicting constants prior to the O release diff --git a/services/Android.bp b/services/Android.bp index f6bb72a46b87..61591c2c29bd 100644 --- a/services/Android.bp +++ b/services/Android.bp @@ -28,6 +28,7 @@ filegroup { ":services.profcollect-sources", ":services.restrictions-sources", ":services.searchui-sources", + ":services.smartspace-sources", ":services.speech-sources", ":services.startop.iorap-sources", ":services.systemcaptions-sources", @@ -36,6 +37,7 @@ filegroup { ":services.usb-sources", ":services.voiceinteraction-sources", ":services.wifi-sources", + ":service-media-s-sources", // TODO (b/177640454) ":service-permission-sources", ":service-statsd-sources", ], @@ -76,6 +78,7 @@ java_library { "services.profcollect", "services.restrictions", "services.searchui", + "services.smartspace", "services.speech", "services.startop", "services.systemcaptions", diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 554edc6d74bd..c091dfa384ca 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -216,8 +216,6 @@ import com.android.server.net.LockdownVpnTracker; import com.android.server.net.NetworkPolicyManagerInternal; import com.android.server.utils.PriorityDump; -import com.google.android.collect.Lists; - import libcore.io.IoUtils; import java.io.FileDescriptor; @@ -1329,31 +1327,6 @@ public class ConnectivityService extends IConnectivityManager.Stub return mNextNetworkRequestId++; } - private NetworkState getFilteredNetworkState(int networkType, int uid) { - if (mLegacyTypeTracker.isTypeSupported(networkType)) { - final NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType); - final NetworkState state; - if (nai != null) { - state = nai.getNetworkState(); - state.networkInfo.setType(networkType); - } else { - final NetworkInfo info = new NetworkInfo(networkType, 0, - getNetworkTypeName(networkType), ""); - info.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, null, null); - info.setIsAvailable(true); - final NetworkCapabilities capabilities = new NetworkCapabilities(); - capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING, - !info.isRoaming()); - state = new NetworkState(info, new LinkProperties(), capabilities, - null, null, null); - } - filterNetworkStateForUid(state, uid, false); - return state; - } else { - return NetworkState.EMPTY; - } - } - @VisibleForTesting protected NetworkAgentInfo getNetworkAgentInfoForNetwork(Network network) { if (network == null) { @@ -1464,6 +1437,18 @@ public class ConnectivityService extends IConnectivityManager.Stub "%s %d(%d) on netId %d", action, nri.mUid, requestId, net.getNetId())); } + private void filterNetworkInfo(@NonNull NetworkInfo networkInfo, + @NonNull NetworkCapabilities nc, int uid, boolean ignoreBlocked) { + if (isNetworkWithCapabilitiesBlocked(nc, uid, ignoreBlocked)) { + networkInfo.setDetailedState(DetailedState.BLOCKED, null, null); + } + synchronized (mVpns) { + if (mLockdownTracker != null) { + mLockdownTracker.augmentNetworkInfo(networkInfo); + } + } + } + /** * Apply any relevant filters to {@link NetworkState} for the given UID. For * example, this may mark the network as {@link DetailedState#BLOCKED} based @@ -1471,16 +1456,7 @@ public class ConnectivityService extends IConnectivityManager.Stub */ private void filterNetworkStateForUid(NetworkState state, int uid, boolean ignoreBlocked) { if (state == null || state.networkInfo == null || state.linkProperties == null) return; - - if (isNetworkWithCapabilitiesBlocked(state.networkCapabilities, uid, - ignoreBlocked)) { - state.networkInfo.setDetailedState(DetailedState.BLOCKED, null, null); - } - synchronized (mVpns) { - if (mLockdownTracker != null) { - mLockdownTracker.augmentNetworkInfo(state.networkInfo); - } - } + filterNetworkInfo(state.networkInfo, state.networkCapabilities, uid, ignoreBlocked); } /** @@ -1545,6 +1521,27 @@ public class ConnectivityService extends IConnectivityManager.Stub return state.networkInfo; } + private NetworkInfo getFilteredNetworkInfo(int networkType, int uid) { + if (!mLegacyTypeTracker.isTypeSupported(networkType)) { + return null; + } + final NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType); + final NetworkInfo info; + final NetworkCapabilities nc; + if (nai != null) { + info = new NetworkInfo(nai.networkInfo); + info.setType(networkType); + nc = nai.networkCapabilities; + } else { + info = new NetworkInfo(networkType, 0, getNetworkTypeName(networkType), ""); + info.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, null, null); + info.setIsAvailable(true); + nc = new NetworkCapabilities(); + } + filterNetworkInfo(info, nc, uid, false); + return info; + } + @Override public NetworkInfo getNetworkInfo(int networkType) { enforceAccessPermission(); @@ -1559,8 +1556,7 @@ public class ConnectivityService extends IConnectivityManager.Stub return state.networkInfo; } } - final NetworkState state = getFilteredNetworkState(networkType, uid); - return state.networkInfo; + return getFilteredNetworkInfo(networkType, uid); } @Override @@ -1579,7 +1575,7 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public NetworkInfo[] getAllNetworkInfo() { enforceAccessPermission(); - final ArrayList<NetworkInfo> result = Lists.newArrayList(); + final ArrayList<NetworkInfo> result = new ArrayList<>(); for (int networkType = 0; networkType <= ConnectivityManager.MAX_NETWORK_TYPE; networkType++) { NetworkInfo info = getNetworkInfo(networkType); @@ -1593,10 +1589,16 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public Network getNetworkForType(int networkType) { enforceAccessPermission(); + if (!mLegacyTypeTracker.isTypeSupported(networkType)) { + return null; + } + final NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType); + if (nai == null) { + return null; + } final int uid = mDeps.getCallingUid(); - NetworkState state = getFilteredNetworkState(networkType, uid); - if (!isNetworkWithCapabilitiesBlocked(state.networkCapabilities, uid, false)) { - return state.network; + if (!isNetworkWithCapabilitiesBlocked(nai.networkCapabilities, uid, false)) { + return nai.network; } return null; } @@ -1847,7 +1849,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // This contains IMSI details, so make sure the caller is privileged. NetworkStack.checkNetworkStackPermission(mContext); - final ArrayList<NetworkState> result = Lists.newArrayList(); + final ArrayList<NetworkState> result = new ArrayList<>(); for (Network network : getAllNetworks()) { final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network); if (nai != null) { diff --git a/services/core/java/com/android/server/PackageWatchdog.java b/services/core/java/com/android/server/PackageWatchdog.java index 8b506bac4a85..41903fcd165f 100644 --- a/services/core/java/com/android/server/PackageWatchdog.java +++ b/services/core/java/com/android/server/PackageWatchdog.java @@ -372,10 +372,12 @@ public class PackageWatchdog { * even from a previous boot. */ public void unregisterHealthObserver(PackageHealthObserver observer) { - synchronized (mLock) { - mAllObservers.remove(observer.getName()); - } - syncState("unregistering observer: " + observer.getName()); + mLongTaskHandler.post(() -> { + synchronized (mLock) { + mAllObservers.remove(observer.getName()); + } + syncState("unregistering observer: " + observer.getName()); + }); } /** @@ -982,7 +984,11 @@ public class PackageWatchdog { if (!DeviceConfig.NAMESPACE_ROLLBACK.equals(properties.getNamespace())) { return; } - updateConfigs(); + try { + updateConfigs(); + } catch (Exception ignore) { + Slog.w(TAG, "Failed to reload device config changes"); + } }); } @@ -990,7 +996,8 @@ public class PackageWatchdog { * Health check is enabled or disabled after reading the flags * from DeviceConfig. */ - private void updateConfigs() { + @VisibleForTesting + void updateConfigs() { synchronized (mLock) { mTriggerFailureCount = DeviceConfig.getInt( DeviceConfig.NAMESPACE_ROLLBACK, diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java index 0412f08d3ae3..7d6515600c2a 100644 --- a/services/core/java/com/android/server/StorageManagerService.java +++ b/services/core/java/com/android/server/StorageManagerService.java @@ -48,6 +48,7 @@ import static org.xmlpull.v1.XmlPullParser.START_TAG; import android.Manifest; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.UserIdInt; import android.app.ActivityManager; import android.app.ActivityManagerInternal; import android.app.AppOpsManager; @@ -482,14 +483,21 @@ class StorageManagerService extends IStorageManager.Stub } } - private @Nullable VolumeInfo findStorageForUuid(String volumeUuid) { + private @Nullable VolumeInfo findStorageForUuidAsUser(String volumeUuid, + @UserIdInt int userId) { final StorageManager storage = mContext.getSystemService(StorageManager.class); if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, volumeUuid)) { - return storage.findVolumeById(VolumeInfo.ID_EMULATED_INTERNAL + ";" + 0); + return storage.findVolumeById(VolumeInfo.ID_EMULATED_INTERNAL + ";" + userId); } else if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, volumeUuid)) { return storage.getPrimaryPhysicalVolume(); } else { - return storage.findEmulatedForPrivate(storage.findVolumeByUuid(volumeUuid)); + VolumeInfo info = storage.findVolumeByUuid(volumeUuid); + if (info == null) { + Slog.w(TAG, "findStorageForUuidAsUser cannot find volumeUuid:" + volumeUuid); + return null; + } + String emulatedUuid = info.getId().replace("private", "emulated") + ";" + userId; + return storage.findVolumeById(emulatedUuid); } } @@ -2605,8 +2613,9 @@ class StorageManagerService extends IStorageManager.Stub return; } else { - from = findStorageForUuid(mPrimaryStorageUuid); - to = findStorageForUuid(volumeUuid); + int currentUserId = mCurrentUserId; + from = findStorageForUuidAsUser(mPrimaryStorageUuid, currentUserId); + to = findStorageForUuidAsUser(volumeUuid, currentUserId); if (from == null) { Slog.w(TAG, "Failing move due to missing from volume " + mPrimaryStorageUuid); diff --git a/services/core/java/com/android/server/TestNetworkService.java b/services/core/java/com/android/server/TestNetworkService.java index a08d066513c7..e96fd390f15a 100644 --- a/services/core/java/com/android/server/TestNetworkService.java +++ b/services/core/java/com/android/server/TestNetworkService.java @@ -32,6 +32,7 @@ import android.net.NetworkAgent; import android.net.NetworkAgentConfig; import android.net.NetworkCapabilities; import android.net.NetworkProvider; +import android.net.NetworkStack; import android.net.RouteInfo; import android.net.StringNetworkSpecifier; import android.net.TestNetworkInterface; @@ -48,6 +49,7 @@ import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; +import com.android.net.module.util.NetdUtils; import java.io.UncheckedIOException; import java.net.Inet4Address; @@ -317,10 +319,10 @@ class TestNetworkService extends ITestNetworkManager.Stub { } try { - // This requires NETWORK_STACK privileges. final long token = Binder.clearCallingIdentity(); try { - mNMS.setInterfaceUp(iface); + NetworkStack.checkNetworkStackPermission(mContext); + NetdUtils.setInterfaceUp(mNetd, iface); } finally { Binder.restoreCallingIdentity(token); } diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java index d63a6c3a0a6f..5b5043141315 100644 --- a/services/core/java/com/android/server/Watchdog.java +++ b/services/core/java/com/android/server/Watchdog.java @@ -111,7 +111,6 @@ public class Watchdog { }; public static final List<String> HAL_INTERFACES_OF_INTEREST = Arrays.asList( - "android.hardware.audio@2.0::IDevicesFactory", "android.hardware.audio@4.0::IDevicesFactory", "android.hardware.audio@5.0::IDevicesFactory", "android.hardware.audio@6.0::IDevicesFactory", diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index 02613cfe0771..6216fc00417a 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -2815,12 +2815,24 @@ public final class ActiveServices { r = smap.mServicesByIntent.get(filter); if (DEBUG_SERVICE && r != null) Slog.v(TAG_SERVICE, "Retrieved by intent: " + r); } - if (r != null && (r.serviceInfo.flags & ServiceInfo.FLAG_EXTERNAL_SERVICE) != 0 - && !callingPackage.equals(r.packageName)) { - // If an external service is running within its own package, other packages - // should not bind to that instance. - r = null; - if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Whoops, can't use existing external service"); + if (r != null) { + // Compared to resolveService below, the ServiceRecord here is retrieved from + // ServiceMap so the package visibility doesn't apply to it. We need to filter it. + if (mAm.getPackageManagerInternal().filterAppAccess(r.packageName, callingUid, + userId)) { + Slog.w(TAG_SERVICE, "Unable to start service " + service + " U=" + userId + + ": not found"); + return null; + } + if ((r.serviceInfo.flags & ServiceInfo.FLAG_EXTERNAL_SERVICE) != 0 + && !callingPackage.equals(r.packageName)) { + // If an external service is running within its own package, other packages + // should not bind to that instance. + r = null; + if (DEBUG_SERVICE) { + Slog.v(TAG_SERVICE, "Whoops, can't use existing external service"); + } + } } if (r == null) { try { @@ -4217,6 +4229,7 @@ public final class ActiveServices { Slog.w(TAG, "Forcing bringing down service: " + sr); sr.isolatedProc = null; mPendingServices.remove(i); + size = mPendingServices.size(); i--; needOomAdj = true; bringDownServiceLocked(sr, true); diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index f63b994307b0..c8f5f8e60187 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -236,6 +236,7 @@ import android.os.DropBoxManager; import android.os.FactoryTest; import android.os.FileUtils; import android.os.Handler; +import android.os.HandlerThread; import android.os.IBinder; import android.os.IDeviceIdentifiersPolicyService; import android.os.IPermissionController; @@ -316,6 +317,7 @@ import com.android.internal.os.IResultReceiver; import com.android.internal.os.ProcessCpuTracker; import com.android.internal.os.TransferPipe; import com.android.internal.os.Zygote; +import com.android.internal.policy.AttributeCache; import com.android.internal.protolog.common.ProtoLog; import com.android.internal.util.ArrayUtils; import com.android.internal.util.DumpUtils; @@ -326,7 +328,6 @@ import com.android.internal.util.Preconditions; import com.android.internal.util.function.HeptFunction; import com.android.internal.util.function.QuadFunction; import com.android.server.AlarmManagerInternal; -import com.android.server.AttributeCache; import com.android.server.DeviceIdleInternal; import com.android.server.DisplayThread; import com.android.server.IntentResolver; @@ -2098,11 +2099,19 @@ public class ActivityManagerService extends IActivityManager.Stub mEnableOffloadQueue = SystemProperties.getBoolean( "persist.device_config.activity_manager_native_boot.offload_queue_enabled", false); - mFgBroadcastQueue = new BroadcastQueue(this, mHandler, + // Decouple broadcast-related timing operations from other OS activity by + // using a dedicated thread. Sharing this thread between queues is safe + // because we know the nature of the activity on it and can't stall + // unexpectedly. + HandlerThread broadcastThread = new HandlerThread("broadcast"); + broadcastThread.start(); + Handler broadcastHandler = broadcastThread.getThreadHandler(); + + mFgBroadcastQueue = new BroadcastQueue(this, broadcastHandler, "foreground", foreConstants, false); - mBgBroadcastQueue = new BroadcastQueue(this, mHandler, + mBgBroadcastQueue = new BroadcastQueue(this, broadcastHandler, "background", backConstants, true); - mOffloadBroadcastQueue = new BroadcastQueue(this, mHandler, + mOffloadBroadcastQueue = new BroadcastQueue(this, broadcastHandler, "offload", offloadConstants, true); mBroadcastQueues[0] = mFgBroadcastQueue; mBroadcastQueues[1] = mBgBroadcastQueue; @@ -4500,7 +4509,6 @@ public class ActivityManagerService extends IActivityManager.Stub String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser) { synchronized (ActivityManagerService.this) { - mOomAdjuster.mCachedAppOptimizer.compactAllSystem(); mAppProfiler.requestPssAllProcsLocked( SystemClock.uptimeMillis(), true, false); } diff --git a/services/core/java/com/android/server/am/CachedAppOptimizer.java b/services/core/java/com/android/server/am/CachedAppOptimizer.java index 27a238dd33ea..c558b3d00400 100644 --- a/services/core/java/com/android/server/am/CachedAppOptimizer.java +++ b/services/core/java/com/android/server/am/CachedAppOptimizer.java @@ -741,10 +741,12 @@ public final class CachedAppOptimizer { // This will ensure app will be out of the freezer for at least FREEZE_TIMEOUT_MS void unfreezeTemporarily(ProcessRecord app) { - synchronized (mAm) { - if (app.frozen) { - unfreezeAppLocked(app); - freezeAppAsync(app); + if (mUseFreezer) { + synchronized (mAm) { + if (app.frozen) { + unfreezeAppLocked(app); + freezeAppAsync(app); + } } } } diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java index a768532a9260..bbf927b1ee2d 100644 --- a/services/core/java/com/android/server/am/ProcessList.java +++ b/services/core/java/com/android/server/am/ProcessList.java @@ -4447,7 +4447,7 @@ public final class ProcessList { } app.getPkgList().forEachPackage(packageName -> { - if (updateFrameworkRes && packagesToUpdate.contains(packageName)) { + if (updateFrameworkRes || packagesToUpdate.contains(packageName)) { try { final ApplicationInfo ai = AppGlobals.getPackageManager() .getApplicationInfo(packageName, STOCK_PM_FLAGS, app.userId); diff --git a/services/core/java/com/android/server/am/ProcessProfileRecord.java b/services/core/java/com/android/server/am/ProcessProfileRecord.java index cf309f4c8e3d..9fd2bd798c04 100644 --- a/services/core/java/com/android/server/am/ProcessProfileRecord.java +++ b/services/core/java/com/android/server/am/ProcessProfileRecord.java @@ -623,6 +623,8 @@ final class ProcessProfileRecord { DebugUtils.printSizeValue(pw, mLastCachedSwapPss * 1024); pw.print(" lastRss="); DebugUtils.printSizeValue(pw, mLastRss * 1024); + pw.println(); + pw.print(prefix); pw.print(" trimMemoryLevel="); pw.println(mTrimMemoryLevel); pw.println(); diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java index f7e87ef94939..a1adeaac52ca 100644 --- a/services/core/java/com/android/server/am/ProcessRecord.java +++ b/services/core/java/com/android/server/am/ProcessRecord.java @@ -643,7 +643,7 @@ class ProcessRecord implements WindowProcessListener { } public void makeActive(IApplicationThread _thread, ProcessStatsService tracker) { - mProfile.onProcessActive(thread, tracker); + mProfile.onProcessActive(_thread, tracker); thread = _thread; mWindowProcessController.setThread(thread); } diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java index b2824846008c..1a4f20c7101e 100644 --- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java +++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java @@ -57,6 +57,7 @@ import com.android.internal.util.WakeupMessage; import com.android.server.ConnectivityService; import java.io.PrintWriter; +import java.util.Arrays; import java.util.List; import java.util.NoSuchElementException; import java.util.Objects; @@ -1025,6 +1026,8 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> { + (networkAgentConfig.acceptUnvalidated ? " acceptUnvalidated" : "") + (networkAgentConfig.acceptPartialConnectivity ? " acceptPartialConnectivity" : "") + (clatd.isStarted() ? " clat{" + clatd + "} " : "") + + (declaredUnderlyingNetworks != null + ? " underlying{" + Arrays.toString(declaredUnderlyingNetworks) + "}" : "") + " lp{" + linkProperties + "}" + " nc{" + networkCapabilities + "}" + "}"; diff --git a/services/core/java/com/android/server/graphics/fonts/FontCrashDetector.java b/services/core/java/com/android/server/graphics/fonts/FontCrashDetector.java new file mode 100644 index 000000000000..b082b25aea02 --- /dev/null +++ b/services/core/java/com/android/server/graphics/fonts/FontCrashDetector.java @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.graphics.fonts; + +import android.annotation.NonNull; +import android.util.Slog; + +import java.io.File; +import java.io.IOException; + +/** + * A class to detect font-related native crash. + * + * <p>If a fs-verity protected file is accessed through mmap and corrupted file block is detected, + * SIGBUG signal is generated and the process will crash. To find corrupted files and remove them, + * we use a marker file to detect crash. + * <ol> + * <li>Create a marker file before reading fs-verity protected font files. + * <li>Delete the marker file after reading font files successfully. + * <li>If the marker file is found in the next process startup, it means that the process + * crashed before. We will delete font files to prevent crash loop. + * </ol> + * + * <p>Example usage: + * <pre> + * FontCrashDetector detector = new FontCrashDetector(new File("/path/to/marker_file")); + * if (detector.hasCrashed()) { + * // Do cleanup + * } + * try (FontCrashDetector.MonitoredBlock b = detector.start()) { + * // Read files + * } + * </pre> + * + * <p>This class DOES NOT detect Java exceptions. If a Java exception is thrown while monitoring + * crash, the marker file will be deleted. Creating and deleting marker files are not lightweight. + * Please use this class sparingly with caution. + */ +/* package */ final class FontCrashDetector { + + private static final String TAG = "FontCrashDetector"; + + @NonNull + private final File mMarkerFile; + + /* package */ FontCrashDetector(@NonNull File markerFile) { + mMarkerFile = markerFile; + } + + /* package */ boolean hasCrashed() { + return mMarkerFile.exists(); + } + + /* package */ void clear() { + if (!mMarkerFile.delete()) { + Slog.e(TAG, "Could not delete marker file: " + mMarkerFile); + } + } + + /** Starts crash monitoring. */ + /* package */ MonitoredBlock start() { + try { + mMarkerFile.createNewFile(); + } catch (IOException e) { + Slog.e(TAG, "Could not create marker file: " + mMarkerFile, e); + } + return new MonitoredBlock(); + } + + /** A helper class to monitor crash with try-with-resources syntax. */ + /* package */ class MonitoredBlock implements AutoCloseable { + /** Ends crash monitoring. */ + @Override + public void close() { + clear(); + } + } +} diff --git a/services/core/java/com/android/server/graphics/fonts/FontManagerService.java b/services/core/java/com/android/server/graphics/fonts/FontManagerService.java index 7461405c9a5f..8e5215b49f16 100644 --- a/services/core/java/com/android/server/graphics/fonts/FontManagerService.java +++ b/services/core/java/com/android/server/graphics/fonts/FontManagerService.java @@ -64,6 +64,7 @@ public final class FontManagerService extends IFontManager.Stub { private static final String TAG = "FontManagerService"; private static final String FONT_FILES_DIR = "/data/fonts/files"; + private static final String CRASH_MARKER_FILE = "/data/fonts/config/crash.txt"; @Override public FontConfig getFontConfig() throws RemoteException { @@ -179,6 +180,13 @@ public final class FontManagerService extends IFontManager.Stub { } } + @NonNull + private final Context mContext; + + @GuardedBy("FontManagerService.this") + @NonNull + private final FontCrashDetector mFontCrashDetector; + @Nullable private final UpdatableFontDir mUpdatableFontDir; @@ -188,7 +196,9 @@ public final class FontManagerService extends IFontManager.Stub { private FontManagerService(Context context) { mContext = context; + mFontCrashDetector = new FontCrashDetector(new File(CRASH_MARKER_FILE)); mUpdatableFontDir = createUpdatableFontDir(); + initialize(); } @Nullable @@ -201,20 +211,35 @@ public final class FontManagerService extends IFontManager.Stub { new OtfFontFileParser(), new FsverityUtilImpl()); } - - @NonNull - private final Context mContext; + private void initialize() { + synchronized (FontManagerService.this) { + if (mUpdatableFontDir == null) { + mSerializedFontMap = buildNewSerializedFontMap(); + return; + } + if (mFontCrashDetector.hasCrashed()) { + Slog.i(TAG, "Crash detected. Clearing font updates."); + try { + mUpdatableFontDir.clearUpdates(); + } catch (SystemFontException e) { + Slog.e(TAG, "Failed to clear updates.", e); + } + mFontCrashDetector.clear(); + } + try (FontCrashDetector.MonitoredBlock ignored = mFontCrashDetector.start()) { + mUpdatableFontDir.loadFontFileMap(); + mSerializedFontMap = buildNewSerializedFontMap(); + } + } + } @NonNull public Context getContext() { return mContext; } - @NonNull /* package */ SharedMemory getCurrentFontMap() { + @Nullable /* package */ SharedMemory getCurrentFontMap() { synchronized (FontManagerService.this) { - if (mSerializedFontMap == null) { - mSerializedFontMap = buildNewSerializedFontMap(); - } return mSerializedFontMap; } } @@ -234,9 +259,10 @@ public final class FontManagerService extends IFontManager.Stub { FontManager.RESULT_ERROR_VERSION_MISMATCH, "The base config version is older than current."); } - mUpdatableFontDir.installFontFile(fd, pkcs7Signature); - // Create updated font map in the next getSerializedSystemFontMap() call. - mSerializedFontMap = null; + try (FontCrashDetector.MonitoredBlock ignored = mFontCrashDetector.start()) { + mUpdatableFontDir.installFontFile(fd, pkcs7Signature); + mSerializedFontMap = buildNewSerializedFontMap(); + } } } @@ -246,7 +272,12 @@ public final class FontManagerService extends IFontManager.Stub { FontManager.RESULT_ERROR_FONT_UPDATER_DISABLED, "The font updater is disabled."); } - mUpdatableFontDir.clearUpdates(); + synchronized (FontManagerService.this) { + try (FontCrashDetector.MonitoredBlock ignored = mFontCrashDetector.start()) { + mUpdatableFontDir.clearUpdates(); + mSerializedFontMap = buildNewSerializedFontMap(); + } + } } /* package */ Map<String, File> getFontFileMap() { diff --git a/services/core/java/com/android/server/graphics/fonts/UpdatableFontDir.java b/services/core/java/com/android/server/graphics/fonts/UpdatableFontDir.java index b0bc65bc7787..0cb704507f7a 100644 --- a/services/core/java/com/android/server/graphics/fonts/UpdatableFontDir.java +++ b/services/core/java/com/android/server/graphics/fonts/UpdatableFontDir.java @@ -142,11 +142,9 @@ final class UpdatableFontDir { mFsverityUtil = fsverityUtil; mConfigFile = configFile; mTmpConfigFile = new File(configFile.getAbsoluteFile() + ".tmp"); - loadFontFileMap(); } - private void loadFontFileMap() { - // TODO: SIGBUS crash protection + /* package */ void loadFontFileMap() { synchronized (UpdatableFontDir.this) { boolean success = false; diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java index 23c70ee69514..2e4200c1f7d9 100644 --- a/services/core/java/com/android/server/input/InputManagerService.java +++ b/services/core/java/com/android/server/input/InputManagerService.java @@ -289,6 +289,8 @@ public class InputManagerService extends IInputManager.Stub private static native void nativeCancelVibrate(long ptr, int deviceId, int token); private static native boolean nativeIsVibrating(long ptr, int deviceId); private static native int[] nativeGetVibratorIds(long ptr, int deviceId); + private static native int nativeGetBatteryCapacity(long ptr, int deviceId); + private static native int nativeGetBatteryStatus(long ptr, int deviceId); private static native void nativeReloadKeyboardLayouts(long ptr); private static native void nativeReloadDeviceAliases(long ptr); private static native String nativeDump(long ptr); @@ -1818,8 +1820,7 @@ public class InputManagerService extends IInputManager.Stub } private void updateMaximumObscuringOpacityForTouchFromSettings() { - final float opacity = InputManager.getInstance().getMaximumObscuringOpacityForTouch( - mContext); + final float opacity = InputManager.getInstance().getMaximumObscuringOpacityForTouch(); if (opacity < 0 || opacity > 1) { Log.e(TAG, "Invalid maximum obscuring opacity " + opacity + ", it should be >= 0 and <= 1, rejecting update."); @@ -2009,6 +2010,18 @@ public class InputManagerService extends IInputManager.Stub // Binder call @Override + public int getBatteryStatus(int deviceId) { + return nativeGetBatteryStatus(mPtr, deviceId); + } + + // Binder call + @Override + public int getBatteryCapacity(int deviceId) { + return nativeGetBatteryCapacity(mPtr, deviceId); + } + + // Binder call + @Override public void setPointerIconType(int iconId) { nativeSetPointerIconType(mPtr, iconId); } diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java index 6308ace26011..e5b53501d6e3 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java @@ -4131,48 +4131,52 @@ public class InputMethodManagerService extends IInputMethodManager.Stub @BinderThread @Override @GuardedBy("mMethodMap") - public void startProtoDump(byte[] protoDump, int source, String where) { - if (protoDump == null && source != IME_TRACING_FROM_IMMS) { - // Dump not triggered from IMMS, but no proto information provided. - return; - } - ImeTracing tracingInstance = ImeTracing.getInstance(); - if (!tracingInstance.isAvailable() || !tracingInstance.isEnabled()) { - return; - } - - ProtoOutputStream proto = new ProtoOutputStream(); - switch (source) { - case ImeTracing.IME_TRACING_FROM_CLIENT: - final long client_token = proto.start(InputMethodClientsTraceFileProto.ENTRY); - proto.write(InputMethodClientsTraceProto.ELAPSED_REALTIME_NANOS, - SystemClock.elapsedRealtimeNanos()); - proto.write(InputMethodClientsTraceProto.WHERE, where); - proto.write(InputMethodClientsTraceProto.CLIENT, protoDump); - proto.end(client_token); - break; - case ImeTracing.IME_TRACING_FROM_IMS: - final long service_token = proto.start(InputMethodServiceTraceFileProto.ENTRY); - proto.write(InputMethodServiceTraceProto.ELAPSED_REALTIME_NANOS, - SystemClock.elapsedRealtimeNanos()); - proto.write(InputMethodServiceTraceProto.WHERE, where); - proto.write(InputMethodServiceTraceProto.INPUT_METHOD_SERVICE, protoDump); - proto.end(service_token); - break; - case IME_TRACING_FROM_IMMS: - final long managerservice_token = - proto.start(InputMethodManagerServiceTraceFileProto.ENTRY); - proto.write(InputMethodManagerServiceTraceProto.ELAPSED_REALTIME_NANOS, - SystemClock.elapsedRealtimeNanos()); - proto.write(InputMethodManagerServiceTraceProto.WHERE, where); - dumpDebug(proto, InputMethodManagerServiceTraceProto.INPUT_METHOD_MANAGER_SERVICE); - proto.end(managerservice_token); - break; - default: - // Dump triggered by a source not recognised. + public void startProtoDump(byte[] protoDump, int source, String where, + IVoidResultCallback resultCallback) { + CallbackUtils.onResult(resultCallback, () -> { + if (protoDump == null && source != IME_TRACING_FROM_IMMS) { + // Dump not triggered from IMMS, but no proto information provided. return; - } - tracingInstance.addToBuffer(proto, source); + } + ImeTracing tracingInstance = ImeTracing.getInstance(); + if (!tracingInstance.isAvailable() || !tracingInstance.isEnabled()) { + return; + } + + ProtoOutputStream proto = new ProtoOutputStream(); + switch (source) { + case ImeTracing.IME_TRACING_FROM_CLIENT: + final long client_token = proto.start(InputMethodClientsTraceFileProto.ENTRY); + proto.write(InputMethodClientsTraceProto.ELAPSED_REALTIME_NANOS, + SystemClock.elapsedRealtimeNanos()); + proto.write(InputMethodClientsTraceProto.WHERE, where); + proto.write(InputMethodClientsTraceProto.CLIENT, protoDump); + proto.end(client_token); + break; + case ImeTracing.IME_TRACING_FROM_IMS: + final long service_token = proto.start(InputMethodServiceTraceFileProto.ENTRY); + proto.write(InputMethodServiceTraceProto.ELAPSED_REALTIME_NANOS, + SystemClock.elapsedRealtimeNanos()); + proto.write(InputMethodServiceTraceProto.WHERE, where); + proto.write(InputMethodServiceTraceProto.INPUT_METHOD_SERVICE, protoDump); + proto.end(service_token); + break; + case IME_TRACING_FROM_IMMS: + final long managerservice_token = + proto.start(InputMethodManagerServiceTraceFileProto.ENTRY); + proto.write(InputMethodManagerServiceTraceProto.ELAPSED_REALTIME_NANOS, + SystemClock.elapsedRealtimeNanos()); + proto.write(InputMethodManagerServiceTraceProto.WHERE, where); + dumpDebug(proto, + InputMethodManagerServiceTraceProto.INPUT_METHOD_MANAGER_SERVICE); + proto.end(managerservice_token); + break; + default: + // Dump triggered by a source not recognised. + return; + } + tracingInstance.addToBuffer(proto, source); + }); } @BinderThread @@ -4183,40 +4187,44 @@ public class InputMethodManagerService extends IInputMethodManager.Stub @BinderThread @Override - public void startImeTrace() { - ImeTracing.getInstance().startTrace(null /* printwriter */); - ArrayMap<IBinder, ClientState> clients; - synchronized (mMethodMap) { - clients = new ArrayMap<>(mClients); - } - for (ClientState state : clients.values()) { - if (state != null) { - try { - state.client.setImeTraceEnabled(true /* enabled */); - } catch (RemoteException e) { - Slog.e(TAG, "Error while trying to enable ime trace on client window", e); + public void startImeTrace(IVoidResultCallback resultCallback) { + CallbackUtils.onResult(resultCallback, () -> { + ImeTracing.getInstance().startTrace(null /* printwriter */); + ArrayMap<IBinder, ClientState> clients; + synchronized (mMethodMap) { + clients = new ArrayMap<>(mClients); + } + for (ClientState state : clients.values()) { + if (state != null) { + try { + state.client.setImeTraceEnabled(true /* enabled */); + } catch (RemoteException e) { + Slog.e(TAG, "Error while trying to enable ime trace on client window", e); + } } } - } + }); } @BinderThread @Override - public void stopImeTrace() { - ImeTracing.getInstance().stopTrace(null /* printwriter */); - ArrayMap<IBinder, ClientState> clients; - synchronized (mMethodMap) { - clients = new ArrayMap<>(mClients); - } - for (ClientState state : clients.values()) { - if (state != null) { - try { - state.client.setImeTraceEnabled(false /* enabled */); - } catch (RemoteException e) { - Slog.e(TAG, "Error while trying to disable ime trace on client window", e); + public void stopImeTrace(IVoidResultCallback resultCallback) { + CallbackUtils.onResult(resultCallback, () -> { + ImeTracing.getInstance().stopTrace(null /* printwriter */); + ArrayMap<IBinder, ClientState> clients; + synchronized (mMethodMap) { + clients = new ArrayMap<>(mClients); + } + for (ClientState state : clients.values()) { + if (state != null) { + try { + state.client.setImeTraceEnabled(false /* enabled */); + } catch (RemoteException e) { + Slog.e(TAG, "Error while trying to disable ime trace on client window", e); + } } } - } + }); } @GuardedBy("mMethodMap") diff --git a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java index 7f9c76634422..6fec9063ba94 100644 --- a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java @@ -1868,7 +1868,9 @@ public final class MultiClientInputMethodManagerService { @BinderThread @Override - public void startProtoDump(byte[] clientProtoDump, int source, String where) { + public void startProtoDump(byte[] clientProtoDump, int source, String where, + IVoidResultCallback resultCallback) { + CallbackUtils.onResult(resultCallback, () -> { }); } @BinderThread @@ -1879,12 +1881,14 @@ public final class MultiClientInputMethodManagerService { @BinderThread @Override - public void startImeTrace() { + public void startImeTrace(IVoidResultCallback resultCallback) { + CallbackUtils.onResult(resultCallback, () -> { }); } @BinderThread @Override - public void stopImeTrace() { + public void stopImeTrace(IVoidResultCallback resultCallback) { + CallbackUtils.onResult(resultCallback, () -> { }); } } } diff --git a/services/core/java/com/android/server/location/contexthub/ContextHubService.java b/services/core/java/com/android/server/location/contexthub/ContextHubService.java index dc1a26ae6fea..785e6745087f 100644 --- a/services/core/java/com/android/server/location/contexthub/ContextHubService.java +++ b/services/core/java/com/android/server/location/contexthub/ContextHubService.java @@ -16,6 +16,7 @@ package com.android.server.location.contexthub; +import android.annotation.Nullable; import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.Context; @@ -320,6 +321,10 @@ public class ContextHubService extends IContextHubService.Stub { @Override public void onNanoAppDisabled(long nanoAppId) { } + + @Override + public void onClientAuthorizationChanged(long nanoAppId, int authorization) { + } }; } @@ -697,6 +702,7 @@ public class ContextHubService extends IContextHubService.Stub { * * @param contextHubId the ID of the hub this client is attached to * @param clientCallback the client interface to register with the service + * @param attributionTag an optional attribution tag within the given package * @return the generated client interface, null if registration was unsuccessful * @throws IllegalArgumentException if contextHubId is not a valid ID * @throws IllegalStateException if max number of clients have already registered @@ -704,7 +710,8 @@ public class ContextHubService extends IContextHubService.Stub { */ @Override public IContextHubClient createClient( - int contextHubId, IContextHubClientCallback clientCallback) throws RemoteException { + int contextHubId, IContextHubClientCallback clientCallback, + @Nullable String attributionTag) throws RemoteException { checkPermissions(); if (!isValidContextHubId(contextHubId)) { throw new IllegalArgumentException("Invalid context hub ID " + contextHubId); @@ -723,13 +730,15 @@ public class ContextHubService extends IContextHubService.Stub { * @param contextHubId the ID of the hub this client is attached to * @param pendingIntent the PendingIntent associated with this client * @param nanoAppId the ID of the nanoapp PendingIntent events will be sent for + * @param attributionTag an optional attribution tag within the given package * @return the generated client interface * @throws IllegalArgumentException if hubInfo does not represent a valid hub * @throws IllegalStateException if there were too many registered clients at the service */ @Override public IContextHubClient createPendingIntentClient( - int contextHubId, PendingIntent pendingIntent, long nanoAppId) throws RemoteException { + int contextHubId, PendingIntent pendingIntent, long nanoAppId, + @Nullable String attributionTag) throws RemoteException { checkPermissions(); if (!isValidContextHubId(contextHubId)) { throw new IllegalArgumentException("Invalid context hub ID " + contextHubId); diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index e32c00fe9a39..6843733eea9f 100755 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -377,7 +377,8 @@ public class NotificationManagerService extends SystemService { static final String[] DEFAULT_ALLOWED_ADJUSTMENTS = new String[] { Adjustment.KEY_CONTEXTUAL_ACTIONS, - Adjustment.KEY_TEXT_REPLIES}; + Adjustment.KEY_TEXT_REPLIES, + Adjustment.KEY_NOT_CONVERSATION}; static final String[] NON_BLOCKABLE_DEFAULT_ROLES = new String[] { RoleManager.ROLE_DIALER, @@ -2313,6 +2314,13 @@ public class NotificationManagerService extends SystemService { } else if ("false".equals(value)) { mAssistants.disallowAdjustmentType(Adjustment.KEY_RANKING_SCORE); } + } else if (SystemUiDeviceConfigFlags.ENABLE_NAS_NOT_CONVERSATION.equals(name)) { + String value = properties.getString(name, null); + if ("true".equals(value)) { + mAssistants.allowAdjustmentType(Adjustment.KEY_NOT_CONVERSATION); + } else if ("false".equals(value)) { + mAssistants.disallowAdjustmentType(Adjustment.KEY_NOT_CONVERSATION); + } } } }; @@ -9302,21 +9310,30 @@ public class NotificationManagerService extends SystemService { Slog.v(TAG, "onNotificationEnqueuedLocked() called with: r = [" + r + "]"); } final StatusBarNotification sbn = r.getSbn(); - notifyAssistantLocked( - sbn, - r.getNotificationType(), - true /* sameUserOnly */, - (assistant, sbnHolder) -> { - try { - if (debug) { - Slog.v(TAG, - "calling onNotificationEnqueuedWithChannel " + sbnHolder); - } - assistant.onNotificationEnqueuedWithChannel(sbnHolder, r.getChannel()); - } catch (RemoteException ex) { - Slog.e(TAG, "unable to notify assistant (enqueued): " + assistant, ex); + + for (final ManagedServiceInfo info : NotificationAssistants.this.getServices()) { + boolean sbnVisible = isVisibleToListener( + sbn, r.getNotificationType(), info) + && info.isSameUser(r.getUserId()); + if (sbnVisible) { + TrimCache trimCache = new TrimCache(sbn); + final INotificationListener assistant = (INotificationListener) info.service; + final StatusBarNotification sbnToPost = trimCache.ForListener(info); + final StatusBarNotificationHolder sbnHolder = + new StatusBarNotificationHolder(sbnToPost); + try { + if (debug) { + Slog.v(TAG, + "calling onNotificationEnqueuedWithChannel " + sbnHolder); } - }); + final NotificationRankingUpdate update = makeRankingUpdateLocked(info); + assistant.onNotificationEnqueuedWithChannel(sbnHolder, r.getChannel(), + update); + } catch (RemoteException ex) { + Slog.e(TAG, "unable to notify assistant (enqueued): " + assistant, ex); + } + } + } } @GuardedBy("mNotificationLock") diff --git a/services/core/java/com/android/server/notification/ValidateNotificationPeople.java b/services/core/java/com/android/server/notification/ValidateNotificationPeople.java index f59934fd6810..d7bc3bb8af28 100644 --- a/services/core/java/com/android/server/notification/ValidateNotificationPeople.java +++ b/services/core/java/com/android/server/notification/ValidateNotificationPeople.java @@ -523,27 +523,39 @@ public class ValidateNotificationPeople implements NotificationSignalExtractor { if (VERBOSE) Slog.i(TAG, "Executing: validation for: " + mKey); long timeStartMs = System.currentTimeMillis(); for (final String handle: mPendingLookups) { + final String cacheKey = getCacheKey(mContext.getUserId(), handle); LookupResult lookupResult = null; - final Uri uri = Uri.parse(handle); - if ("tel".equals(uri.getScheme())) { - if (DEBUG) Slog.d(TAG, "checking telephone URI: " + handle); - lookupResult = resolvePhoneContact(mContext, uri.getSchemeSpecificPart()); - } else if ("mailto".equals(uri.getScheme())) { - if (DEBUG) Slog.d(TAG, "checking mailto URI: " + handle); - lookupResult = resolveEmailContact(mContext, uri.getSchemeSpecificPart()); - } else if (handle.startsWith(Contacts.CONTENT_LOOKUP_URI.toString())) { - if (DEBUG) Slog.d(TAG, "checking lookup URI: " + handle); - lookupResult = searchContacts(mContext, uri); - } else { - lookupResult = new LookupResult(); // invalid person for the cache - if (!"name".equals(uri.getScheme())) { - Slog.w(TAG, "unsupported URI " + handle); + boolean cacheHit = false; + synchronized (mPeopleCache) { + lookupResult = mPeopleCache.get(cacheKey); + if (lookupResult != null && !lookupResult.isExpired()) { + // The name wasn't already added to the cache, no need to retry + cacheHit = true; + } + } + if (!cacheHit) { + final Uri uri = Uri.parse(handle); + if ("tel".equals(uri.getScheme())) { + if (DEBUG) Slog.d(TAG, "checking telephone URI: " + handle); + lookupResult = resolvePhoneContact(mContext, uri.getSchemeSpecificPart()); + } else if ("mailto".equals(uri.getScheme())) { + if (DEBUG) Slog.d(TAG, "checking mailto URI: " + handle); + lookupResult = resolveEmailContact(mContext, uri.getSchemeSpecificPart()); + } else if (handle.startsWith(Contacts.CONTENT_LOOKUP_URI.toString())) { + if (DEBUG) Slog.d(TAG, "checking lookup URI: " + handle); + lookupResult = searchContacts(mContext, uri); + } else { + lookupResult = new LookupResult(); // invalid person for the cache + if (!"name".equals(uri.getScheme())) { + Slog.w(TAG, "unsupported URI " + handle); + } } } if (lookupResult != null) { - synchronized (mPeopleCache) { - final String cacheKey = getCacheKey(mContext.getUserId(), handle); - mPeopleCache.put(cacheKey, lookupResult); + if (!cacheHit) { + synchronized (mPeopleCache) { + mPeopleCache.put(cacheKey, lookupResult); + } } if (DEBUG) { Slog.d(TAG, "lookup contactAffinity is " + lookupResult.getAffinity()); @@ -580,4 +592,3 @@ public class ValidateNotificationPeople implements NotificationSignalExtractor { } } } - diff --git a/services/core/java/com/android/server/pm/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java index e0b57e4ce42f..402f6467e82d 100644 --- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java +++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java @@ -118,8 +118,8 @@ public class BackgroundDexOptService extends JobService { // Schedule a one-off job which scans installed packages and updates // out-of-date oat files. js.schedule(new JobInfo.Builder(JOB_POST_BOOT_UPDATE, sDexoptServiceName) - .setMinimumLatency(TimeUnit.MINUTES.toMillis(1)) - .setOverrideDeadline(TimeUnit.MINUTES.toMillis(1)) + .setMinimumLatency(TimeUnit.MINUTES.toMillis(10)) + .setOverrideDeadline(TimeUnit.MINUTES.toMillis(60)) .build()); // Schedule a daily job which scans installed packages and compiles diff --git a/services/core/java/com/android/server/pm/DynamicCodeLoggingService.java b/services/core/java/com/android/server/pm/DynamicCodeLoggingService.java index da65fe2bc0ab..c65c2b112706 100644 --- a/services/core/java/com/android/server/pm/DynamicCodeLoggingService.java +++ b/services/core/java/com/android/server/pm/DynamicCodeLoggingService.java @@ -234,7 +234,7 @@ public class DynamicCodeLoggingService extends JobService { List<EventLog.Event> events = new ArrayList<>(); EventLog.readEvents(tags, events); - + Matcher matcher = EXECUTE_NATIVE_AUDIT_PATTERN.matcher(""); for (int i = 0; i < events.size(); ++i) { if (mAuditWatchingStopRequested) { Log.w(TAG, "Stopping AuditWatchingJob run at scheduler request"); @@ -259,7 +259,9 @@ public class DynamicCodeLoggingService extends JobService { // And then use a regular expression to verify it's one of the messages we're // interested in and to extract the path of the file being loaded. - Matcher matcher = EXECUTE_NATIVE_AUDIT_PATTERN.matcher(message); + // Reuse the Matcher to avoid unnecessary string garbage caused by libcore's + // regex matching. + matcher.reset(message); if (!matcher.matches()) { continue; } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index f772f63a08ac..f68113d5520a 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -347,6 +347,7 @@ import com.android.internal.content.PackageHelper; import com.android.internal.content.om.OverlayConfig; import com.android.internal.logging.MetricsLogger; import com.android.internal.os.SomeArgs; +import com.android.internal.policy.AttributeCache; import com.android.internal.telephony.CarrierAppUtils; import com.android.internal.util.ArrayUtils; import com.android.internal.util.ConcurrentUtils; @@ -355,7 +356,6 @@ import com.android.internal.util.FrameworkStatsLog; import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.Preconditions; import com.android.permission.persistence.RuntimePermissionsPersistence; -import com.android.server.AttributeCache; import com.android.server.DeviceIdleInternal; import com.android.server.EventLogTags; import com.android.server.FgThread; @@ -18819,9 +18819,11 @@ public class PackageManagerService extends IPackageManager.Stub final VersionInfo versionInfo = request.versionInfos.get(installPackageName); final boolean compareCompat = isCompatSignatureUpdateNeeded(versionInfo); final boolean compareRecover = isRecoverSignatureUpdateNeeded(versionInfo); + final boolean isRollback = installArgs != null + && installArgs.installReason == PackageManager.INSTALL_REASON_ROLLBACK; final boolean compatMatch = verifySignatures(signatureCheckPs, disabledPkgSetting, parsedPackage.getSigningDetails(), compareCompat, - compareRecover); + compareRecover, isRollback); // The new KeySets will be re-added later in the scanning process. if (compatMatch) { removeAppKeySetData = true; @@ -19791,6 +19793,7 @@ public class PackageManagerService extends IPackageManager.Stub final boolean fullApp = ((installFlags & PackageManager.INSTALL_FULL_APP) != 0); final boolean virtualPreload = ((installFlags & PackageManager.INSTALL_VIRTUAL_PRELOAD) != 0); + final boolean isRollback = args.installReason == PackageManager.INSTALL_REASON_ROLLBACK; @ScanFlags int scanFlags = SCAN_NEW_INSTALL | SCAN_UPDATE_SIGNATURE; if (args.move != null) { // moving a complete application; perform an initial scan on the new install location @@ -19971,7 +19974,8 @@ public class PackageManagerService extends IPackageManager.Stub parsedPackage); // We don't care about disabledPkgSetting on install for now. final boolean compatMatch = verifySignatures(signatureCheckPs, null, - parsedPackage.getSigningDetails(), compareCompat, compareRecover); + parsedPackage.getSigningDetails(), compareCompat, compareRecover, + isRollback); // The new KeySets will be re-added later in the scanning process. if (compatMatch) { synchronized (mLock) { @@ -20248,15 +20252,23 @@ public class PackageManagerService extends IPackageManager.Stub + pkgName11); } } else { + SigningDetails parsedPkgSigningDetails = parsedPackage.getSigningDetails(); + SigningDetails oldPkgSigningDetails = oldPackage.getSigningDetails(); // default to original signature matching - if (!parsedPackage.getSigningDetails().checkCapability( - oldPackage.getSigningDetails(), + if (!parsedPkgSigningDetails.checkCapability(oldPkgSigningDetails, SigningDetails.CertCapabilities.INSTALLED_DATA) - && !oldPackage.getSigningDetails().checkCapability( - parsedPackage.getSigningDetails(), + && !oldPkgSigningDetails.checkCapability(parsedPkgSigningDetails, SigningDetails.CertCapabilities.ROLLBACK)) { - throw new PrepareFailure(INSTALL_FAILED_UPDATE_INCOMPATIBLE, - "New package has a different signature: " + pkgName11); + // Allow the update to proceed if this is a rollback and the parsed + // package's current signing key is the current signer or in the lineage + // of the old package; this allows a rollback to a previously installed + // version after an app's signing key has been rotated without requiring + // the rollback capability on the previous signing key. + if (!isRollback || !oldPkgSigningDetails.hasAncestorOrSelf( + parsedPkgSigningDetails)) { + throw new PrepareFailure(INSTALL_FAILED_UPDATE_INCOMPATIBLE, + "New package has a different signature: " + pkgName11); + } } } diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java index ee94b8599625..8015063812e6 100644 --- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java +++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java @@ -624,7 +624,7 @@ public class PackageManagerServiceUtils { */ public static boolean verifySignatures(PackageSetting pkgSetting, PackageSetting disabledPkgSetting, PackageParser.SigningDetails parsedSignatures, - boolean compareCompat, boolean compareRecover) + boolean compareCompat, boolean compareRecover, boolean isRollback) throws PackageManagerException { final String packageName = pkgSetting.name; boolean compatMatch = false; @@ -658,6 +658,13 @@ public class PackageManagerServiceUtils { match = matchSignatureInSystem(pkgSetting, disabledPkgSetting); } + if (!match && isRollback) { + // Since a rollback can only be initiated for an APK previously installed on the + // device allow rolling back to a previous signing key even if the rollback + // capability has not been granted. + match = pkgSetting.signatures.mSigningDetails.hasAncestorOrSelf(parsedSignatures); + } + if (!match) { throw new PackageManagerException(INSTALL_FAILED_UPDATE_INCOMPATIBLE, "Package " + packageName + diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 89e7986fc4bc..a407e8e1b7df 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -188,7 +188,6 @@ import android.view.WindowManagerPolicyConstants; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; import android.view.animation.Animation; -import android.view.animation.AnimationSet; import android.view.animation.AnimationUtils; import android.view.autofill.AutofillManagerInternal; @@ -201,7 +200,9 @@ import com.android.internal.os.RoSystemProperties; import com.android.internal.policy.IKeyguardDismissCallback; import com.android.internal.policy.IShortcutService; import com.android.internal.policy.KeyInterceptionInfo; +import com.android.internal.policy.LogDecelerateInterpolator; import com.android.internal.policy.PhoneWindow; +import com.android.internal.policy.TransitionAnimation; import com.android.internal.statusbar.IStatusBarService; import com.android.internal.util.ArrayUtils; import com.android.server.ExtconStateObserver; @@ -228,7 +229,6 @@ import java.io.FileReader; import java.io.IOException; import java.io.PrintWriter; import java.util.HashSet; -import java.util.List; /** * WindowManagerPolicy implementation for the Android phone UI. This @@ -582,7 +582,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { private final SparseArray<KeyCharacterMap.FallbackAction> mFallbackActions = new SparseArray<KeyCharacterMap.FallbackAction>(); - private final LogDecelerateInterpolator mLogDecelerateInterpolator + private final com.android.internal.policy.LogDecelerateInterpolator mLogDecelerateInterpolator = new LogDecelerateInterpolator(100, 0); private final MutableBoolean mTmpBoolean = new MutableBoolean(false); @@ -2484,28 +2484,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { @Override public Animation createHiddenByKeyguardExit(boolean onWallpaper, boolean goingToNotificationShade, boolean subtleAnimation) { - if (goingToNotificationShade) { - return AnimationUtils.loadAnimation(mContext, R.anim.lock_screen_behind_enter_fade_in); - } - - final int resource; - if (subtleAnimation) { - resource = R.anim.lock_screen_behind_enter_subtle; - } else if (onWallpaper) { - resource = R.anim.lock_screen_behind_enter_wallpaper; - } else { - resource = R.anim.lock_screen_behind_enter; - } - - AnimationSet set = (AnimationSet) AnimationUtils.loadAnimation(mContext, resource); - - // TODO: Use XML interpolators when we have log interpolators available in XML. - final List<Animation> animations = set.getAnimations(); - for (int i = animations.size() - 1; i >= 0; --i) { - animations.get(i).setInterpolator(mLogDecelerateInterpolator); - } - - return set; + return TransitionAnimation.createHiddenByKeyguardExit(mContext, + mLogDecelerateInterpolator, onWallpaper, goingToNotificationShade, subtleAnimation); } diff --git a/services/core/java/com/android/server/rollback/Rollback.java b/services/core/java/com/android/server/rollback/Rollback.java index e12991a220c9..9560f59924de 100644 --- a/services/core/java/com/android/server/rollback/Rollback.java +++ b/services/core/java/com/android/server/rollback/Rollback.java @@ -563,6 +563,7 @@ class Rollback { params.setRequestDowngrade(true); params.setRequiredInstalledVersionCode( pkgRollbackInfo.getVersionRolledBackFrom().getLongVersionCode()); + params.setInstallReason(PackageManager.INSTALL_REASON_ROLLBACK); if (isStaged()) { params.setStaged(); } diff --git a/services/core/java/com/android/server/vcn/Vcn.java b/services/core/java/com/android/server/vcn/Vcn.java index 9d21b9241c0d..132883e4a041 100644 --- a/services/core/java/com/android/server/vcn/Vcn.java +++ b/services/core/java/com/android/server/vcn/Vcn.java @@ -168,8 +168,8 @@ public class Vcn extends Handler { @NonNull NetworkRequest request, int score, int providerId) { if (score > getNetworkScore()) { Slog.v(getLogTag(), - "Request " + request.requestId + " already satisfied by higher-scoring (" - + score + ") network from provider " + providerId); + "Request already satisfied by higher-scoring (" + score + ") network from " + + "provider " + providerId + ": " + request); return; } @@ -177,8 +177,7 @@ public class Vcn extends Handler { for (VcnGatewayConnectionConfig gatewayConnectionConfig : mVcnGatewayConnections.keySet()) { if (requestSatisfiedByGatewayConnectionConfig(request, gatewayConnectionConfig)) { Slog.v(getLogTag(), - "Request " + request.requestId - + " satisfied by existing VcnGatewayConnection"); + "Request already satisfied by existing VcnGatewayConnection: " + request); return; } } @@ -202,12 +201,12 @@ public class Vcn extends Handler { private boolean requestSatisfiedByGatewayConnectionConfig( @NonNull NetworkRequest request, @NonNull VcnGatewayConnectionConfig config) { - final NetworkCapabilities configCaps = new NetworkCapabilities(); + final NetworkCapabilities.Builder builder = new NetworkCapabilities.Builder(); for (int cap : config.getAllExposedCapabilities()) { - configCaps.addCapability(cap); + builder.addCapability(cap); } - return request.networkCapabilities.satisfiedByNetworkCapabilities(configCaps); + return request.canBeSatisfiedBy(builder.build()); } private String getLogTag() { diff --git a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java index 703bfab6d868..3cfa00eb6079 100644 --- a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java +++ b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java @@ -963,18 +963,18 @@ public class VcnGatewayConnection extends StateMachine { @VisibleForTesting(visibility = Visibility.PRIVATE) static NetworkCapabilities buildNetworkCapabilities( @NonNull VcnGatewayConnectionConfig gatewayConnectionConfig) { - final NetworkCapabilities caps = new NetworkCapabilities(); + final NetworkCapabilities.Builder builder = new NetworkCapabilities.Builder(); - caps.addTransportType(TRANSPORT_CELLULAR); - caps.addCapability(NET_CAPABILITY_NOT_CONGESTED); - caps.addCapability(NET_CAPABILITY_NOT_SUSPENDED); + builder.addTransportType(TRANSPORT_CELLULAR); + builder.addCapability(NET_CAPABILITY_NOT_CONGESTED); + builder.addCapability(NET_CAPABILITY_NOT_SUSPENDED); // Add exposed capabilities for (int cap : gatewayConnectionConfig.getAllExposedCapabilities()) { - caps.addCapability(cap); + builder.addCapability(cap); } - return caps; + return builder.build(); } private static LinkProperties buildConnectedLinkProperties( diff --git a/services/core/java/com/android/server/vcn/VcnNetworkProvider.java b/services/core/java/com/android/server/vcn/VcnNetworkProvider.java index 7f5b23c9db6f..b9babae4c6b7 100644 --- a/services/core/java/com/android/server/vcn/VcnNetworkProvider.java +++ b/services/core/java/com/android/server/vcn/VcnNetworkProvider.java @@ -21,9 +21,9 @@ import android.content.Context; import android.net.NetworkProvider; import android.net.NetworkRequest; import android.os.Looper; +import android.util.ArrayMap; import android.util.ArraySet; import android.util.Slog; -import android.util.SparseArray; import java.util.Objects; import java.util.Set; @@ -40,7 +40,13 @@ public class VcnNetworkProvider extends NetworkProvider { private static final String TAG = VcnNetworkProvider.class.getSimpleName(); private final Set<NetworkRequestListener> mListeners = new ArraySet<>(); - private final SparseArray<NetworkRequestEntry> mRequests = new SparseArray<>(); + + /** + * Cache of NetworkRequest(s), scores and network providers, keyed by NetworkRequest + * + * <p>NetworkRequests are immutable once created, and therefore can be used as stable keys. + */ + private final ArrayMap<NetworkRequest, NetworkRequestEntry> mRequests = new ArrayMap<>(); public VcnNetworkProvider(Context context, Looper looper) { super(context, looper, VcnNetworkProvider.class.getSimpleName()); @@ -51,8 +57,8 @@ public class VcnNetworkProvider extends NetworkProvider { mListeners.add(listener); // Send listener all cached requests - for (int i = 0; i < mRequests.size(); i++) { - notifyListenerForEvent(listener, mRequests.valueAt(i)); + for (NetworkRequestEntry entry : mRequests.values()) { + notifyListenerForEvent(listener, entry); } } @@ -75,7 +81,9 @@ public class VcnNetworkProvider extends NetworkProvider { request, score, providerId)); final NetworkRequestEntry entry = new NetworkRequestEntry(request, score, providerId); - mRequests.put(request.requestId, entry); + + // NetworkRequests are immutable once created, and therefore can be used as stable keys. + mRequests.put(request, entry); // TODO(b/176939047): Intelligently route requests to prioritized VcnInstances (based on // Default Data Sub, or similar) @@ -86,7 +94,7 @@ public class VcnNetworkProvider extends NetworkProvider { @Override public void onNetworkRequestWithdrawn(@NonNull NetworkRequest request) { - mRequests.remove(request.requestId); + mRequests.remove(request); } private static class NetworkRequestEntry { diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 3bb4c74b7dc0..4e359f2577c2 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -303,13 +303,13 @@ import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.ResolverActivity; import com.android.internal.content.ReferrerIntent; +import com.android.internal.policy.AttributeCache; import com.android.internal.protolog.common.ProtoLog; import com.android.internal.util.ToBooleanFunction; import com.android.internal.util.XmlUtils; import com.android.internal.util.function.pooled.PooledConsumer; import com.android.internal.util.function.pooled.PooledFunction; import com.android.internal.util.function.pooled.PooledLambda; -import com.android.server.AttributeCache; import com.android.server.LocalServices; import com.android.server.am.AppTimeTracker; import com.android.server.am.PendingIntentRecord; @@ -1431,14 +1431,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } /** - * @return {@code true} if bar shown within a given rectangle is allowed to be transparent + * @return {@code true} if bar shown within a given rectangle is allowed to be fully transparent * when the current activity is displayed. */ - boolean isTransparentBarAllowed(Rect rect) { - // TODO(b/175482966): Allow status and navigation bars to be semi-transparent black - // in letterbox mode. - return mLetterbox == null || mLetterbox.notIntersectsOrFullyContains(rect) - || mWmService.isLetterboxActivityCornersRounded(); + boolean isFullyTransparentBarAllowed(Rect rect) { + return mLetterbox == null || mLetterbox.notIntersectsOrFullyContains(rect); } /** @@ -2183,6 +2180,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } /** @return Root task of this activity, null if there is no task. */ + @Nullable Task getRootTask() { return task != null ? task.getRootTask() : null; } @@ -2191,6 +2189,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A return task != null ? task.getRootTaskId() : INVALID_TASK_ID; } + /** @return the first organized parent task. */ + @Nullable + Task getOrganizedTask() { + return task != null ? task.getOrganizedTask() : null; + } + @Override @Nullable TaskDisplayArea getDisplayArea() { diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index 9e2e58fddd18..64b1e042a58c 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -232,13 +232,13 @@ import com.android.internal.app.ProcessMap; import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; import com.android.internal.notification.SystemNotificationChannels; import com.android.internal.os.TransferPipe; +import com.android.internal.policy.AttributeCache; import com.android.internal.policy.KeyguardDismissCallback; import com.android.internal.protolog.common.ProtoLog; import com.android.internal.util.ArrayUtils; import com.android.internal.util.FastPrintWriter; import com.android.internal.util.FrameworkStatsLog; import com.android.internal.util.function.pooled.PooledLambda; -import com.android.server.AttributeCache; import com.android.server.LocalServices; import com.android.server.SystemService; import com.android.server.SystemServiceManager; @@ -486,13 +486,13 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { * Whether normal application switches are allowed; a call to {@link #stopAppSwitches() * disables this. */ - private boolean mAppSwitchesAllowed = true; + private volatile boolean mAppSwitchesAllowed = true; /** * Last stop app switches time, apps finished before this time cannot start background activity * even if they are in grace period. */ - private long mLastStopAppSwitchesTime; + private volatile long mLastStopAppSwitchesTime; IActivityController mController = null; boolean mControllerIsAMonkey = false; @@ -698,6 +698,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { int OOM_ADJUSTMENT = 1; int LRU_UPDATE = 2; int PROCESS_CHANGE = 3; + int START_SERVICE = 4; int caller() default NONE; } @@ -4744,6 +4745,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } /** A uid is considered to be foreground if it has a visible non-toast window. */ + @HotPath(caller = HotPath.START_SERVICE) boolean hasActiveVisibleWindow(int uid) { if (mVisibleActivityProcessTracker.hasVisibleActivity(uid)) { return true; diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java index f8b498797ff3..90070c8f5068 100644 --- a/services/core/java/com/android/server/wm/AppTransition.java +++ b/services/core/java/com/android/server/wm/AppTransition.java @@ -78,6 +78,10 @@ import static com.android.internal.R.styleable.WindowAnimation_wallpaperIntraOpe import static com.android.internal.R.styleable.WindowAnimation_wallpaperIntraOpenExitAnimation; import static com.android.internal.R.styleable.WindowAnimation_wallpaperOpenEnterAnimation; import static com.android.internal.R.styleable.WindowAnimation_wallpaperOpenExitAnimation; +import static com.android.internal.policy.TransitionAnimation.THUMBNAIL_TRANSITION_ENTER_SCALE_DOWN; +import static com.android.internal.policy.TransitionAnimation.THUMBNAIL_TRANSITION_ENTER_SCALE_UP; +import static com.android.internal.policy.TransitionAnimation.THUMBNAIL_TRANSITION_EXIT_SCALE_DOWN; +import static com.android.internal.policy.TransitionAnimation.THUMBNAIL_TRANSITION_EXIT_SCALE_UP; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS_ANIM; import static com.android.server.wm.AppTransitionProto.APP_TRANSITION_STATE; @@ -96,9 +100,6 @@ import android.app.ActivityManager; import android.content.ComponentName; import android.content.Context; import android.content.res.Configuration; -import android.content.res.ResourceId; -import android.content.res.Resources; -import android.content.res.Resources.NotFoundException; import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.Canvas; @@ -136,15 +137,12 @@ import android.view.animation.PathInterpolator; import android.view.animation.ScaleAnimation; import android.view.animation.TranslateAnimation; -import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.policy.TransitionAnimation; import com.android.internal.protolog.common.ProtoLog; import com.android.internal.util.DumpUtils.Dump; import com.android.internal.util.function.pooled.PooledLambda; import com.android.internal.util.function.pooled.PooledPredicate; -import com.android.server.AttributeCache; -import com.android.server.wm.animation.ClipRectLRAnimation; -import com.android.server.wm.animation.ClipRectTBAnimation; import java.io.PrintWriter; import java.util.ArrayList; @@ -184,6 +182,8 @@ public class AppTransition implements Dump { private final WindowManagerService mService; private final DisplayContent mDisplayContent; + private final TransitionAnimation mTransitionAnimation; + private @TransitionFlags int mNextAppTransitionFlags = 0; private final ArrayList<Integer> mNextAppTransitionRequests = new ArrayList<>(); private @TransitionOldType int mLastUsedAppTransition = TRANSIT_OLD_UNSET; @@ -212,12 +212,6 @@ public class AppTransition implements Dump { private int mNextAppTransitionType = NEXT_TRANSIT_TYPE_NONE; private boolean mNextAppTransitionOverrideRequested; - // These are the possible states for the enter/exit activities during a thumbnail transition - private static final int THUMBNAIL_TRANSITION_ENTER_SCALE_UP = 0; - private static final int THUMBNAIL_TRANSITION_EXIT_SCALE_UP = 1; - private static final int THUMBNAIL_TRANSITION_ENTER_SCALE_DOWN = 2; - private static final int THUMBNAIL_TRANSITION_EXIT_SCALE_DOWN = 3; - private String mNextAppTransitionPackage; // Used for thumbnail transitions. True if we're scaling up, false if scaling down private boolean mNextAppTransitionScaleUp; @@ -283,6 +277,7 @@ public class AppTransition implements Dump { mService = service; mHandler = new Handler(service.mH.getLooper()); mDisplayContent = displayContent; + mTransitionAnimation = new TransitionAnimation(context, DEBUG_ANIM, TAG); mLinearOutSlowInInterpolator = AnimationUtils.loadInterpolator(context, com.android.internal.R.interpolator.linear_out_slow_in); mFastOutLinearInInterpolator = AnimationUtils.loadInterpolator(context, @@ -555,242 +550,18 @@ public class AppTransition implements Dump { /** Returns window animation style ID from {@link LayoutParams} or from system in some cases */ @VisibleForTesting int getAnimationStyleResId(@NonNull LayoutParams lp) { - int resId = lp.windowAnimations; - if (lp.type == LayoutParams.TYPE_APPLICATION_STARTING) { - // Note that we don't want application to customize starting window animation. - // Since this window is specific for displaying while app starting, - // application should not change its animation directly. - // In this case, it will use system resource to get default animation. - resId = mDefaultWindowAnimationStyleResId; - } - return resId; - } - - private AttributeCache.Entry getCachedAnimations(LayoutParams lp) { - if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: layout params pkg=" - + (lp != null ? lp.packageName : null) - + " resId=0x" + (lp != null ? Integer.toHexString(lp.windowAnimations) : null)); - if (lp != null && lp.windowAnimations != 0) { - // If this is a system resource, don't try to load it from the - // application resources. It is nice to avoid loading application - // resources if we can. - String packageName = lp.packageName != null ? lp.packageName : "android"; - int resId = getAnimationStyleResId(lp); - if ((resId&0xFF000000) == 0x01000000) { - packageName = "android"; - } - if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: picked package=" - + packageName); - return AttributeCache.instance().get(packageName, resId, - com.android.internal.R.styleable.WindowAnimation, mCurrentUserId); - } - return null; - } - - private AttributeCache.Entry getCachedAnimations(String packageName, int resId) { - if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: package=" - + packageName + " resId=0x" + Integer.toHexString(resId)); - if (packageName != null) { - if ((resId&0xFF000000) == 0x01000000) { - packageName = "android"; - } - if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: picked package=" - + packageName); - return AttributeCache.instance().get(packageName, resId, - com.android.internal.R.styleable.WindowAnimation, mCurrentUserId); - } - return null; - } - - Animation loadAnimationAttr(LayoutParams lp, int animAttr, int transit) { - int resId = Resources.ID_NULL; - Context context = mContext; - if (animAttr >= 0) { - AttributeCache.Entry ent = getCachedAnimations(lp); - if (ent != null) { - context = ent.context; - resId = ent.array.getResourceId(animAttr, 0); - } - } - resId = updateToTranslucentAnimIfNeeded(resId, transit); - if (ResourceId.isValid(resId)) { - return loadAnimationSafely(context, resId); - } - return null; - } - - private Animation loadAnimationRes(LayoutParams lp, int resId) { - Context context = mContext; - if (ResourceId.isValid(resId)) { - AttributeCache.Entry ent = getCachedAnimations(lp); - if (ent != null) { - context = ent.context; - } - return loadAnimationSafely(context, resId); - } - return null; - } - - private Animation loadAnimationRes(String packageName, int resId) { - if (ResourceId.isValid(resId)) { - AttributeCache.Entry ent = getCachedAnimations(packageName, resId); - if (ent != null) { - return loadAnimationSafely(ent.context, resId); - } - } - return null; + return mTransitionAnimation.getAnimationStyleResId(lp); } @VisibleForTesting + @Nullable Animation loadAnimationSafely(Context context, int resId) { - try { - return AnimationUtils.loadAnimation(context, resId); - } catch (NotFoundException e) { - Slog.w(TAG, "Unable to load animation resource", e); - return null; - } - } - - private int updateToTranslucentAnimIfNeeded(int anim, @TransitionOldType int transit) { - if (transit == TRANSIT_OLD_TRANSLUCENT_ACTIVITY_OPEN - && anim == R.anim.activity_open_enter) { - return R.anim.activity_translucent_open_enter; - } - if (transit == TRANSIT_OLD_TRANSLUCENT_ACTIVITY_CLOSE - && anim == R.anim.activity_close_exit) { - return R.anim.activity_translucent_close_exit; - } - return anim; - } - - /** - * Compute the pivot point for an animation that is scaling from a small - * rect on screen to a larger rect. The pivot point varies depending on - * the distance between the inner and outer edges on both sides. This - * function computes the pivot point for one dimension. - * @param startPos Offset from left/top edge of outer rectangle to - * left/top edge of inner rectangle. - * @param finalScale The scaling factor between the size of the outer - * and inner rectangles. - */ - private static float computePivot(int startPos, float finalScale) { - - /* - Theorem of intercepting lines: - - + + +-----------------------------------------------+ - | | | | - | | | | - | | | | - | | | | - x | y | | | - | | | | - | | | | - | | | | - | | | | - | + | +--------------------+ | - | | | | | - | | | | | - | | | | | - | | | | | - | | | | | - | | | | | - | | | | | - | | | | | - | | | | | - | | | | | - | | | | | - | | | | | - | | | | | - | | | | | - | | | | | - | | | | | - | | | | | - | | +--------------------+ | - | | | - | | | - | | | - | | | - | | | - | | | - | | | - | +-----------------------------------------------+ - | - | - | - | - | - | - | - | - | - + ++ - p ++ - - scale = (x - y) / x - <=> x = -y / (scale - 1) - */ - final float denom = finalScale-1; - if (Math.abs(denom) < .0001f) { - return startPos; - } - return -startPos / denom; + return TransitionAnimation.loadAnimationSafely(context, resId, TAG); } - private Animation createScaleUpAnimationLocked(int transit, boolean enter, - Rect containingFrame) { - Animation a; - getDefaultNextAppTransitionStartRect(mTmpRect); - final int appWidth = containingFrame.width(); - final int appHeight = containingFrame.height(); - if (enter) { - // Entering app zooms out from the center of the initial rect. - float scaleW = mTmpRect.width() / (float) appWidth; - float scaleH = mTmpRect.height() / (float) appHeight; - Animation scale = new ScaleAnimation(scaleW, 1, scaleH, 1, - computePivot(mTmpRect.left, scaleW), - computePivot(mTmpRect.top, scaleH)); - scale.setInterpolator(mDecelerateInterpolator); - - Animation alpha = new AlphaAnimation(0, 1); - alpha.setInterpolator(mThumbnailFadeOutInterpolator); - - AnimationSet set = new AnimationSet(false); - set.addAnimation(scale); - set.addAnimation(alpha); - set.setDetachWallpaper(true); - a = set; - } else if (transit == TRANSIT_OLD_WALLPAPER_INTRA_OPEN - || transit == TRANSIT_OLD_WALLPAPER_INTRA_CLOSE) { - // If we are on top of the wallpaper, we need an animation that - // correctly handles the wallpaper staying static behind all of - // the animated elements. To do this, will just have the existing - // element fade out. - a = new AlphaAnimation(1, 0); - a.setDetachWallpaper(true); - } else { - // For normal animations, the exiting element just holds in place. - a = new AlphaAnimation(1, 1); - } - - // Pick the desired duration. If this is an inter-activity transition, - // it is the standard duration for that. Otherwise we use the longer - // task transition duration. - final long duration; - switch (transit) { - case TRANSIT_OLD_ACTIVITY_OPEN: - case TRANSIT_OLD_ACTIVITY_CLOSE: - duration = mConfigShortAnimTime; - break; - default: - duration = DEFAULT_APP_TRANSITION_DURATION; - break; - } - a.setDuration(duration); - a.setFillAfter(true); - a.setInterpolator(mDecelerateInterpolator); - a.initialize(appWidth, appHeight, appWidth, appHeight); - return a; + @Nullable + Animation loadAnimationAttr(LayoutParams lp, int animAttr, int transit) { + return mTransitionAnimation.loadAnimationAttr(lp, animAttr, transit); } private void getDefaultNextAppTransitionStartRect(Rect rect) { @@ -825,27 +596,6 @@ public class AppTransition implements Dump { } /** - * @return the duration of the last clip reveal animation - */ - long getLastClipRevealTransitionDuration() { - return mLastClipRevealTransitionDuration; - } - - /** - * @return the maximum distance the app surface is traveling of the last clip reveal animation - */ - int getLastClipRevealMaxTranslation() { - return mLastClipRevealMaxTranslation; - } - - /** - * @return true if in the last app transition had a clip reveal animation, false otherwise - */ - boolean hadClipRevealAnimation() { - return mLastHadClipReveal; - } - - /** * Calculates the duration for the clip reveal animation. If the clip is "cut off", meaning that * the start rect is outside of the target rect, and there is a lot of movement going on. * @@ -867,137 +617,21 @@ public class AppTransition implements Dump { (MAX_CLIP_REVEAL_TRANSITION_DURATION - DEFAULT_APP_TRANSITION_DURATION)); } - private Animation createClipRevealAnimationLocked(int transit, boolean enter, Rect appFrame, - Rect displayFrame) { - final Animation anim; - if (enter) { - final int appWidth = appFrame.width(); - final int appHeight = appFrame.height(); - - // mTmpRect will contain an area around the launcher icon that was pressed. We will - // clip reveal from that area in the final area of the app. - getDefaultNextAppTransitionStartRect(mTmpRect); - - float t = 0f; - if (appHeight > 0) { - t = (float) mTmpRect.top / displayFrame.height(); - } - int translationY = mClipRevealTranslationY + (int)(displayFrame.height() / 7f * t); - int translationX = 0; - int translationYCorrection = translationY; - int centerX = mTmpRect.centerX(); - int centerY = mTmpRect.centerY(); - int halfWidth = mTmpRect.width() / 2; - int halfHeight = mTmpRect.height() / 2; - int clipStartX = centerX - halfWidth - appFrame.left; - int clipStartY = centerY - halfHeight - appFrame.top; - boolean cutOff = false; - - // If the starting rectangle is fully or partially outside of the target rectangle, we - // need to start the clipping at the edge and then achieve the rest with translation - // and extending the clip rect from that edge. - if (appFrame.top > centerY - halfHeight) { - translationY = (centerY - halfHeight) - appFrame.top; - translationYCorrection = 0; - clipStartY = 0; - cutOff = true; - } - if (appFrame.left > centerX - halfWidth) { - translationX = (centerX - halfWidth) - appFrame.left; - clipStartX = 0; - cutOff = true; - } - if (appFrame.right < centerX + halfWidth) { - translationX = (centerX + halfWidth) - appFrame.right; - clipStartX = appWidth - mTmpRect.width(); - cutOff = true; - } - final long duration = calculateClipRevealTransitionDuration(cutOff, translationX, - translationY, displayFrame); - - // Clip third of the from size of launch icon, expand to full width/height - Animation clipAnimLR = new ClipRectLRAnimation( - clipStartX, clipStartX + mTmpRect.width(), 0, appWidth); - clipAnimLR.setInterpolator(mClipHorizontalInterpolator); - clipAnimLR.setDuration((long) (duration / 2.5f)); - - TranslateAnimation translate = new TranslateAnimation(translationX, 0, translationY, 0); - translate.setInterpolator(cutOff ? TOUCH_RESPONSE_INTERPOLATOR - : mLinearOutSlowInInterpolator); - translate.setDuration(duration); - - Animation clipAnimTB = new ClipRectTBAnimation( - clipStartY, clipStartY + mTmpRect.height(), - 0, appHeight, - translationYCorrection, 0, - mLinearOutSlowInInterpolator); - clipAnimTB.setInterpolator(TOUCH_RESPONSE_INTERPOLATOR); - clipAnimTB.setDuration(duration); - - // Quick fade-in from icon to app window - final long alphaDuration = duration / 4; - AlphaAnimation alpha = new AlphaAnimation(0.5f, 1); - alpha.setDuration(alphaDuration); - alpha.setInterpolator(mLinearOutSlowInInterpolator); - - AnimationSet set = new AnimationSet(false); - set.addAnimation(clipAnimLR); - set.addAnimation(clipAnimTB); - set.addAnimation(translate); - set.addAnimation(alpha); - set.setZAdjustment(Animation.ZORDER_TOP); - set.initialize(appWidth, appHeight, appWidth, appHeight); - anim = set; - mLastHadClipReveal = true; - mLastClipRevealTransitionDuration = duration; - - // If the start rect was full inside the target rect (cutOff == false), we don't need - // to store the translation, because it's only used if cutOff == true. - mLastClipRevealMaxTranslation = cutOff - ? Math.max(Math.abs(translationY), Math.abs(translationX)) : 0; - } else { - final long duration; - switch (transit) { - case TRANSIT_OLD_ACTIVITY_OPEN: - case TRANSIT_OLD_ACTIVITY_CLOSE: - duration = mConfigShortAnimTime; - break; - default: - duration = DEFAULT_APP_TRANSITION_DURATION; - break; - } - if (transit == TRANSIT_OLD_WALLPAPER_INTRA_OPEN - || transit == TRANSIT_OLD_WALLPAPER_INTRA_CLOSE) { - // If we are on top of the wallpaper, we need an animation that - // correctly handles the wallpaper staying static behind all of - // the animated elements. To do this, will just have the existing - // element fade out. - anim = new AlphaAnimation(1, 0); - anim.setDetachWallpaper(true); - } else { - // For normal animations, the exiting element just holds in place. - anim = new AlphaAnimation(1, 1); - } - anim.setInterpolator(mDecelerateInterpolator); - anim.setDuration(duration); - anim.setFillAfter(true); - } - return anim; - } - /** * Prepares the specified animation with a standard duration, interpolator, etc. */ - Animation prepareThumbnailAnimationWithDuration(Animation a, int appWidth, int appHeight, - long duration, Interpolator interpolator) { - if (duration > 0) { - a.setDuration(duration); - } - a.setFillAfter(true); - if (interpolator != null) { - a.setInterpolator(interpolator); + Animation prepareThumbnailAnimationWithDuration(@Nullable Animation a, int appWidth, + int appHeight, long duration, Interpolator interpolator) { + if (a != null) { + if (duration > 0) { + a.setDuration(duration); + } + a.setFillAfter(true); + if (interpolator != null) { + a.setInterpolator(interpolator); + } + a.initialize(appWidth, appHeight, appWidth, appHeight); } - a.initialize(appWidth, appHeight, appWidth, appHeight); return a; } @@ -1069,8 +703,8 @@ public class AppTransition implements Dump { } Animation createCrossProfileAppsThumbnailAnimationLocked(Rect appRect) { - final Animation animation = loadAnimationRes( - "android", com.android.internal.R.anim.cross_profile_apps_thumbnail_enter); + final Animation animation = + mTransitionAnimation.loadCrossProfileAppThumbnailEnterAnimation(); return prepareThumbnailAnimationWithDuration(animation, appRect.width(), appRect.height(), 0, null); } @@ -1203,145 +837,6 @@ public class AppTransition implements Dump { return TOUCH_RESPONSE_INTERPOLATOR; } - /** - * This alternate animation is created when we are doing a thumbnail transition, for the - * activity that is leaving, and the activity that is entering. - */ - Animation createAspectScaledThumbnailEnterExitAnimationLocked(int thumbTransitState, - int uiMode, int orientation, int transit, Rect containingFrame, Rect contentInsets, - @Nullable Rect surfaceInsets, @Nullable Rect stableInsets, boolean freeform, - WindowContainer container) { - Animation a; - final int appWidth = containingFrame.width(); - final int appHeight = containingFrame.height(); - getDefaultNextAppTransitionStartRect(mTmpRect); - final int thumbWidthI = mTmpRect.width(); - final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1; - final int thumbHeightI = mTmpRect.height(); - final float thumbHeight = thumbHeightI > 0 ? thumbHeightI : 1; - final int thumbStartX = mTmpRect.left - containingFrame.left - contentInsets.left; - final int thumbStartY = mTmpRect.top - containingFrame.top; - - switch (thumbTransitState) { - case THUMBNAIL_TRANSITION_ENTER_SCALE_UP: - case THUMBNAIL_TRANSITION_EXIT_SCALE_DOWN: { - final boolean scaleUp = thumbTransitState == THUMBNAIL_TRANSITION_ENTER_SCALE_UP; - if (freeform && scaleUp) { - a = createAspectScaledThumbnailEnterFreeformAnimationLocked( - containingFrame, surfaceInsets, container); - } else if (freeform) { - a = createAspectScaledThumbnailExitFreeformAnimationLocked( - containingFrame, surfaceInsets, container); - } else { - AnimationSet set = new AnimationSet(true); - - // In portrait, we scale to fit the width - mTmpFromClipRect.set(containingFrame); - mTmpToClipRect.set(containingFrame); - - // Containing frame is in screen space, but we need the clip rect in the - // app space. - mTmpFromClipRect.offsetTo(0, 0); - mTmpToClipRect.offsetTo(0, 0); - - // Exclude insets region from the source clip. - mTmpFromClipRect.inset(contentInsets); - mNextAppTransitionInsets.set(contentInsets); - - if (shouldScaleDownThumbnailTransition(uiMode, orientation)) { - // We scale the width and clip to the top/left square - float scale = thumbWidth / - (appWidth - contentInsets.left - contentInsets.right); - if (!mGridLayoutRecentsEnabled) { - int unscaledThumbHeight = (int) (thumbHeight / scale); - mTmpFromClipRect.bottom = mTmpFromClipRect.top + unscaledThumbHeight; - } - - mNextAppTransitionInsets.set(contentInsets); - - Animation scaleAnim = new ScaleAnimation( - scaleUp ? scale : 1, scaleUp ? 1 : scale, - scaleUp ? scale : 1, scaleUp ? 1 : scale, - containingFrame.width() / 2f, - containingFrame.height() / 2f + contentInsets.top); - final float targetX = (mTmpRect.left - containingFrame.left); - final float x = containingFrame.width() / 2f - - containingFrame.width() / 2f * scale; - final float targetY = (mTmpRect.top - containingFrame.top); - float y = containingFrame.height() / 2f - - containingFrame.height() / 2f * scale; - - // During transition may require clipping offset from any top stable insets - // such as the statusbar height when statusbar is hidden - if (mLowRamRecentsEnabled && contentInsets.top == 0 && scaleUp) { - mTmpFromClipRect.top += stableInsets.top; - y += stableInsets.top; - } - final float startX = targetX - x; - final float startY = targetY - y; - Animation clipAnim = scaleUp - ? new ClipRectAnimation(mTmpFromClipRect, mTmpToClipRect) - : new ClipRectAnimation(mTmpToClipRect, mTmpFromClipRect); - Animation translateAnim = scaleUp - ? createCurvedMotion(startX, 0, startY - contentInsets.top, 0) - : createCurvedMotion(0, startX, 0, startY - contentInsets.top); - - set.addAnimation(clipAnim); - set.addAnimation(scaleAnim); - set.addAnimation(translateAnim); - - } else { - // In landscape, we don't scale at all and only crop - mTmpFromClipRect.bottom = mTmpFromClipRect.top + thumbHeightI; - mTmpFromClipRect.right = mTmpFromClipRect.left + thumbWidthI; - - Animation clipAnim = scaleUp - ? new ClipRectAnimation(mTmpFromClipRect, mTmpToClipRect) - : new ClipRectAnimation(mTmpToClipRect, mTmpFromClipRect); - Animation translateAnim = scaleUp - ? createCurvedMotion(thumbStartX, 0, - thumbStartY - contentInsets.top, 0) - : createCurvedMotion(0, thumbStartX, 0, - thumbStartY - contentInsets.top); - - set.addAnimation(clipAnim); - set.addAnimation(translateAnim); - } - a = set; - a.setZAdjustment(Animation.ZORDER_TOP); - } - break; - } - case THUMBNAIL_TRANSITION_EXIT_SCALE_UP: { - // Previous app window during the scale up - if (transit == TRANSIT_OLD_WALLPAPER_INTRA_OPEN) { - // Fade out the source activity if we are animating to a wallpaper - // activity. - a = new AlphaAnimation(1, 0); - } else { - a = new AlphaAnimation(1, 1); - } - break; - } - case THUMBNAIL_TRANSITION_ENTER_SCALE_DOWN: { - // Target app window during the scale down - if (transit == TRANSIT_OLD_WALLPAPER_INTRA_OPEN) { - // Fade in the destination activity if we are animating from a wallpaper - // activity. - a = new AlphaAnimation(0, 1); - } else { - a = new AlphaAnimation(1, 1); - } - break; - } - default: - throw new RuntimeException("Invalid thumbnail transition state"); - } - - return prepareThumbnailAnimationWithDuration(a, appWidth, appHeight, - getAspectScaleDuration(), getAspectScaleInterpolator()); - } - private Animation createAspectScaledThumbnailEnterFreeformAnimationLocked(Rect frame, @Nullable Rect surfaceInsets, WindowContainer container) { getNextAppTransitionStartRect(container, mTmpRect); @@ -1408,8 +903,8 @@ public class AppTransition implements Dump { float scaleW = appWidth / thumbWidth; float scaleH = appHeight / thumbHeight; Animation scale = new ScaleAnimation(1, scaleW, 1, scaleH, - computePivot(mTmpRect.left, 1 / scaleW), - computePivot(mTmpRect.top, 1 / scaleH)); + TransitionAnimation.computePivot(mTmpRect.left, 1 / scaleW), + TransitionAnimation.computePivot(mTmpRect.top, 1 / scaleH)); scale.setInterpolator(mDecelerateInterpolator); Animation alpha = new AlphaAnimation(1, 0); @@ -1425,124 +920,13 @@ public class AppTransition implements Dump { float scaleW = appWidth / thumbWidth; float scaleH = appHeight / thumbHeight; a = new ScaleAnimation(scaleW, 1, scaleH, 1, - computePivot(mTmpRect.left, 1 / scaleW), - computePivot(mTmpRect.top, 1 / scaleH)); - } - - return prepareThumbnailAnimation(a, appWidth, appHeight, transit); - } - - /** - * This animation is created when we are doing a thumbnail transition, for the activity that is - * leaving, and the activity that is entering. - */ - Animation createThumbnailEnterExitAnimationLocked(int thumbTransitState, Rect containingFrame, - int transit, WindowContainer container) { - final int appWidth = containingFrame.width(); - final int appHeight = containingFrame.height(); - final HardwareBuffer thumbnailHeader = getAppTransitionThumbnailHeader(container); - Animation a; - getDefaultNextAppTransitionStartRect(mTmpRect); - final int thumbWidthI = thumbnailHeader != null ? thumbnailHeader.getWidth() : appWidth; - final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1; - final int thumbHeightI = thumbnailHeader != null ? thumbnailHeader.getHeight() : appHeight; - final float thumbHeight = thumbHeightI > 0 ? thumbHeightI : 1; - - switch (thumbTransitState) { - case THUMBNAIL_TRANSITION_ENTER_SCALE_UP: { - // Entering app scales up with the thumbnail - float scaleW = thumbWidth / appWidth; - float scaleH = thumbHeight / appHeight; - a = new ScaleAnimation(scaleW, 1, scaleH, 1, - computePivot(mTmpRect.left, scaleW), - computePivot(mTmpRect.top, scaleH)); - break; - } - case THUMBNAIL_TRANSITION_EXIT_SCALE_UP: { - // Exiting app while the thumbnail is scaling up should fade or stay in place - if (transit == TRANSIT_OLD_WALLPAPER_INTRA_OPEN) { - // Fade out while bringing up selected activity. This keeps the - // current activity from showing through a launching wallpaper - // activity. - a = new AlphaAnimation(1, 0); - } else { - // noop animation - a = new AlphaAnimation(1, 1); - } - break; - } - case THUMBNAIL_TRANSITION_ENTER_SCALE_DOWN: { - // Entering the other app, it should just be visible while we scale the thumbnail - // down above it - a = new AlphaAnimation(1, 1); - break; - } - case THUMBNAIL_TRANSITION_EXIT_SCALE_DOWN: { - // Exiting the current app, the app should scale down with the thumbnail - float scaleW = thumbWidth / appWidth; - float scaleH = thumbHeight / appHeight; - Animation scale = new ScaleAnimation(1, scaleW, 1, scaleH, - computePivot(mTmpRect.left, scaleW), - computePivot(mTmpRect.top, scaleH)); - - Animation alpha = new AlphaAnimation(1, 0); - - AnimationSet set = new AnimationSet(true); - set.addAnimation(scale); - set.addAnimation(alpha); - set.setZAdjustment(Animation.ZORDER_TOP); - a = set; - break; - } - default: - throw new RuntimeException("Invalid thumbnail transition state"); + TransitionAnimation.computePivot(mTmpRect.left, 1 / scaleW), + TransitionAnimation.computePivot(mTmpRect.top, 1 / scaleH)); } return prepareThumbnailAnimation(a, appWidth, appHeight, transit); } - private Animation createRelaunchAnimation(Rect containingFrame, Rect contentInsets) { - getDefaultNextAppTransitionStartRect(mTmpFromClipRect); - final int left = mTmpFromClipRect.left; - final int top = mTmpFromClipRect.top; - mTmpFromClipRect.offset(-left, -top); - // TODO: Isn't that strange that we ignore exact position of the containingFrame? - mTmpToClipRect.set(0, 0, containingFrame.width(), containingFrame.height()); - AnimationSet set = new AnimationSet(true); - float fromWidth = mTmpFromClipRect.width(); - float toWidth = mTmpToClipRect.width(); - float fromHeight = mTmpFromClipRect.height(); - // While the window might span the whole display, the actual content will be cropped to the - // system decoration frame, for example when the window is docked. We need to take into - // account the visible height when constructing the animation. - float toHeight = mTmpToClipRect.height() - contentInsets.top - contentInsets.bottom; - int translateAdjustment = 0; - if (fromWidth <= toWidth && fromHeight <= toHeight) { - // The final window is larger in both dimensions than current window (e.g. we are - // maximizing), so we can simply unclip the new window and there will be no disappearing - // frame. - set.addAnimation(new ClipRectAnimation(mTmpFromClipRect, mTmpToClipRect)); - } else { - // The disappearing window has one larger dimension. We need to apply scaling, so the - // first frame of the entry animation matches the old window. - set.addAnimation(new ScaleAnimation(fromWidth / toWidth, 1, fromHeight / toHeight, 1)); - // We might not be going exactly full screen, but instead be aligned under the status - // bar using cropping. We still need to account for the cropped part, which will also - // be scaled. - translateAdjustment = (int) (contentInsets.top * fromHeight / toHeight); - } - - // We animate the translation from the old position of the removed window, to the new - // position of the added window. The latter might not be full screen, for example docked for - // docked windows. - TranslateAnimation translate = new TranslateAnimation(left - containingFrame.left, - 0, top - containingFrame.top - translateAdjustment, 0); - set.addAnimation(translate); - set.setDuration(DEFAULT_APP_TRANSITION_DURATION); - set.setZAdjustment(Animation.ZORDER_TOP); - return set; - } - /** * @return true if and only if the first frame of the transition can be skipped, i.e. the first * frame of the transition doesn't change the visuals on screen, so we can start @@ -1581,6 +965,7 @@ public class AppTransition implements Dump { * to the recents thumbnail and hence need to account for the surface being * bigger. */ + @Nullable Animation loadAnimation(LayoutParams lp, int transit, boolean enter, int uiMode, int orientation, Rect frame, Rect displayFrame, Rect insets, @Nullable Rect surfaceInsets, @Nullable Rect stableInsets, boolean isVoiceInteraction, @@ -1592,57 +977,61 @@ public class AppTransition implements Dump { Animation a; if (isKeyguardGoingAwayTransitOld(transit) && enter) { - a = loadKeyguardExitAnimation(transit); + a = mTransitionAnimation.loadKeyguardExitAnimation(transit, mNextAppTransitionFlags); } else if (transit == TRANSIT_OLD_KEYGUARD_OCCLUDE) { a = null; } else if (transit == TRANSIT_OLD_KEYGUARD_UNOCCLUDE && !enter) { - a = loadAnimationRes(lp, com.android.internal.R.anim.wallpaper_open_exit); + a = mTransitionAnimation.loadKeyguardUnoccludeAnimation(lp); } else if (transit == TRANSIT_OLD_CRASHING_ACTIVITY_CLOSE) { a = null; } else if (isVoiceInteraction && (transit == TRANSIT_OLD_ACTIVITY_OPEN || transit == TRANSIT_OLD_TASK_OPEN || transit == TRANSIT_OLD_TASK_TO_FRONT)) { - a = loadAnimationRes(lp, enter - ? com.android.internal.R.anim.voice_activity_open_enter - : com.android.internal.R.anim.voice_activity_open_exit); + a = mTransitionAnimation.loadVoiceActivityOpenAnimation(lp, enter); ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM, "applyAnimation voice: anim=%s transit=%s isEntrance=%b Callers=%s", a, appTransitionOldToString(transit), enter, Debug.getCallers(3)); } else if (isVoiceInteraction && (transit == TRANSIT_OLD_ACTIVITY_CLOSE || transit == TRANSIT_OLD_TASK_CLOSE || transit == TRANSIT_OLD_TASK_TO_BACK)) { - a = loadAnimationRes(lp, enter - ? com.android.internal.R.anim.voice_activity_close_enter - : com.android.internal.R.anim.voice_activity_close_exit); + a = mTransitionAnimation.loadVoiceActivityExitAnimation(lp, enter); ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM, "applyAnimation voice: anim=%s transit=%s isEntrance=%b Callers=%s", a, appTransitionOldToString(transit), enter, Debug.getCallers(3)); } else if (transit == TRANSIT_OLD_ACTIVITY_RELAUNCH) { - a = createRelaunchAnimation(frame, insets); + a = mTransitionAnimation.createRelaunchAnimation(frame, insets, + mDefaultNextAppTransitionAnimationSpec != null + ? mDefaultNextAppTransitionAnimationSpec.rect : null); ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM, "applyAnimation: anim=%s transit=%s Callers=%s", a, appTransitionOldToString(transit), Debug.getCallers(3)); } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_CUSTOM) { - a = loadAnimationRes(mNextAppTransitionPackage, enter ? - mNextAppTransitionEnter : mNextAppTransitionExit); + a = mTransitionAnimation.loadAppTransitionAnimation(mNextAppTransitionPackage, + enter ? mNextAppTransitionEnter : mNextAppTransitionExit); ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM, "applyAnimation: anim=%s nextAppTransition=ANIM_CUSTOM transit=%s " + "isEntrance=%b Callers=%s", a, appTransitionOldToString(transit), enter, Debug.getCallers(3)); } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_CUSTOM_IN_PLACE) { - a = loadAnimationRes(mNextAppTransitionPackage, mNextAppTransitionInPlace); + a = mTransitionAnimation.loadAppTransitionAnimation( + mNextAppTransitionPackage, mNextAppTransitionInPlace); ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM, "applyAnimation: anim=%s nextAppTransition=ANIM_CUSTOM_IN_PLACE " + "transit=%s Callers=%s", a, appTransitionOldToString(transit), Debug.getCallers(3)); } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_CLIP_REVEAL) { - a = createClipRevealAnimationLocked(transit, enter, frame, displayFrame); + a = mTransitionAnimation.createClipRevealAnimationLocked( + transit, enter, frame, displayFrame, + mDefaultNextAppTransitionAnimationSpec != null + ? mDefaultNextAppTransitionAnimationSpec.rect : null); ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM, "applyAnimation: anim=%s nextAppTransition=ANIM_CLIP_REVEAL " + "transit=%s Callers=%s", a, appTransitionOldToString(transit), Debug.getCallers(3)); } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_SCALE_UP) { - a = createScaleUpAnimationLocked(transit, enter, frame); + a = mTransitionAnimation.createScaleUpAnimationLocked(transit, enter, frame, + mDefaultNextAppTransitionAnimationSpec != null + ? mDefaultNextAppTransitionAnimationSpec.rect : null); ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM, "applyAnimation: anim=%s nextAppTransition=ANIM_SCALE_UP transit=%s " + "isEntrance=%s Callers=%s", @@ -1651,8 +1040,11 @@ public class AppTransition implements Dump { mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN) { mNextAppTransitionScaleUp = (mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP); - a = createThumbnailEnterExitAnimationLocked(getThumbnailTransitionState(enter), - frame, transit, container); + final HardwareBuffer thumbnailHeader = getAppTransitionThumbnailHeader(container); + a = mTransitionAnimation.createThumbnailEnterExitAnimationLocked( + getThumbnailTransitionState(enter), frame, transit, thumbnailHeader, + mDefaultNextAppTransitionAnimationSpec != null + ? mDefaultNextAppTransitionAnimationSpec.rect : null); ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM, "applyAnimation: anim=%s nextAppTransition=%s transit=%s isEntrance=%b " + "Callers=%s", @@ -1663,9 +1055,13 @@ public class AppTransition implements Dump { mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN) { mNextAppTransitionScaleUp = (mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP); - a = createAspectScaledThumbnailEnterExitAnimationLocked( - getThumbnailTransitionState(enter), uiMode, orientation, transit, frame, - insets, surfaceInsets, stableInsets, freeform, container); + AppTransitionAnimationSpec spec = mNextAppTransitionAnimationsSpecs.get( + container.hashCode()); + a = mTransitionAnimation.createAspectScaledThumbnailEnterExitAnimationLocked( + getThumbnailTransitionState(enter), orientation, transit, frame, + insets, surfaceInsets, stableInsets, freeform, spec != null ? spec.rect : null, + mDefaultNextAppTransitionAnimationSpec != null + ? mDefaultNextAppTransitionAnimationSpec.rect : null); ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM, "applyAnimation: anim=%s nextAppTransition=%s transit=%s isEntrance=%b " + "Callers=%s", @@ -1674,8 +1070,7 @@ public class AppTransition implements Dump { : "ANIM_THUMBNAIL_ASPECT_SCALE_DOWN", appTransitionOldToString(transit), enter, Debug.getCallers(3)); } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_OPEN_CROSS_PROFILE_APPS && enter) { - a = loadAnimationRes("android", - com.android.internal.R.anim.task_open_enter_cross_profile_apps); + a = mTransitionAnimation.loadCrossProfileAppEnterAnimation(); ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM, "applyAnimation NEXT_TRANSIT_TYPE_OPEN_CROSS_PROFILE_APPS: " + "anim=%s transit=%s isEntrance=true Callers=%s", @@ -1758,18 +1153,6 @@ public class AppTransition implements Dump { return a; } - private Animation loadKeyguardExitAnimation(int transit) { - if ((mNextAppTransitionFlags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION) != 0) { - return null; - } - final boolean toShade = - (mNextAppTransitionFlags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE) != 0; - final boolean subtle = - (mNextAppTransitionFlags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_SUBTLE_ANIMATION) != 0; - return mService.mPolicy.createHiddenByKeyguardExit( - transit == TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER, toShade, subtle); - } - int getAppRootTaskClipMode() { return mNextAppTransitionRequests.contains(TRANSIT_RELAUNCH) || mNextAppTransitionRequests.contains(TRANSIT_KEYGUARD_GOING_AWAY) diff --git a/services/core/java/com/android/server/wm/BackgroundActivityStartCallback.java b/services/core/java/com/android/server/wm/BackgroundActivityStartCallback.java index 200f207fe50a..eec648dae24a 100644 --- a/services/core/java/com/android/server/wm/BackgroundActivityStartCallback.java +++ b/services/core/java/com/android/server/wm/BackgroundActivityStartCallback.java @@ -31,7 +31,8 @@ public interface BackgroundActivityStartCallback { * Note that if the start was allowed due to a mechanism other than tokens (eg. permission), * this won't be called. * - * This will be called holding the WM lock, don't do anything costly here. + * This will be called holding the WM and local lock, don't do anything costly or invoke AM/WM + * methods here directly. */ boolean isActivityStartAllowed(Collection<IBinder> tokens, int uid, String packageName); @@ -40,7 +41,8 @@ public interface BackgroundActivityStartCallback { * #ACTION_CLOSE_SYSTEM_DIALOGS}, presumably to start activities, based on the originating * tokens {@code tokens} currently associated with potential activity starts. * - * This will be called holding the AM and WM lock, don't do anything costly here. + * This will be called holding the AM and local lock, don't do anything costly or invoke AM/WM + * methods here directly. */ boolean canCloseSystemDialogs(Collection<IBinder> tokens, int uid); } diff --git a/services/core/java/com/android/server/wm/BackgroundLaunchProcessController.java b/services/core/java/com/android/server/wm/BackgroundLaunchProcessController.java new file mode 100644 index 000000000000..ab1ed67d4cf9 --- /dev/null +++ b/services/core/java/com/android/server/wm/BackgroundLaunchProcessController.java @@ -0,0 +1,264 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.wm; + +import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ACTIVITY_STARTS; +import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM; +import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME; +import static com.android.server.wm.ActivityTaskManagerService.ACTIVITY_BG_START_GRACE_PERIOD_MS; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.os.Binder; +import android.os.IBinder; +import android.os.SystemClock; +import android.util.ArrayMap; +import android.util.ArraySet; +import android.util.IntArray; +import android.util.Slog; + +import com.android.internal.annotations.GuardedBy; + +import java.io.PrintWriter; +import java.util.Arrays; +import java.util.function.IntPredicate; + +/** + * A per-process controller to decide whether the process can start activity or foreground service + * (especially from background). All methods of this class must be thread safe. The caller does not + * need to hold WM lock, e.g. lock contention of WM lock shouldn't happen when starting service. + */ +class BackgroundLaunchProcessController { + private static final String TAG = + TAG_WITH_CLASS_NAME ? "BackgroundLaunchProcessController" : TAG_ATM; + + /** It is {@link ActivityTaskManagerService#hasActiveVisibleWindow(int)}. */ + private final IntPredicate mUidHasActiveVisibleWindowPredicate; + + private final @Nullable BackgroundActivityStartCallback mBackgroundActivityStartCallback; + + /** + * A set of tokens that currently contribute to this process being temporarily allowed + * to start activities even if it's not in the foreground. The values of this map are optional + * (can be null) and are used to trace back the grant to the notification token mechanism. + */ + @GuardedBy("this") + private @Nullable ArrayMap<Binder, IBinder> mBackgroundActivityStartTokens; + + /** Set of UIDs of clients currently bound to this process. */ + @GuardedBy("this") + private @Nullable IntArray mBoundClientUids; + + BackgroundLaunchProcessController(@NonNull IntPredicate uidHasActiveVisibleWindowPredicate, + @Nullable BackgroundActivityStartCallback callback) { + mUidHasActiveVisibleWindowPredicate = uidHasActiveVisibleWindowPredicate; + mBackgroundActivityStartCallback = callback; + } + + boolean areBackgroundActivityStartsAllowed(int pid, int uid, String packageName, + boolean appSwitchAllowed, boolean isCheckingForFgsStart, boolean hasVisibleActivities, + boolean hasBackgroundActivityStartPrivileges, long lastStopAppSwitchesTime, + long lastActivityLaunchTime, long lastActivityFinishTime) { + // If app switching is not allowed, we ignore all the start activity grace period + // exception so apps cannot start itself in onPause() after pressing home button. + if (appSwitchAllowed) { + // Allow if any activity in the caller has either started or finished very recently, and + // it must be started or finished after last stop app switches time. + final long now = SystemClock.uptimeMillis(); + if (now - lastActivityLaunchTime < ACTIVITY_BG_START_GRACE_PERIOD_MS + || now - lastActivityFinishTime < ACTIVITY_BG_START_GRACE_PERIOD_MS) { + // If activity is started and finished before stop app switch time, we should not + // let app to be able to start background activity even it's in grace period. + if (lastActivityLaunchTime > lastStopAppSwitchesTime + || lastActivityFinishTime > lastStopAppSwitchesTime) { + if (DEBUG_ACTIVITY_STARTS) { + Slog.d(TAG, "[Process(" + pid + + ")] Activity start allowed: within " + + ACTIVITY_BG_START_GRACE_PERIOD_MS + "ms grace period"); + } + return true; + } + if (DEBUG_ACTIVITY_STARTS) { + Slog.d(TAG, "[Process(" + pid + ")] Activity start within " + + ACTIVITY_BG_START_GRACE_PERIOD_MS + + "ms grace period but also within stop app switch window"); + } + + } + } + // Allow if the proc is instrumenting with background activity starts privs. + if (hasBackgroundActivityStartPrivileges) { + if (DEBUG_ACTIVITY_STARTS) { + Slog.d(TAG, "[Process(" + pid + + ")] Activity start allowed: process instrumenting with background " + + "activity starts privileges"); + } + return true; + } + // Allow if the caller has an activity in any foreground task. + if (appSwitchAllowed && hasVisibleActivities) { + if (DEBUG_ACTIVITY_STARTS) { + Slog.d(TAG, "[Process(" + pid + + ")] Activity start allowed: process has activity in foreground task"); + } + return true; + } + // Allow if the caller is bound by a UID that's currently foreground. + if (isBoundByForegroundUid()) { + if (DEBUG_ACTIVITY_STARTS) { + Slog.d(TAG, "[Process(" + pid + + ")] Activity start allowed: process bound by foreground uid"); + } + return true; + } + // Allow if the flag was explicitly set. + if (isBackgroundStartAllowedByToken(uid, packageName, isCheckingForFgsStart)) { + if (DEBUG_ACTIVITY_STARTS) { + Slog.d(TAG, "[Process(" + pid + + ")] Activity start allowed: process allowed by token"); + } + return true; + } + return false; + } + + /** + * If there are no tokens, we don't allow *by token*. If there are tokens and + * isCheckingForFgsStart is false, we ask the callback if the start is allowed for these tokens, + * otherwise if there is no callback we allow. + */ + private boolean isBackgroundStartAllowedByToken(int uid, String packageName, + boolean isCheckingForFgsStart) { + synchronized (this) { + if (mBackgroundActivityStartTokens == null + || mBackgroundActivityStartTokens.isEmpty()) { + return false; + } + if (isCheckingForFgsStart) { + // BG-FGS-start only checks if there is a token. + return true; + } + + if (mBackgroundActivityStartCallback == null) { + // We have tokens but no callback to decide => allow. + return true; + } + // The callback will decide. + return mBackgroundActivityStartCallback.isActivityStartAllowed( + mBackgroundActivityStartTokens.values(), uid, packageName); + } + } + + private boolean isBoundByForegroundUid() { + synchronized (this) { + if (mBoundClientUids != null) { + for (int i = mBoundClientUids.size() - 1; i >= 0; i--) { + if (mUidHasActiveVisibleWindowPredicate.test(mBoundClientUids.get(i))) { + return true; + } + } + } + } + return false; + } + + void setBoundClientUids(ArraySet<Integer> boundClientUids) { + synchronized (this) { + if (boundClientUids == null || boundClientUids.isEmpty()) { + mBoundClientUids = null; + return; + } + if (mBoundClientUids == null) { + mBoundClientUids = new IntArray(); + } else { + mBoundClientUids.clear(); + } + for (int i = boundClientUids.size() - 1; i >= 0; i--) { + mBoundClientUids.add(boundClientUids.valueAt(i)); + } + } + } + + /** + * Allows background activity starts using token {@code entity}. Optionally, you can provide + * {@code originatingToken} if you have one such originating token, this is useful for tracing + * back the grant in the case of the notification token. + * + * If {@code entity} is already added, this method will update its {@code originatingToken}. + */ + void addOrUpdateAllowBackgroundActivityStartsToken(Binder entity, + @Nullable IBinder originatingToken) { + synchronized (this) { + if (mBackgroundActivityStartTokens == null) { + mBackgroundActivityStartTokens = new ArrayMap<>(); + } + mBackgroundActivityStartTokens.put(entity, originatingToken); + } + } + + /** + * Removes token {@code entity} that allowed background activity starts added via {@link + * #addOrUpdateAllowBackgroundActivityStartsToken(Binder, IBinder)}. + */ + void removeAllowBackgroundActivityStartsToken(Binder entity) { + synchronized (this) { + if (mBackgroundActivityStartTokens != null) { + mBackgroundActivityStartTokens.remove(entity); + } + } + } + + /** + * Returns whether this process is allowed to close system dialogs via a background activity + * start token that allows the close system dialogs operation (eg. notification). + */ + boolean canCloseSystemDialogsByToken(int uid) { + if (mBackgroundActivityStartCallback == null) { + return false; + } + synchronized (this) { + if (mBackgroundActivityStartTokens == null + || mBackgroundActivityStartTokens.isEmpty()) { + return false; + } + return mBackgroundActivityStartCallback.canCloseSystemDialogs( + mBackgroundActivityStartTokens.values(), uid); + } + } + + void dump(PrintWriter pw, String prefix) { + synchronized (this) { + if (mBackgroundActivityStartTokens != null + && !mBackgroundActivityStartTokens.isEmpty()) { + pw.print(prefix); + pw.println("Background activity start tokens (token: originating token):"); + for (int i = mBackgroundActivityStartTokens.size() - 1; i >= 0; i--) { + pw.print(prefix); + pw.print(" - "); + pw.print(mBackgroundActivityStartTokens.keyAt(i)); + pw.print(": "); + pw.println(mBackgroundActivityStartTokens.valueAt(i)); + } + } + if (mBoundClientUids != null && mBoundClientUids.size() > 0) { + pw.print(prefix); + pw.print("BoundClientUids:"); + pw.println(Arrays.toString(mBoundClientUids.toArray())); + } + } + } +} diff --git a/services/core/java/com/android/server/wm/BarController.java b/services/core/java/com/android/server/wm/BarController.java deleted file mode 100644 index eee27c72e583..000000000000 --- a/services/core/java/com/android/server/wm/BarController.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.wm; - -import android.annotation.NonNull; -import android.graphics.Rect; - -/** - * Controls state/behavior specific to a system bar window. - */ -public class BarController { - private final int mWindowType; - - private final Rect mContentFrame = new Rect(); - - BarController(int windowType) { - mWindowType = windowType; - } - - /** - * Sets the frame within which the bar will display its content. - * - * This is used to determine if letterboxes interfere with the display of such content. - */ - void setContentFrame(Rect frame) { - mContentFrame.set(frame); - } - - private Rect getContentFrame(@NonNull WindowState win) { - final Rect rotatedContentFrame = win.mToken.getFixedRotationBarContentFrame(mWindowType); - return rotatedContentFrame != null ? rotatedContentFrame : mContentFrame; - } - - boolean isLightAppearanceAllowed(WindowState win) { - if (win == null) { - return true; - } - return !win.isLetterboxedOverlappingWith(getContentFrame(win)); - } - - boolean isTransparentAllowed(WindowState win) { - if (win == null) { - return true; - } - return win.isTransparentBarAllowed(getContentFrame(win)); - } -} diff --git a/services/core/java/com/android/server/wm/DisplayArea.java b/services/core/java/com/android/server/wm/DisplayArea.java index 15483cb90ce2..f075d850c20f 100644 --- a/services/core/java/com/android/server/wm/DisplayArea.java +++ b/services/core/java/com/android/server/wm/DisplayArea.java @@ -462,6 +462,23 @@ public class DisplayArea<T extends WindowContainer> extends WindowContainer<T> { } @Override + void resolveOverrideConfiguration(Configuration newParentConfiguration) { + super.resolveOverrideConfiguration(newParentConfiguration); + final Configuration resolvedConfig = getResolvedOverrideConfiguration(); + final Rect overrideBounds = resolvedConfig.windowConfiguration.getBounds(); + final Rect overrideAppBounds = resolvedConfig.windowConfiguration.getAppBounds(); + final Rect parentAppBounds = newParentConfiguration.windowConfiguration.getAppBounds(); + + // If there is no override of appBounds, restrict appBounds to the override bounds. + if (!overrideBounds.isEmpty() && (overrideAppBounds == null || overrideAppBounds.isEmpty()) + && parentAppBounds != null && !parentAppBounds.isEmpty()) { + final Rect appBounds = new Rect(overrideBounds); + appBounds.intersect(parentAppBounds); + resolvedConfig.windowConfiguration.setAppBounds(appBounds); + } + } + + @Override boolean isOrganized() { return mOrganizer != null; } diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index ece101d2e605..d5d06f9a0033 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -670,8 +670,9 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp // Used in updating override configurations private final Configuration mTempConfig = new Configuration(); - // Used in performing layout - private boolean mTmpWindowsBehindIme; + // Used in performing layout, to record the insets provided by other windows above the current + // window. + private InsetsState mTmpAboveInsetsState = new InsetsState(); /** * Used to prevent recursions when calling @@ -770,17 +771,11 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp + " parentHidden=" + w.isParentWindowHidden()); } - // Sets mBehindIme for each window. Windows behind IME can get IME insets. - if (w.mBehindIme != mTmpWindowsBehindIme) { - w.mBehindIme = mTmpWindowsBehindIme; - if (getInsetsStateController().getRawInsetsState().getSourceOrDefaultVisibility( - ITYPE_IME)) { - // If IME is invisible, behind IME or not doesn't make the insets different. - mWinInsetsChanged.add(w); - } - } - if (w == mInputMethodWindow) { - mTmpWindowsBehindIme = true; + // Sets mAboveInsets for each window. Windows behind the window providing the insets can + // receive the insets. + if (!w.mAboveInsetsState.equals(mTmpAboveInsetsState)) { + w.mAboveInsetsState.set(mTmpAboveInsetsState); + mWinInsetsChanged.add(w); } // If this view is GONE, then skip it -- keep the current frame, and let the caller know @@ -816,8 +811,16 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp + " mContainingFrame=" + w.getContainingFrame() + " mDisplayFrame=" + w.getDisplayFrame()); } + provideInsetsByWindow(w); }; + private void provideInsetsByWindow(WindowState w) { + for (int i = 0; i < w.mProvidedInsetsSources.size(); i++) { + final InsetsSource providedSource = w.mProvidedInsetsSources.valueAt(i); + mTmpAboveInsetsState.addSource(providedSource); + } + } + private final Consumer<WindowState> mPerformLayoutAttached = w -> { if (w.mLayoutAttached) { if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + w + " mHaveFrame=" + w.mHaveFrame @@ -4283,14 +4286,20 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp + " dh=" + mDisplayInfo.logicalHeight); } + // Used to indicate that we have processed the insets windows. This needs to be after + // beginLayoutLw to ensure the raw insets state display related info is initialized. + final InsetsState rawInsetsState = getInsetsStateController().getRawInsetsState(); + mTmpAboveInsetsState = new InsetsState(); + mTmpAboveInsetsState.setDisplayFrame(rawInsetsState.getDisplayFrame()); + mTmpAboveInsetsState.setDisplayCutout(rawInsetsState.getDisplayCutout()); + mTmpAboveInsetsState.mirrorAlwaysVisibleInsetsSources(rawInsetsState); + int seq = mLayoutSeq + 1; if (seq < 0) seq = 0; mLayoutSeq = seq; mTmpInitial = initial; - // Used to indicate that we have processed the IME window. - mTmpWindowsBehindIme = false; // First perform layout of any root windows (not attached to another window). forAllWindows(mPerformLayout, true /* traverseTopToBottom */); @@ -5485,14 +5494,19 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp /** Checks whether the given activity is in size compatibility mode and notifies the change. */ void handleActivitySizeCompatModeIfNeeded(ActivityRecord r) { - if (!r.isState(RESUMED) || r.getWindowingMode() != WINDOWING_MODE_FULLSCREEN) { + final Task organizedTask = r.getOrganizedTask(); + if (!r.isState(RESUMED) || r.getWindowingMode() != WINDOWING_MODE_FULLSCREEN + || organizedTask == null) { // The callback is only interested in the foreground changes of fullscreen activity. return; } if (!r.inSizeCompatMode()) { if (mLastCompatModeActivity != null) { + // TODO(b/178327644) Remove notifySizeCompatModeActivityChanged mAtmService.getTaskChangeNotificationController() .notifySizeCompatModeActivityChanged(mDisplayId, null /* activityToken */); + // This will do nothing until SizeCompatModeActivityController is moved to shell + organizedTask.onSizeCompatActivityChanged(); } mLastCompatModeActivity = null; return; @@ -5501,8 +5515,11 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp return; } mLastCompatModeActivity = r; + // TODO(b/178327644) Remove notifySizeCompatModeActivityChanged mAtmService.getTaskChangeNotificationController() .notifySizeCompatModeActivityChanged(mDisplayId, r.appToken); + // This will do nothing until SizeCompatModeActivityController is moved to shell + organizedTask.onSizeCompatActivityChanged(); } boolean isUidPresent(int uid) { diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java index a7db9d624b7e..ed97848aece7 100644 --- a/services/core/java/com/android/server/wm/DisplayPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayPolicy.java @@ -42,6 +42,8 @@ import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS; import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS; import static android.view.WindowInsetsController.APPEARANCE_OPAQUE_NAVIGATION_BARS; import static android.view.WindowInsetsController.APPEARANCE_OPAQUE_STATUS_BARS; +import static android.view.WindowInsetsController.APPEARANCE_SEMI_TRANSPARENT_NAVIGATION_BARS; +import static android.view.WindowInsetsController.APPEARANCE_SEMI_TRANSPARENT_STATUS_BARS; import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW; import static android.view.WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW; import static android.view.WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON; @@ -84,6 +86,7 @@ import static android.view.WindowManagerPolicyConstants.ALT_BAR_TOP; import static android.view.WindowManagerPolicyConstants.ALT_BAR_UNKNOWN; import static android.view.WindowManagerPolicyConstants.EXTRA_HDMI_PLUGGED_STATE; import static android.view.WindowManagerPolicyConstants.NAV_BAR_BOTTOM; +import static android.view.WindowManagerPolicyConstants.NAV_BAR_INVALID; import static android.view.WindowManagerPolicyConstants.NAV_BAR_LEFT; import static android.view.WindowManagerPolicyConstants.NAV_BAR_RIGHT; @@ -303,8 +306,7 @@ public class DisplayPolicy { private boolean mLastImmersiveMode; - private final BarController mStatusBarController; - private final BarController mNavigationBarController; + private final SparseArray<Rect> mBarContentFrames = new SparseArray<>(); // The windows we were told about in focusChanged. private WindowState mFocusedWindow; @@ -430,8 +432,8 @@ public class DisplayPolicy { final int displayId = displayContent.getDisplayId(); - mStatusBarController = new BarController(TYPE_STATUS_BAR); - mNavigationBarController = new BarController(TYPE_NAVIGATION_BAR); + mBarContentFrames.put(TYPE_STATUS_BAR, new Rect()); + mBarContentFrames.put(TYPE_NAVIGATION_BAR, new Rect()); final Resources r = mContext.getResources(); mCarDockEnablesAccelerometer = r.getBoolean(R.bool.config_carDockEnablesAccelerometer); @@ -1251,11 +1253,6 @@ public class DisplayPolicy { displayFrames.mDisplayCutoutSafe.top); } - @VisibleForTesting - BarController getStatusBarController() { - return mStatusBarController; - } - WindowState getStatusBar() { return mStatusBar != null ? mStatusBar : mStatusBarAlt; } @@ -1471,7 +1468,7 @@ public class DisplayPolicy { mSystemGestures.screenHeight = info.logicalHeight; } - private void layoutStatusBar(DisplayFrames displayFrames, Rect simulatedContentFrame) { + private void layoutStatusBar(DisplayFrames displayFrames, Rect contentFrame) { // decide where the status bar goes ahead of time if (mStatusBar == null) { return; @@ -1498,21 +1495,16 @@ public class DisplayPolicy { statusBarBottom); } - // Tell the bar controller where the collapsed status bar content is. sTmpRect.set(windowFrames.mFrame); sTmpRect.intersect(displayFrames.mDisplayCutoutSafe); sTmpRect.top = windowFrames.mFrame.top; // Ignore top display cutout inset sTmpRect.bottom = statusBarBottom; // Use collapsed status bar size - if (simulatedContentFrame != null) { - simulatedContentFrame.set(sTmpRect); - } else { - mStatusBarController.setContentFrame(sTmpRect); - } + contentFrame.set(sTmpRect); } - private void layoutNavigationBar(DisplayFrames displayFrames, Rect simulatedContentFrame) { + private int layoutNavigationBar(DisplayFrames displayFrames, Rect contentFrame) { if (mNavigationBar == null) { - return; + return NAV_BAR_INVALID; } final int uiMode = mDisplayContent.getConfiguration().uiMode; @@ -1550,17 +1542,12 @@ public class DisplayPolicy { windowFrames.setFrames(navigationFrame /* parentFrame */, navigationFrame /* displayFrame */); mNavigationBar.computeFrameAndUpdateSourceFrame(); - final Rect contentFrame = sTmpRect; - contentFrame.set(windowFrames.mFrame); - contentFrame.intersect(displayFrames.mDisplayCutoutSafe); - if (simulatedContentFrame != null) { - simulatedContentFrame.set(contentFrame); - } else { - mNavigationBarPosition = navBarPosition; - mNavigationBarController.setContentFrame(contentFrame); - } + sTmpRect.set(windowFrames.mFrame); + sTmpRect.intersect(displayFrames.mDisplayCutoutSafe); + contentFrame.set(sTmpRect); if (DEBUG_LAYOUT) Slog.i(TAG, "mNavigationBar frame: " + navigationFrame); + return navBarPosition; } private boolean canReceiveInput(WindowState win) { @@ -1607,11 +1594,12 @@ public class DisplayPolicy { */ public void layoutWindowLw(WindowState win, WindowState attached, DisplayFrames displayFrames) { if (win == mNavigationBar) { - layoutNavigationBar(displayFrames, null /* simulatedContentFrame */); + mNavigationBarPosition = layoutNavigationBar(displayFrames, + mBarContentFrames.get(TYPE_NAVIGATION_BAR)); return; } if ((win == mStatusBar && !canReceiveInput(win))) { - layoutStatusBar(displayFrames, null /* simulatedContentFrame */); + layoutStatusBar(displayFrames, mBarContentFrames.get(TYPE_STATUS_BAR)); return; } final WindowManager.LayoutParams attrs = win.getAttrs(); @@ -2620,7 +2608,7 @@ public class DisplayPolicy { // Otherwise if it's dimming, clear the light flag. appearance &= ~APPEARANCE_LIGHT_STATUS_BARS; } - if (!mStatusBarController.isLightAppearanceAllowed(statusColorWin)) { + if (!isLightBarAllowed(statusColorWin, TYPE_STATUS_BAR)) { appearance &= ~APPEARANCE_LIGHT_STATUS_BARS; } } @@ -2683,7 +2671,7 @@ public class DisplayPolicy { // Clear the light flag for dimming window. appearance &= ~APPEARANCE_LIGHT_NAVIGATION_BARS; } - if (!mNavigationBarController.isLightAppearanceAllowed(navColorWin)) { + if (!isLightBarAllowed(navColorWin, TYPE_NAVIGATION_BAR)) { appearance &= ~APPEARANCE_LIGHT_NAVIGATION_BARS; } } @@ -2693,34 +2681,17 @@ public class DisplayPolicy { private int updateSystemBarsLw(WindowState win, int disableFlags) { final boolean dockedRootTaskVisible = mDisplayContent.getDefaultTaskDisplayArea() .isRootTaskVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY); - final boolean freeformRootTaskVisible = mDisplayContent.getDefaultTaskDisplayArea() - .isRootTaskVisible(WINDOWING_MODE_FREEFORM); final boolean resizing = mDisplayContent.getDockedDividerController().isResizing(); // We need to force system bars when the docked root task is visible, when the freeform // root task is focused but also when we are resizing for the transitions when docked // root task visibility changes. mForceShowSystemBars = dockedRootTaskVisible || win.inFreeformWindowingMode() || resizing; - final boolean forceOpaqueStatusBar = mForceShowSystemBars && !isKeyguardShowing(); - - final boolean fullscreenDrawsStatusBarBackground = - drawsStatusBarBackground(mTopFullscreenOpaqueWindowState); - final boolean dockedDrawsStatusBarBackground = - drawsStatusBarBackground(mTopDockedOpaqueWindowState); - final boolean fullscreenDrawsNavBarBackground = - drawsNavigationBarBackground(mTopFullscreenOpaqueWindowState); - final boolean dockedDrawsNavigationBarBackground = - drawsNavigationBarBackground(mTopDockedOpaqueWindowState); int appearance = APPEARANCE_OPAQUE_NAVIGATION_BARS | APPEARANCE_OPAQUE_STATUS_BARS; - if (fullscreenDrawsStatusBarBackground && dockedDrawsStatusBarBackground) { - appearance &= ~APPEARANCE_OPAQUE_STATUS_BARS; - } - - appearance = configureNavBarOpacity(appearance, dockedRootTaskVisible, - freeformRootTaskVisible, resizing, fullscreenDrawsNavBarBackground, - dockedDrawsNavigationBarBackground); + appearance = configureStatusBarOpacity(appearance); + appearance = configureNavBarOpacity(appearance, dockedRootTaskVisible, resizing); final boolean requestHideNavBar = !win.getRequestedVisibility(ITYPE_NAVIGATION_BAR); final long now = SystemClock.uptimeMillis(); @@ -2754,10 +2725,36 @@ public class DisplayPolicy { return appearance; } - private boolean drawsBarBackground(WindowState win, BarController controller) { - if (!controller.isTransparentAllowed(win)) { - return false; + private boolean isLightBarAllowed(WindowState win, int windowType) { + if (win == null) { + return true; + } + return !win.isLetterboxedOverlappingWith(getBarContentFrameForWindow(win, windowType)); + } + + private Rect getBarContentFrameForWindow(WindowState win, int windowType) { + final Rect rotatedBarFrame = win.mToken.getFixedRotationBarContentFrame(windowType); + return rotatedBarFrame != null ? rotatedBarFrame : mBarContentFrames.get(windowType); + } + + /** + * @return {@code true} if bar is allowed to be fully transparent when given window is show. + * + * <p>Prevents showing a transparent bar over a letterboxed activity which can make + * notification icons or navigation buttons unreadable due to contrast between letterbox + * background and an activity. For instance, this happens when letterbox background is solid + * black while activity is white. To resolve this, only semi-transparent bars are allowed to + * be drawn over letterboxed activity. + */ + @VisibleForTesting + boolean isFullyTransparentAllowed(WindowState win, int windowType) { + if (win == null) { + return true; } + return win.isFullyTransparentBarAllowed(getBarContentFrameForWindow(win, windowType)); + } + + private boolean drawsBarBackground(WindowState win) { if (win == null) { return true; } @@ -2770,12 +2767,23 @@ public class DisplayPolicy { return forceDrawsSystemBars || drawsSystemBars; } - private boolean drawsStatusBarBackground(WindowState win) { - return drawsBarBackground(win, mStatusBarController); - } + /** @return the current visibility flags with the status bar opacity related flags toggled. */ + private int configureStatusBarOpacity(int appearance) { + final boolean fullscreenDrawsBackground = + drawsBarBackground(mTopFullscreenOpaqueWindowState); + final boolean dockedDrawsBackground = + drawsBarBackground(mTopDockedOpaqueWindowState); - private boolean drawsNavigationBarBackground(WindowState win) { - return drawsBarBackground(win, mNavigationBarController); + if (fullscreenDrawsBackground && dockedDrawsBackground) { + appearance &= ~APPEARANCE_OPAQUE_STATUS_BARS; + } + + if (!isFullyTransparentAllowed(mTopFullscreenOpaqueWindowState, TYPE_STATUS_BAR) + || !isFullyTransparentAllowed(mTopDockedOpaqueWindowState, TYPE_STATUS_BAR)) { + appearance |= APPEARANCE_SEMI_TRANSPARENT_STATUS_BARS; + } + + return appearance; } /** @@ -2783,10 +2791,16 @@ public class DisplayPolicy { * on the nav bar opacity rules chosen by {@link #mNavBarOpacityMode}. */ private int configureNavBarOpacity(int appearance, boolean dockedRootTaskVisible, - boolean freeformRootTaskVisible, boolean isDockedDividerResizing, - boolean fullscreenDrawsBackground, boolean dockedDrawsNavigationBarBackground) { + boolean isDockedDividerResizing) { + final boolean freeformRootTaskVisible = mDisplayContent.getDefaultTaskDisplayArea() + .isRootTaskVisible(WINDOWING_MODE_FREEFORM); + final boolean fullscreenDrawsBackground = + drawsBarBackground(mTopFullscreenOpaqueWindowState); + final boolean dockedDrawsBackground = + drawsBarBackground(mTopDockedOpaqueWindowState); + if (mNavBarOpacityMode == NAV_BAR_FORCE_TRANSPARENT) { - if (fullscreenDrawsBackground && dockedDrawsNavigationBarBackground) { + if (fullscreenDrawsBackground && dockedDrawsBackground) { appearance = clearNavBarOpaqueFlag(appearance); } else if (dockedRootTaskVisible) { appearance = setNavBarOpaqueFlag(appearance); @@ -2811,6 +2825,11 @@ public class DisplayPolicy { } } + if (!isFullyTransparentAllowed(mTopFullscreenOpaqueWindowState, TYPE_NAVIGATION_BAR) + || !isFullyTransparentAllowed(mTopDockedOpaqueWindowState, TYPE_NAVIGATION_BAR)) { + appearance |= APPEARANCE_SEMI_TRANSPARENT_NAVIGATION_BARS; + } + return appearance; } diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java index 1692df6d82cd..c6c7fe083b16 100644 --- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java +++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java @@ -151,6 +151,7 @@ class InsetsSourceProvider { // animate-out as new one animates-in. mWin.cancelAnimation(); mWin.mPendingPositionChanged = null; + mWin.mProvidedInsetsSources.remove(mSource.getType()); } ProtoLog.d(WM_DEBUG_IME, "InsetsSource setWin %s", win); mWin = win; @@ -160,11 +161,14 @@ class InsetsSourceProvider { setServerVisible(false); mSource.setFrame(new Rect()); mSource.setVisibleFrame(null); - } else if (mControllable) { - mWin.setControllableInsetProvider(this); - if (mPendingControlTarget != null) { - updateControlForTarget(mPendingControlTarget, true /* force */); - mPendingControlTarget = null; + } else { + mWin.mProvidedInsetsSources.put(mSource.getType(), mSource); + if (mControllable) { + mWin.setControllableInsetProvider(this); + if (mPendingControlTarget != null) { + updateControlForTarget(mPendingControlTarget, true /* force */); + mPendingControlTarget = null; + } } } } diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java index 267f67759a24..3ba7b7d96e47 100644 --- a/services/core/java/com/android/server/wm/InsetsStateController.java +++ b/services/core/java/com/android/server/wm/InsetsStateController.java @@ -104,6 +104,8 @@ class InsetsStateController { * visible to the target. e.g., the source which represents the target window itself, and the * IME source when the target is above IME. We also need to exclude certain types of insets * source for client within specific windowing modes. + * This is to get the insets for a window layout on the screen. If the window is not there, use + * the {@link #getInsetsForWindowMetrics} to get insets instead. * * @param target The window associate with the perspective. * @return The state stripped of the necessary information. @@ -117,8 +119,8 @@ class InsetsStateController { final @InternalInsetsType int type = provider != null ? provider.getSource().getType() : ITYPE_INVALID; return getInsetsForTarget(type, target.getWindowingMode(), target.isAlwaysOnTop(), - isAboveIme(target), - target.getFrozenInsetsState() != null ? target.getFrozenInsetsState() : mState); + target.getFrozenInsetsState() != null ? target.getFrozenInsetsState() : + target.mAboveInsetsState); } InsetsState getInsetsForWindowMetrics(@NonNull WindowManager.LayoutParams attrs) { @@ -133,19 +135,7 @@ class InsetsStateController { final @WindowingMode int windowingMode = token != null ? token.getWindowingMode() : WINDOWING_MODE_UNDEFINED; final boolean alwaysOnTop = token != null && token.isAlwaysOnTop(); - return getInsetsForTarget(type, windowingMode, alwaysOnTop, isAboveIme(token), mState); - } - - private boolean isAboveIme(WindowContainer target) { - final WindowState imeWindow = mDisplayContent.mInputMethodWindow; - if (target == null || imeWindow == null) { - return false; - } - if (target instanceof WindowState) { - final WindowState win = (WindowState) target; - return win.needsRelativeLayeringToIme() || !win.mBehindIme; - } - return false; + return getInsetsForTarget(type, windowingMode, alwaysOnTop, mState); } private static @InternalInsetsType @@ -181,10 +171,12 @@ class InsetsStateController { * @see #getInsetsForWindowMetrics */ private InsetsState getInsetsForTarget(@InternalInsetsType int type, - @WindowingMode int windowingMode, boolean isAlwaysOnTop, boolean aboveIme, - @NonNull InsetsState state) { + @WindowingMode int windowingMode, boolean isAlwaysOnTop, InsetsState state) { + boolean stateCopied = false; + if (type != ITYPE_INVALID) { state = new InsetsState(state); + stateCopied = true; state.removeSource(type); // Navigation bar doesn't get influenced by anything else @@ -219,23 +211,15 @@ class InsetsStateController { if (WindowConfiguration.isFloating(windowingMode) || (windowingMode == WINDOWING_MODE_MULTI_WINDOW && isAlwaysOnTop)) { - state = new InsetsState(state); + if (!stateCopied) { + state = new InsetsState(state); + stateCopied = true; + } state.removeSource(ITYPE_STATUS_BAR); state.removeSource(ITYPE_NAVIGATION_BAR); state.removeSource(ITYPE_EXTRA_NAVIGATION_BAR); } - if (aboveIme) { - InsetsSource imeSource = state.peekSource(ITYPE_IME); - if (imeSource != null && imeSource.isVisible()) { - imeSource = new InsetsSource(imeSource); - imeSource.setVisible(false); - imeSource.setFrame(0, 0, 0, 0); - state = new InsetsState(state); - state.addSource(imeSource); - } - } - return state; } diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 6a3110f52c91..f3f608bb9070 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -3082,6 +3082,20 @@ class Task extends WindowContainer<WindowContainer> { return parentTask == null ? this : parentTask.getRootTask(); } + /** @return the first organized task. */ + @Nullable + Task getOrganizedTask() { + if (isOrganized()) { + return this; + } + final WindowContainer parent = getParent(); + if (parent == null) { + return null; + } + final Task parentTask = parent.asTask(); + return parentTask == null ? null : parentTask.getOrganizedTask(); + } + // TODO(task-merge): Figure out what's the right thing to do for places that used it. boolean isRootTask() { return getRootTask() == this; @@ -4172,6 +4186,14 @@ class Task extends WindowContainer<WindowContainer> { info.topActivityInfo = mReuseActivitiesReport.top != null ? mReuseActivitiesReport.top.info : null; + info.topActivityToken = mReuseActivitiesReport.top != null + ? mReuseActivitiesReport.top.appToken + : null; + // Whether the direct top activity is in size compat mode on foreground. + info.topActivityInSizeCompat = mReuseActivitiesReport.top != null + && mReuseActivitiesReport.top.getOrganizedTask() == this + && mReuseActivitiesReport.top.inSizeCompatMode() + && mReuseActivitiesReport.top.isState(RESUMED); info.launchCookies.clear(); info.addLaunchCookie(mLaunchCookie); forAllActivities(r -> { @@ -5221,6 +5243,12 @@ class Task extends WindowContainer<WindowContainer> { } } + /** Called when the top activity in the Root Task enters or exits size compat mode. */ + void onSizeCompatActivityChanged() { + // Trigger TaskInfoChanged to update the size compat restart button. + dispatchTaskInfoChangedIfNeeded(true /* force */); + } + /** * See {@link WindowContainerTransaction#setBoundsChangeTransaction}. In short this * transaction will be consumed by the next BASE_APPLICATION window within our hierarchy diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java index 5676909d021c..8b4d415efcb5 100644 --- a/services/core/java/com/android/server/wm/WindowProcessController.java +++ b/services/core/java/com/android/server/wm/WindowProcessController.java @@ -24,13 +24,11 @@ import static android.os.IInputConstants.DEFAULT_DISPATCHING_TIMEOUT_MILLIS; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_CONFIGURATION; import static com.android.internal.util.Preconditions.checkArgument; import static com.android.server.am.ActivityManagerService.MY_PID; -import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ACTIVITY_STARTS; import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RELEASE; import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_CONFIGURATION; import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_RELEASE; import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM; import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME; -import static com.android.server.wm.ActivityTaskManagerService.ACTIVITY_BG_START_GRACE_PERIOD_MS; import static com.android.server.wm.ActivityTaskManagerService.INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT_MILLIS; import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_NONE; import static com.android.server.wm.Task.ActivityState.DESTROYED; @@ -61,8 +59,6 @@ import android.os.IBinder; import android.os.Message; import android.os.Process; import android.os.RemoteException; -import android.os.SystemClock; -import android.util.ArrayMap; import android.util.ArraySet; import android.util.Log; import android.util.Slog; @@ -103,10 +99,6 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio final String mName; final int mUid; - // A set of tokens that currently contribute to this process being temporarily allowed - // to start activities even if it's not in the foreground. The values of this map are optional - // (can be null) and are used to trace back the grant to the notification token mechanism. - private final ArrayMap<Binder, IBinder> mBackgroundActivityStartTokens = new ArrayMap<>(); // The process of this application; 0 if none private volatile int mPid; // user of process. @@ -118,6 +110,7 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio final ArraySet<String> mPkgList = new ArraySet<>(); private final WindowProcessListener mListener; private final ActivityTaskManagerService mAtm; + private final BackgroundLaunchProcessController mBgLaunchController; // The actual proc... may be null only if 'persistent' is true (in which case we are in the // process of launching the app) private IApplicationThread mThread; @@ -169,8 +162,6 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio private volatile boolean mPerceptible; // Set to true when process was launched with a wrapper attached private volatile boolean mUsingWrapper; - // Set of UIDs of clients currently bound to this process - private volatile ArraySet<Integer> mBoundClientUids = new ArraySet<Integer>(); // Thread currently set for VR scheduling int mVrThreadTid; @@ -191,10 +182,10 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio // The most recent top-most activity that was resumed in the process for pre-Q app. private ActivityRecord mPreQTopResumedActivity = null; // The last time an activity was launched in the process - private long mLastActivityLaunchTime; + private volatile long mLastActivityLaunchTime; // The last time an activity was finished in the process while the process participated // in a visible task - private long mLastActivityFinishTime; + private volatile long mLastActivityFinishTime; // Last configuration that was reported to the process. private final Configuration mLastReportedConfiguration = new Configuration(); @@ -227,9 +218,6 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio /** Whether our process is currently running a {@link IRemoteAnimationRunner} */ private boolean mRunningRemoteAnimation; - @Nullable - private final BackgroundActivityStartCallback mBackgroundActivityStartCallback; - // The bits used for mActivityStateFlags. private static final int ACTIVITY_STATE_FLAG_IS_VISIBLE = 1 << 16; private static final int ACTIVITY_STATE_FLAG_IS_PAUSING_OR_PAUSED = 1 << 17; @@ -246,8 +234,8 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio */ private volatile int mActivityStateFlags = ACTIVITY_STATE_FLAG_MASK_MIN_TASK_LAYER; - public WindowProcessController(@NonNull ActivityTaskManagerService atm, ApplicationInfo info, - String name, int uid, int userId, Object owner, + public WindowProcessController(@NonNull ActivityTaskManagerService atm, + @NonNull ApplicationInfo info, String name, int uid, int userId, Object owner, @NonNull WindowProcessListener listener) { mInfo = info; mName = name; @@ -256,7 +244,8 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio mOwner = owner; mListener = listener; mAtm = atm; - mBackgroundActivityStartCallback = mAtm.getBackgroundActivityStartCallback(); + mBgLaunchController = new BackgroundLaunchProcessController( + atm::hasActiveVisibleWindow, atm.getBackgroundActivityStartCallback()); boolean isSysUiPackage = info.packageName.equals( mAtm.getSysUiServiceComponentLocked().getPackageName()); @@ -489,162 +478,59 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio } void setLastActivityFinishTimeIfNeeded(long finishTime) { - if (finishTime <= mLastActivityFinishTime || !hasActivityInVisibleTask()) { + if (finishTime <= mLastActivityFinishTime || !hasVisibleActivities()) { return; } mLastActivityFinishTime = finishTime; } /** - * Allows background activity starts using token {@code entity}. Optionally, you can provide - * {@code originatingToken} if you have one such originating token, this is useful for tracing - * back the grant in the case of the notification token. - * - * If {@code entity} is already added, this method will update its {@code originatingToken}. + * @see BackgroundLaunchProcessController#addOrUpdateAllowBackgroundActivityStartsToken(Binder, + * IBinder) */ public void addOrUpdateAllowBackgroundActivityStartsToken(Binder entity, @Nullable IBinder originatingToken) { - synchronized (mAtm.mGlobalLock) { - mBackgroundActivityStartTokens.put(entity, originatingToken); - } + mBgLaunchController.addOrUpdateAllowBackgroundActivityStartsToken(entity, originatingToken); } - /** - * Removes token {@code entity} that allowed background activity starts added via {@link - * #addOrUpdateAllowBackgroundActivityStartsToken(Binder, IBinder)}. - */ + /** @see BackgroundLaunchProcessController#removeAllowBackgroundActivityStartsToken(Binder) */ public void removeAllowBackgroundActivityStartsToken(Binder entity) { - synchronized (mAtm.mGlobalLock) { - mBackgroundActivityStartTokens.remove(entity); - } + mBgLaunchController.removeAllowBackgroundActivityStartsToken(entity); } /** * Is this WindowProcessController in the state of allowing background FGS start? */ + @HotPath(caller = HotPath.START_SERVICE) public boolean areBackgroundFgsStartsAllowed() { - synchronized (mAtm.mGlobalLock) { - return areBackgroundActivityStartsAllowed(mAtm.getBalAppSwitchesAllowed(), true); - } + return areBackgroundActivityStartsAllowed(mAtm.getBalAppSwitchesAllowed(), + true /* isCheckingForFgsStart */); } boolean areBackgroundActivityStartsAllowed(boolean appSwitchAllowed) { - return areBackgroundActivityStartsAllowed(appSwitchAllowed, false); + return areBackgroundActivityStartsAllowed(appSwitchAllowed, + false /* isCheckingForFgsStart */); } - boolean areBackgroundActivityStartsAllowed(boolean appSwitchAllowed, + private boolean areBackgroundActivityStartsAllowed(boolean appSwitchAllowed, boolean isCheckingForFgsStart) { - // If app switching is not allowed, we ignore all the start activity grace period - // exception so apps cannot start itself in onPause() after pressing home button. - if (appSwitchAllowed) { - // allow if any activity in the caller has either started or finished very recently, and - // it must be started or finished after last stop app switches time. - final long now = SystemClock.uptimeMillis(); - if (now - mLastActivityLaunchTime < ACTIVITY_BG_START_GRACE_PERIOD_MS - || now - mLastActivityFinishTime < ACTIVITY_BG_START_GRACE_PERIOD_MS) { - // if activity is started and finished before stop app switch time, we should not - // let app to be able to start background activity even it's in grace period. - if (mLastActivityLaunchTime > mAtm.getLastStopAppSwitchesTime() - || mLastActivityFinishTime > mAtm.getLastStopAppSwitchesTime()) { - if (DEBUG_ACTIVITY_STARTS) { - Slog.d(TAG, "[WindowProcessController(" + mPid - + ")] Activity start allowed: within " - + ACTIVITY_BG_START_GRACE_PERIOD_MS + "ms grace period"); - } - return true; - } - if (DEBUG_ACTIVITY_STARTS) { - Slog.d(TAG, "[WindowProcessController(" + mPid + ")] Activity start within " - + ACTIVITY_BG_START_GRACE_PERIOD_MS - + "ms grace period but also within stop app switch window"); - } - - } - } - // allow if the proc is instrumenting with background activity starts privs - if (mInstrumentingWithBackgroundActivityStartPrivileges) { - if (DEBUG_ACTIVITY_STARTS) { - Slog.d(TAG, "[WindowProcessController(" + mPid - + ")] Activity start allowed: process instrumenting with background " - + "activity starts privileges"); - } - return true; - } - // allow if the caller has an activity in any foreground task - if (appSwitchAllowed && hasActivityInVisibleTask()) { - if (DEBUG_ACTIVITY_STARTS) { - Slog.d(TAG, "[WindowProcessController(" + mPid - + ")] Activity start allowed: process has activity in foreground task"); - } - return true; - } - // allow if the caller is bound by a UID that's currently foreground - if (isBoundByForegroundUid()) { - if (DEBUG_ACTIVITY_STARTS) { - Slog.d(TAG, "[WindowProcessController(" + mPid - + ")] Activity start allowed: process bound by foreground uid"); - } - return true; - } - // allow if the flag was explicitly set - if (isBackgroundStartAllowedByToken(isCheckingForFgsStart)) { - if (DEBUG_ACTIVITY_STARTS) { - Slog.d(TAG, "[WindowProcessController(" + mPid - + ")] Activity start allowed: process allowed by token"); - } - return true; - } - return false; - } - - /** - * If there are no tokens, we don't allow *by token*. If there are tokens and - * isCheckingForFgsStart is false, we ask the callback if the start is allowed for these tokens, - * otherwise if there is no callback we allow. - */ - private boolean isBackgroundStartAllowedByToken(boolean isCheckingForFgsStart) { - if (mBackgroundActivityStartTokens.isEmpty()) { - return false; - } - - if (isCheckingForFgsStart) { - /// The checking is for BG-FGS-start. - return true; - } - - if (mBackgroundActivityStartCallback == null) { - // We have tokens but no callback to decide => allow - return true; - } - // The callback will decide - return mBackgroundActivityStartCallback.isActivityStartAllowed( - mBackgroundActivityStartTokens.values(), mInfo.uid, mInfo.packageName); + return mBgLaunchController.areBackgroundActivityStartsAllowed(mPid, mUid, mInfo.packageName, + appSwitchAllowed, isCheckingForFgsStart, hasVisibleActivities(), + mInstrumentingWithBackgroundActivityStartPrivileges, + mAtm.getLastStopAppSwitchesTime(), + mLastActivityLaunchTime, mLastActivityFinishTime); } /** * Returns whether this process is allowed to close system dialogs via a background activity * start token that allows the close system dialogs operation (eg. notification). */ - public boolean canCloseSystemDialogsByToken() { - synchronized (mAtm.mGlobalLock) { - return !mBackgroundActivityStartTokens.isEmpty() - && mBackgroundActivityStartCallback != null - && mBackgroundActivityStartCallback.canCloseSystemDialogs( - mBackgroundActivityStartTokens.values(), mInfo.uid); - } - } - - private boolean isBoundByForegroundUid() { - for (int i = mBoundClientUids.size() - 1; i >= 0; --i) { - if (mAtm.hasActiveVisibleWindow(mBoundClientUids.valueAt(i))) { - return true; - } - } - return false; + boolean canCloseSystemDialogsByToken() { + return mBgLaunchController.canCloseSystemDialogsByToken(mUid); } public void setBoundClientUids(ArraySet<Integer> boundClientUids) { - mBoundClientUids = boundClientUids; + mBgLaunchController.setBoundClientUids(boundClientUids); } /** @@ -793,20 +679,6 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio return displayArea; } - private boolean hasActivityInVisibleTask() { - for (int i = mActivities.size() - 1; i >= 0; --i) { - Task task = mActivities.get(i).getTask(); - if (task == null) { - continue; - } - ActivityRecord topActivity = task.getTopNonFinishingActivity(); - if (topActivity != null && topActivity.mVisibleRequested) { - return true; - } - } - return false; - } - /** * Update the top resuming activity in process for pre-Q apps, only the top-most visible * activities are allowed to be resumed per process. @@ -1701,17 +1573,8 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio if (mVrThreadTid != 0) { pw.print(prefix); pw.print("mVrThreadTid="); pw.println(mVrThreadTid); } - if (mBackgroundActivityStartTokens.size() > 0) { - pw.print(prefix); - pw.println("Background activity start tokens (token: originating token):"); - for (int i = 0; i < mBackgroundActivityStartTokens.size(); i++) { - pw.print(prefix); pw.print(" - "); - pw.print(mBackgroundActivityStartTokens.keyAt(i)); - pw.print(": "); - pw.println(mBackgroundActivityStartTokens.valueAt(i)); - } - } + mBgLaunchController.dump(pw, prefix); } pw.println(prefix + " Configuration=" + getConfiguration()); pw.println(prefix + " OverrideConfiguration=" + getRequestedOverrideConfiguration()); diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 9a7823e35a01..f2be5ffb2ab2 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -212,6 +212,7 @@ import android.os.Trace; import android.os.WorkSource; import android.provider.Settings; import android.text.TextUtils; +import android.util.ArrayMap; import android.util.ArraySet; import android.util.DisplayMetrics; import android.util.MergedConfiguration; @@ -647,9 +648,14 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP boolean mSeamlesslyRotated = false; /** - * Indicates if this window is behind IME. Only windows behind IME can get insets from IME. + * The insets state of sources provided by windows above the current window. */ - boolean mBehindIme = false; + InsetsState mAboveInsetsState = new InsetsState(); + + /** + * The insets sources provided by this window. + */ + ArrayMap<Integer, InsetsSource> mProvidedInsetsSources = new ArrayMap<>(); /** * Surface insets from the previous call to relayout(), used to track @@ -3846,11 +3852,11 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP } /** - * @return {@code true} if bar shown within a given frame is allowed to be transparent + * @return {@code true} if bar shown within a given frame is allowed to be fully transparent * when the current window is displayed. */ - boolean isTransparentBarAllowed(Rect frame) { - return mActivityRecord == null || mActivityRecord.isTransparentBarAllowed(frame); + boolean isFullyTransparentBarAllowed(Rect frame) { + return mActivityRecord == null || mActivityRecord.isFullyTransparentBarAllowed(frame); } public boolean isLetterboxedOverlappingWith(Rect rect) { diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp index dc15b0749bb1..5b587e9859d8 100644 --- a/services/core/jni/com_android_server_input_InputManagerService.cpp +++ b/services/core/jni/com_android_server_input_InputManagerService.cpp @@ -26,14 +26,14 @@ // Log debug messages about InputDispatcherPolicy #define DEBUG_INPUT_DISPATCHER_POLICY 0 - -#include <atomic> -#include <cinttypes> -#include <limits.h> #include <android-base/parseint.h> #include <android-base/stringprintf.h> +#include <android/os/IInputConstants.h> #include <android_runtime/AndroidRuntime.h> #include <android_runtime/Log.h> +#include <limits.h> +#include <atomic> +#include <cinttypes> #include <utils/Log.h> #include <utils/Looper.h> @@ -46,6 +46,7 @@ #include <input/SpriteController.h> #include <ui/Region.h> +#include <batteryservice/include/batteryservice/BatteryServiceConstants.h> #include <inputflinger/InputManager.h> #include <android_os_MessageQueue.h> @@ -1908,6 +1909,20 @@ static jintArray nativeGetVibratorIds(JNIEnv* env, jclass clazz, jlong ptr, jint return vibIdArray; } +static jint nativeGetBatteryCapacity(JNIEnv* env, jclass /* clazz */, jlong ptr, jint deviceId) { + NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); + + std::optional<int32_t> ret = im->getInputManager()->getReader()->getBatteryCapacity(deviceId); + return static_cast<jint>(ret.value_or(android::os::IInputConstants::INVALID_BATTERY_CAPACITY)); +} + +static jint nativeGetBatteryStatus(JNIEnv* env, jclass /* clazz */, jlong ptr, jint deviceId) { + NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); + + std::optional<int32_t> ret = im->getInputManager()->getReader()->getBatteryStatus(deviceId); + return static_cast<jint>(ret.value_or(BATTERY_STATUS_UNKNOWN)); +} + static void nativeReloadKeyboardLayouts(JNIEnv* /* env */, jclass /* clazz */, jlong ptr) { NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); @@ -2163,6 +2178,8 @@ static const JNINativeMethod gInputManagerMethods[] = { {"nativeCancelVibrate", "(JII)V", (void*)nativeCancelVibrate}, {"nativeIsVibrating", "(JI)Z", (void*)nativeIsVibrating}, {"nativeGetVibratorIds", "(JI)[I", (void*)nativeGetVibratorIds}, + {"nativeGetBatteryCapacity", "(JI)I", (void*)nativeGetBatteryCapacity}, + {"nativeGetBatteryStatus", "(JI)I", (void*)nativeGetBatteryStatus}, {"nativeReloadKeyboardLayouts", "(J)V", (void*)nativeReloadKeyboardLayouts}, {"nativeReloadDeviceAliases", "(J)V", (void*)nativeReloadDeviceAliases}, {"nativeDump", "(J)Ljava/lang/String;", (void*)nativeDump}, diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 544eedf99c9e..da8d82450769 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -97,6 +97,7 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.notification.SystemNotificationChannels; import com.android.internal.os.BinderInternal; import com.android.internal.os.RuntimeInit; +import com.android.internal.policy.AttributeCache; import com.android.internal.util.ConcurrentUtils; import com.android.internal.util.EmergencyAffordanceManager; import com.android.internal.util.FrameworkStatsLog; @@ -341,6 +342,8 @@ public final class SystemServer implements Dumpable { "com.android.server.contentsuggestions.ContentSuggestionsManagerService"; private static final String SEARCH_UI_MANAGER_SERVICE_CLASS = "com.android.server.searchui.SearchUiManagerService"; + private static final String SMARTSPACE_MANAGER_SERVICE_CLASS = + "com.android.server.smartspace.SmartspaceManagerService"; private static final String DEVICE_IDLE_CONTROLLER_CLASS = "com.android.server.DeviceIdleController"; private static final String BLOB_STORE_MANAGER_SERVICE_CLASS = @@ -359,6 +362,9 @@ public final class SystemServer implements Dumpable { "com.android.server.ConnectivityServiceInitializer"; private static final String IP_CONNECTIVITY_METRICS_CLASS = "com.android.server.connectivity.IpConnectivityMetrics"; + private static final String MEDIA_COMMUNICATION_SERVICE_CLASS = + "com.android.server.media.MediaCommunicationService"; + private static final String ROLE_SERVICE_CLASS = "com.android.role.RoleService"; private static final String GAME_MANAGER_SERVICE_CLASS = "com.android.server.graphics.GameManagerService$Lifecycle"; @@ -1672,6 +1678,12 @@ public final class SystemServer implements Dumpable { mSystemServiceManager.startService(SEARCH_UI_MANAGER_SERVICE_CLASS); t.traceEnd(); + // Smartspace manager service + // TODO: add deviceHasConfigString(context, R.string.config_defaultSmartspaceService) + t.traceBegin("StartSmartspaceService"); + mSystemServiceManager.startService(SMARTSPACE_MANAGER_SERVICE_CLASS); + t.traceEnd(); + t.traceBegin("InitConnectivityModuleConnector"); try { ConnectivityModuleConnector.getInstance().init(context); @@ -2528,6 +2540,10 @@ public final class SystemServer implements Dumpable { mSystemServiceManager.startService(APP_SEARCH_MANAGER_SERVICE_CLASS); t.traceEnd(); + t.traceBegin("StartMediaCommunicationService"); + mSystemServiceManager.startService(MEDIA_COMMUNICATION_SERVICE_CLASS); + t.traceEnd(); + ConcurrentUtils.waitForFutureNoInterrupt(mBlobStoreServiceStart, START_BLOB_STORE_SERVICE); diff --git a/services/people/java/com/android/server/people/data/DataManager.java b/services/people/java/com/android/server/people/data/DataManager.java index 9a9a17112245..444f9c685a1b 100644 --- a/services/people/java/com/android/server/people/data/DataManager.java +++ b/services/people/java/com/android/server/people/data/DataManager.java @@ -264,7 +264,8 @@ public class DataManager { return new ConversationChannel(shortcutInfo, uid, parentChannel, parentChannelGroup, conversationInfo.getLastEventTimestamp(), - hasActiveNotifications(packageName, userId, shortcutId)); + hasActiveNotifications(packageName, userId, shortcutId), false, + getStatuses(conversationInfo)); } /** Returns the cached non-customized recent conversations. */ @@ -404,6 +405,10 @@ public class DataManager { String conversationId) { ConversationStore cs = getConversationStoreOrThrow(packageName, userId); ConversationInfo conversationInfo = getConversationInfoOrThrow(cs, conversationId); + return getStatuses(conversationInfo); + } + + private @NonNull List<ConversationStatus> getStatuses(ConversationInfo conversationInfo) { Collection<ConversationStatus> statuses = conversationInfo.getStatuses(); if (statuses != null) { final ArrayList<ConversationStatus> list = new ArrayList<>(statuses.size()); diff --git a/services/smartspace/Android.bp b/services/smartspace/Android.bp new file mode 100644 index 000000000000..fcf780d4d927 --- /dev/null +++ b/services/smartspace/Android.bp @@ -0,0 +1,13 @@ +filegroup { + name: "services.smartspace-sources", + srcs: ["java/**/*.java"], + path: "java", + visibility: ["//frameworks/base/services"], +} + +java_library_static { + name: "services.smartspace", + defaults: ["platform_service_defaults"], + srcs: [":services.smartspace-sources"], + libs: ["services.core"], +} diff --git a/services/smartspace/java/com/android/server/smartspace/RemoteSmartspaceService.java b/services/smartspace/java/com/android/server/smartspace/RemoteSmartspaceService.java new file mode 100644 index 000000000000..3b5a5a51536e --- /dev/null +++ b/services/smartspace/java/com/android/server/smartspace/RemoteSmartspaceService.java @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.server.smartspace; + +import android.annotation.NonNull; +import android.content.ComponentName; +import android.content.Context; +import android.os.IBinder; +import android.service.smartspace.ISmartspaceService; +import android.text.format.DateUtils; + +import com.android.internal.infra.AbstractMultiplePendingRequestsRemoteService; + + +/** + * Proxy to the {@link android.service.smartspace.SmartspaceService} implementation in another + * process. + */ +public class RemoteSmartspaceService extends + AbstractMultiplePendingRequestsRemoteService<RemoteSmartspaceService, + ISmartspaceService> { + + private static final String TAG = "RemoteSmartspaceService"; + + private static final long TIMEOUT_REMOTE_REQUEST_MILLIS = 2 * DateUtils.SECOND_IN_MILLIS; + + private final RemoteSmartspaceServiceCallbacks mCallback; + + public RemoteSmartspaceService(Context context, String serviceInterface, + ComponentName componentName, int userId, + RemoteSmartspaceServiceCallbacks callback, boolean bindInstantServiceAllowed, + boolean verbose) { + super(context, serviceInterface, componentName, userId, callback, + context.getMainThreadHandler(), + bindInstantServiceAllowed ? Context.BIND_ALLOW_INSTANT : 0, + verbose, /* initialCapacity= */ 1); + mCallback = callback; + } + + @Override + protected ISmartspaceService getServiceInterface(IBinder service) { + return ISmartspaceService.Stub.asInterface(service); + } + + @Override + protected long getTimeoutIdleBindMillis() { + return PERMANENT_BOUND_TIMEOUT_MS; + } + + @Override + protected long getRemoteRequestMillis() { + return TIMEOUT_REMOTE_REQUEST_MILLIS; + } + + /** + * Schedules a request to bind to the remote service. + */ + public void reconnect() { + super.scheduleBind(); + } + + /** + * Schedule async request on remote service. + */ + public void scheduleOnResolvedService(@NonNull AsyncRequest<ISmartspaceService> request) { + scheduleAsyncRequest(request); + } + + /** + * Execute async request on remote service immediately instead of sending it to Handler queue. + */ + public void executeOnResolvedService(@NonNull AsyncRequest<ISmartspaceService> request) { + executeAsyncRequest(request); + } + + /** + * Failure callback + */ + public interface RemoteSmartspaceServiceCallbacks + extends VultureCallback<RemoteSmartspaceService> { + + /** + * Notifies a the failure or timeout of a remote call. + */ + void onFailureOrTimeout(boolean timedOut); + + /** + * Notifies change in connected state of the remote service. + */ + void onConnectedStateChanged(boolean connected); + } + + @Override // from AbstractRemoteService + protected void handleOnConnectedStateChanged(boolean connected) { + if (mCallback != null) { + mCallback.onConnectedStateChanged(connected); + } + } +} diff --git a/services/smartspace/java/com/android/server/smartspace/SmartspaceManagerService.java b/services/smartspace/java/com/android/server/smartspace/SmartspaceManagerService.java new file mode 100644 index 000000000000..169b85eb7e06 --- /dev/null +++ b/services/smartspace/java/com/android/server/smartspace/SmartspaceManagerService.java @@ -0,0 +1,184 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.smartspace; + +import static android.Manifest.permission.MANAGE_SMARTSPACE; +import static android.app.ActivityManagerInternal.ALLOW_NON_FULL; +import static android.content.Context.SMARTSPACE_SERVICE; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.UserIdInt; +import android.app.ActivityManagerInternal; +import android.app.smartspace.ISmartspaceCallback; +import android.app.smartspace.ISmartspaceManager; +import android.app.smartspace.SmartspaceConfig; +import android.app.smartspace.SmartspaceSessionId; +import android.app.smartspace.SmartspaceTargetEvent; +import android.content.Context; +import android.os.Binder; +import android.os.IBinder; +import android.os.ResultReceiver; +import android.os.ShellCallback; +import android.util.Slog; + +import com.android.server.LocalServices; +import com.android.server.infra.AbstractMasterSystemService; +import com.android.server.infra.FrameworkResourcesServiceNameResolver; +import com.android.server.wm.ActivityTaskManagerInternal; + +import java.io.FileDescriptor; +import java.util.function.Consumer; + +/** + * A service used to return smartspace targets given a query. + */ +public class SmartspaceManagerService extends + AbstractMasterSystemService<SmartspaceManagerService, SmartspacePerUserService> { + + private static final String TAG = SmartspaceManagerService.class.getSimpleName(); + private static final boolean DEBUG = false; + + private static final int MAX_TEMP_SERVICE_DURATION_MS = 1_000 * 60 * 2; // 2 minutes + + private final ActivityTaskManagerInternal mActivityTaskManagerInternal; + + public SmartspaceManagerService(Context context) { + super(context, new FrameworkResourcesServiceNameResolver(context, + com.android.internal.R.string.config_defaultSmartspaceService), null, + PACKAGE_UPDATE_POLICY_NO_REFRESH | PACKAGE_RESTART_POLICY_NO_REFRESH); + mActivityTaskManagerInternal = LocalServices.getService(ActivityTaskManagerInternal.class); + } + + @Override + protected SmartspacePerUserService newServiceLocked(int resolvedUserId, boolean disabled) { + return new SmartspacePerUserService(this, mLock, resolvedUserId); + } + + @Override + public void onStart() { + publishBinderService(SMARTSPACE_SERVICE, new SmartspaceManagerStub()); + } + + @Override + protected void enforceCallingPermissionForManagement() { + getContext().enforceCallingPermission(MANAGE_SMARTSPACE, TAG); + } + + @Override // from AbstractMasterSystemService + protected void onServicePackageUpdatedLocked(@UserIdInt int userId) { + final SmartspacePerUserService service = peekServiceForUserLocked(userId); + if (service != null) { + service.onPackageUpdatedLocked(); + } + } + + @Override // from AbstractMasterSystemService + protected void onServicePackageRestartedLocked(@UserIdInt int userId) { + final SmartspacePerUserService service = peekServiceForUserLocked(userId); + if (service != null) { + service.onPackageRestartedLocked(); + } + } + + @Override + protected int getMaximumTemporaryServiceDurationMs() { + return MAX_TEMP_SERVICE_DURATION_MS; + } + + private class SmartspaceManagerStub extends ISmartspaceManager.Stub { + + @Override + public void createSmartspaceSession(@NonNull SmartspaceConfig smartspaceConfig, + @NonNull SmartspaceSessionId sessionId, @NonNull IBinder token) { + runForUserLocked("createSmartspaceSession", sessionId, (service) -> + service.onCreateSmartspaceSessionLocked(smartspaceConfig, sessionId, token)); + } + + @Override + public void notifySmartspaceEvent(SmartspaceSessionId sessionId, + SmartspaceTargetEvent event) { + runForUserLocked("notifySmartspaceEvent", sessionId, + (service) -> service.notifySmartspaceEventLocked(sessionId, event)); + } + + @Override + public void requestSmartspaceUpdate(SmartspaceSessionId sessionId) { + runForUserLocked("requestSmartspaceUpdate", sessionId, + (service) -> service.requestSmartspaceUpdateLocked(sessionId)); + } + + @Override + public void registerSmartspaceUpdates(@NonNull SmartspaceSessionId sessionId, + @NonNull ISmartspaceCallback callback) { + runForUserLocked("registerSmartspaceUpdates", sessionId, + (service) -> service.registerSmartspaceUpdatesLocked(sessionId, callback)); + } + + @Override + public void unregisterSmartspaceUpdates(SmartspaceSessionId sessionId, + ISmartspaceCallback callback) { + runForUserLocked("unregisterSmartspaceUpdates", sessionId, + (service) -> service.unregisterSmartspaceUpdatesLocked(sessionId, callback)); + } + + @Override + public void destroySmartspaceSession(@NonNull SmartspaceSessionId sessionId) { + runForUserLocked("destroySmartspaceSession", sessionId, + (service) -> service.onDestroyLocked(sessionId)); + } + + public void onShellCommand(@Nullable FileDescriptor in, @Nullable FileDescriptor out, + @Nullable FileDescriptor err, + @NonNull String[] args, @Nullable ShellCallback callback, + @NonNull ResultReceiver resultReceiver) { + new SmartspaceManagerServiceShellCommand(SmartspaceManagerService.this) + .exec(this, in, out, err, args, callback, resultReceiver); + } + + private void runForUserLocked(@NonNull final String func, + @NonNull final SmartspaceSessionId sessionId, + @NonNull final Consumer<SmartspacePerUserService> c) { + ActivityManagerInternal am = LocalServices.getService(ActivityManagerInternal.class); + final int userId = am.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), + sessionId.getUserId(), false, ALLOW_NON_FULL, null, null); + + if (DEBUG) { + Slog.d(TAG, "runForUserLocked:" + func + " from pid=" + Binder.getCallingPid() + + ", uid=" + Binder.getCallingUid()); + } + if (!(mServiceNameResolver.isTemporary(userId) + || mActivityTaskManagerInternal.isCallerRecents(Binder.getCallingUid()))) { + + String msg = "Permission Denial: " + func + " from pid=" + Binder.getCallingPid() + + ", uid=" + Binder.getCallingUid(); + Slog.w(TAG, msg); + throw new SecurityException(msg); + } + + final long origId = Binder.clearCallingIdentity(); + try { + synchronized (mLock) { + final SmartspacePerUserService service = getServiceForUserLocked(userId); + c.accept(service); + } + } finally { + Binder.restoreCallingIdentity(origId); + } + } + } +} diff --git a/services/smartspace/java/com/android/server/smartspace/SmartspaceManagerServiceShellCommand.java b/services/smartspace/java/com/android/server/smartspace/SmartspaceManagerServiceShellCommand.java new file mode 100644 index 000000000000..4143418e112e --- /dev/null +++ b/services/smartspace/java/com/android/server/smartspace/SmartspaceManagerServiceShellCommand.java @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.smartspace; + +import android.annotation.NonNull; +import android.os.ShellCommand; + +import java.io.PrintWriter; + +/** + * The shell command implementation for the SmartspaceManagerService. + */ +public class SmartspaceManagerServiceShellCommand extends ShellCommand { + + private static final String TAG = + SmartspaceManagerServiceShellCommand.class.getSimpleName(); + + private final SmartspaceManagerService mService; + + public SmartspaceManagerServiceShellCommand(@NonNull SmartspaceManagerService service) { + mService = service; + } + + @Override + public int onCommand(String cmd) { + if (cmd == null) { + return handleDefaultCommands(cmd); + } + final PrintWriter pw = getOutPrintWriter(); + switch (cmd) { + case "set": { + final String what = getNextArgRequired(); + switch (what) { + case "temporary-service": { + final int userId = Integer.parseInt(getNextArgRequired()); + String serviceName = getNextArg(); + if (serviceName == null) { + mService.resetTemporaryService(userId); + pw.println("SmartspaceService temporarily reset. "); + return 0; + } + final int duration = Integer.parseInt(getNextArgRequired()); + mService.setTemporaryService(userId, serviceName, duration); + pw.println("SmartspaceService temporarily set to " + serviceName + + " for " + duration + "ms"); + break; + } + } + } + break; + default: + return handleDefaultCommands(cmd); + } + return 0; + } + + @Override + public void onHelp() { + try (PrintWriter pw = getOutPrintWriter()) { + pw.println("SmartspaceManagerService commands:"); + pw.println(" help"); + pw.println(" Prints this help text."); + pw.println(""); + pw.println(" set temporary-service USER_ID [COMPONENT_NAME DURATION]"); + pw.println(" Temporarily (for DURATION ms) changes the service implemtation."); + pw.println(" To reset, call with just the USER_ID argument."); + pw.println(""); + } + } +} diff --git a/services/smartspace/java/com/android/server/smartspace/SmartspacePerUserService.java b/services/smartspace/java/com/android/server/smartspace/SmartspacePerUserService.java new file mode 100644 index 000000000000..db4346830efb --- /dev/null +++ b/services/smartspace/java/com/android/server/smartspace/SmartspacePerUserService.java @@ -0,0 +1,411 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.smartspace; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.app.AppGlobals; +import android.app.smartspace.ISmartspaceCallback; +import android.app.smartspace.SmartspaceConfig; +import android.app.smartspace.SmartspaceSessionId; +import android.app.smartspace.SmartspaceTargetEvent; +import android.content.ComponentName; +import android.content.pm.PackageManager; +import android.content.pm.PackageManager.NameNotFoundException; +import android.content.pm.ServiceInfo; +import android.os.IBinder; +import android.os.RemoteCallbackList; +import android.os.RemoteException; +import android.service.smartspace.ISmartspaceService; +import android.service.smartspace.SmartspaceService; +import android.util.ArrayMap; +import android.util.Slog; + +import com.android.internal.annotations.GuardedBy; +import com.android.internal.infra.AbstractRemoteService; +import com.android.server.infra.AbstractPerUserSystemService; + +/** + * Per-user instance of {@link SmartspaceManagerService}. + */ +public class SmartspacePerUserService extends + AbstractPerUserSystemService<SmartspacePerUserService, SmartspaceManagerService> + implements RemoteSmartspaceService.RemoteSmartspaceServiceCallbacks { + + private static final String TAG = SmartspacePerUserService.class.getSimpleName(); + @GuardedBy("mLock") + private final ArrayMap<SmartspaceSessionId, SmartspaceSessionInfo> mSessionInfos = + new ArrayMap<>(); + @Nullable + @GuardedBy("mLock") + private RemoteSmartspaceService mRemoteService; + /** + * When {@code true}, remote service died but service state is kept so it's restored after + * the system re-binds to it. + */ + @GuardedBy("mLock") + private boolean mZombie; + + protected SmartspacePerUserService(SmartspaceManagerService master, + Object lock, int userId) { + super(master, lock, userId); + } + + @Override // from PerUserSystemService + protected ServiceInfo newServiceInfoLocked(@NonNull ComponentName serviceComponent) + throws NameNotFoundException { + + ServiceInfo si; + try { + si = AppGlobals.getPackageManager().getServiceInfo(serviceComponent, + PackageManager.GET_META_DATA, mUserId); + } catch (RemoteException e) { + throw new NameNotFoundException("Could not get service for " + serviceComponent); + } + // TODO(b/177858728): must check that either the service is from a system component, + // or it matches a service set by shell cmd (so it can be used on CTS tests and when + // OEMs are implementing the real service and also verify the proper permissions + return si; + } + + @GuardedBy("mLock") + @Override // from PerUserSystemService + protected boolean updateLocked(boolean disabled) { + final boolean enabledChanged = super.updateLocked(disabled); + if (enabledChanged) { + if (!isEnabledLocked()) { + // Clear the remote service for the next call + updateRemoteServiceLocked(); + } + } + return enabledChanged; + } + + /** + * Notifies the service of a new smartspace session. + */ + @GuardedBy("mLock") + public void onCreateSmartspaceSessionLocked(@NonNull SmartspaceConfig smartspaceConfig, + @NonNull SmartspaceSessionId sessionId, @NonNull IBinder token) { + final boolean serviceExists = resolveService(sessionId, + s -> s.onCreateSmartspaceSession(smartspaceConfig, sessionId)); + + if (serviceExists && !mSessionInfos.containsKey(sessionId)) { + final SmartspaceSessionInfo sessionInfo = new SmartspaceSessionInfo( + sessionId, smartspaceConfig, token, () -> { + synchronized (mLock) { + onDestroyLocked(sessionId); + } + }); + if (sessionInfo.linkToDeath()) { + mSessionInfos.put(sessionId, sessionInfo); + } else { + // destroy the session if calling process is already dead + onDestroyLocked(sessionId); + } + } + } + + /** + * Records an smartspace event to the service. + */ + @GuardedBy("mLock") + public void notifySmartspaceEventLocked(@NonNull SmartspaceSessionId sessionId, + @NonNull SmartspaceTargetEvent event) { + final SmartspaceSessionInfo sessionInfo = mSessionInfos.get(sessionId); + if (sessionInfo == null) return; + resolveService(sessionId, s -> s.notifySmartspaceEvent(sessionId, event)); + } + + /** + * Requests the service to return smartspace results of an input query. + */ + @GuardedBy("mLock") + public void requestSmartspaceUpdateLocked(@NonNull SmartspaceSessionId sessionId) { + final SmartspaceSessionInfo sessionInfo = mSessionInfos.get(sessionId); + if (sessionInfo == null) return; + resolveService(sessionId, + s -> s.requestSmartspaceUpdate(sessionId)); + } + + /** + * Registers a callback for continuous updates of predicted apps or shortcuts. + */ + @GuardedBy("mLock") + public void registerSmartspaceUpdatesLocked(@NonNull SmartspaceSessionId sessionId, + @NonNull ISmartspaceCallback callback) { + final SmartspaceSessionInfo sessionInfo = mSessionInfos.get(sessionId); + if (sessionInfo == null) return; + final boolean serviceExists = resolveService(sessionId, + s -> s.registerSmartspaceUpdates(sessionId, callback)); + if (serviceExists) { + sessionInfo.addCallbackLocked(callback); + } + } + + /** + * Unregisters a callback for continuous updates of predicted apps or shortcuts. + */ + @GuardedBy("mLock") + public void unregisterSmartspaceUpdatesLocked(@NonNull SmartspaceSessionId sessionId, + @NonNull ISmartspaceCallback callback) { + final SmartspaceSessionInfo sessionInfo = mSessionInfos.get(sessionId); + if (sessionInfo == null) return; + final boolean serviceExists = resolveService(sessionId, + s -> s.unregisterSmartspaceUpdates(sessionId, callback)); + if (serviceExists) { + sessionInfo.removeCallbackLocked(callback); + } + } + + /** + * Notifies the service of the end of an existing smartspace session. + */ + @GuardedBy("mLock") + public void onDestroyLocked(@NonNull SmartspaceSessionId sessionId) { + if (isDebug()) { + Slog.d(TAG, "onDestroyLocked(): sessionId=" + sessionId); + } + final SmartspaceSessionInfo sessionInfo = mSessionInfos.remove(sessionId); + if (sessionInfo == null) return; + resolveService(sessionId, s -> s.onDestroySmartspaceSession(sessionId)); + sessionInfo.destroy(); + } + + @Override + public void onFailureOrTimeout(boolean timedOut) { + if (isDebug()) { + Slog.d(TAG, "onFailureOrTimeout(): timed out=" + timedOut); + } + // Do nothing, we are just proxying to the smartspace ui service + } + + @Override + public void onConnectedStateChanged(boolean connected) { + if (isDebug()) { + Slog.d(TAG, "onConnectedStateChanged(): connected=" + connected); + } + if (connected) { + synchronized (mLock) { + if (mZombie) { + // Validation check - shouldn't happen + if (mRemoteService == null) { + Slog.w(TAG, "Cannot resurrect sessions because remote service is null"); + return; + } + mZombie = false; + resurrectSessionsLocked(); + } + } + } + } + + @Override + public void onServiceDied(RemoteSmartspaceService service) { + if (isDebug()) { + Slog.w(TAG, "onServiceDied(): service=" + service); + } + synchronized (mLock) { + mZombie = true; + } + updateRemoteServiceLocked(); + } + + @GuardedBy("mLock") + private void updateRemoteServiceLocked() { + if (mRemoteService != null) { + mRemoteService.destroy(); + mRemoteService = null; + } + } + + void onPackageUpdatedLocked() { + if (isDebug()) { + Slog.v(TAG, "onPackageUpdatedLocked()"); + } + destroyAndRebindRemoteService(); + } + + void onPackageRestartedLocked() { + if (isDebug()) { + Slog.v(TAG, "onPackageRestartedLocked()"); + } + destroyAndRebindRemoteService(); + } + + private void destroyAndRebindRemoteService() { + if (mRemoteService == null) { + return; + } + + if (isDebug()) { + Slog.d(TAG, "Destroying the old remote service."); + } + mRemoteService.destroy(); + mRemoteService = null; + + synchronized (mLock) { + mZombie = true; + } + mRemoteService = getRemoteServiceLocked(); + if (mRemoteService != null) { + if (isDebug()) { + Slog.d(TAG, "Rebinding to the new remote service."); + } + mRemoteService.reconnect(); + } + } + + /** + * Called after the remote service connected, it's used to restore state from a 'zombie' + * service (i.e., after it died). + */ + private void resurrectSessionsLocked() { + final int numSessions = mSessionInfos.size(); + if (isDebug()) { + Slog.d(TAG, "Resurrecting remote service (" + mRemoteService + ") on " + + numSessions + " sessions."); + } + + for (SmartspaceSessionInfo sessionInfo : mSessionInfos.values()) { + sessionInfo.resurrectSessionLocked(this, sessionInfo.mToken); + } + } + + @GuardedBy("mLock") + @Nullable + protected boolean resolveService( + @NonNull final SmartspaceSessionId sessionId, + @NonNull final AbstractRemoteService.AsyncRequest<ISmartspaceService> cb) { + + final RemoteSmartspaceService service = getRemoteServiceLocked(); + if (service != null) { + service.executeOnResolvedService(cb); + } + return service != null; + } + + @GuardedBy("mLock") + @Nullable + private RemoteSmartspaceService getRemoteServiceLocked() { + if (mRemoteService == null) { + final String serviceName = getComponentNameLocked(); + if (serviceName == null) { + if (mMaster.verbose) { + Slog.v(TAG, "getRemoteServiceLocked(): not set"); + } + return null; + } + ComponentName serviceComponent = ComponentName.unflattenFromString(serviceName); + + mRemoteService = new RemoteSmartspaceService(getContext(), + SmartspaceService.SERVICE_INTERFACE, serviceComponent, mUserId, this, + mMaster.isBindInstantServiceAllowed(), mMaster.verbose); + } + + return mRemoteService; + } + + private static final class SmartspaceSessionInfo { + private static final boolean DEBUG = false; // Do not submit with true + @NonNull + final IBinder mToken; + @NonNull + final IBinder.DeathRecipient mDeathRecipient; + @NonNull + private final SmartspaceSessionId mSessionId; + @NonNull + private final SmartspaceConfig mSmartspaceConfig; + private final RemoteCallbackList<ISmartspaceCallback> mCallbacks = + new RemoteCallbackList<ISmartspaceCallback>() { + @Override + public void onCallbackDied(ISmartspaceCallback callback) { + if (DEBUG) { + Slog.d(TAG, "Binder died for session Id=" + mSessionId + + " and callback=" + callback.asBinder()); + } + if (mCallbacks.getRegisteredCallbackCount() == 0) { + destroy(); + } + } + }; + + SmartspaceSessionInfo( + @NonNull final SmartspaceSessionId id, + @NonNull final SmartspaceConfig context, + @NonNull final IBinder token, + @NonNull final IBinder.DeathRecipient deathRecipient) { + if (DEBUG) { + Slog.d(TAG, "Creating SmartspaceSessionInfo for session Id=" + id); + } + mSessionId = id; + mSmartspaceConfig = context; + mToken = token; + mDeathRecipient = deathRecipient; + } + + void addCallbackLocked(ISmartspaceCallback callback) { + if (DEBUG) { + Slog.d(TAG, "Storing callback for session Id=" + mSessionId + + " and callback=" + callback.asBinder()); + } + mCallbacks.register(callback); + } + + void removeCallbackLocked(ISmartspaceCallback callback) { + if (DEBUG) { + Slog.d(TAG, "Removing callback for session Id=" + mSessionId + + " and callback=" + callback.asBinder()); + } + mCallbacks.unregister(callback); + } + + boolean linkToDeath() { + try { + mToken.linkToDeath(mDeathRecipient, 0); + } catch (RemoteException e) { + if (DEBUG) { + Slog.w(TAG, "Caller is dead before session can be started, sessionId: " + + mSessionId); + } + return false; + } + return true; + } + + void destroy() { + if (DEBUG) { + Slog.d(TAG, "Removing all callbacks for session Id=" + mSessionId + + " and " + mCallbacks.getRegisteredCallbackCount() + " callbacks."); + } + if (mToken != null) { + mToken.unlinkToDeath(mDeathRecipient, 0); + } + mCallbacks.kill(); + } + + void resurrectSessionLocked(SmartspacePerUserService service, IBinder token) { + int callbackCount = mCallbacks.getRegisteredCallbackCount(); + if (DEBUG) { + Slog.d(TAG, "Resurrecting remote service (" + service.getRemoteServiceLocked() + + ") for session Id=" + mSessionId + " and " + + callbackCount + " callbacks."); + } + service.onCreateSmartspaceSessionLocked(mSmartspaceConfig, mSessionId, token); + } + } +} diff --git a/services/tests/servicestests/src/com/android/server/VibratorServiceTest.java b/services/tests/servicestests/src/com/android/server/VibratorServiceTest.java index 743848c2453c..2932926b0b05 100644 --- a/services/tests/servicestests/src/com/android/server/VibratorServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/VibratorServiceTest.java @@ -745,7 +745,8 @@ public class VibratorServiceTest { private InputDevice createInputDeviceWithVibrator(int id) { return new InputDevice(id, 0, 0, "name", 0, 0, "description", false, 0, 0, - null, /* hasVibrator= */ true, false, false, false /* hasSensor */); + null, /* hasVibrator= */ true, false, false, false /* hasSensor */, + false /* hasBattery */); } private static <T> void addLocalServiceMock(Class<T> clazz, T mock) { diff --git a/services/tests/servicestests/src/com/android/server/graphics/fonts/FontCrashDetectorTest.java b/services/tests/servicestests/src/com/android/server/graphics/fonts/FontCrashDetectorTest.java new file mode 100644 index 000000000000..275e7c7fec04 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/graphics/fonts/FontCrashDetectorTest.java @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.graphics.fonts; + +import static com.google.common.truth.Truth.assertThat; + +import android.content.Context; +import android.os.FileUtils; +import android.platform.test.annotations.Presubmit; + +import androidx.test.InstrumentationRegistry; +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.io.File; + +@Presubmit +@SmallTest +@RunWith(AndroidJUnit4.class) +public final class FontCrashDetectorTest { + + private File mCacheDir; + + @SuppressWarnings("ResultOfMethodCallIgnored") + @Before + public void setUp() { + Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); + mCacheDir = new File(context.getCacheDir(), "UpdatableFontDirTest"); + FileUtils.deleteContentsAndDir(mCacheDir); + mCacheDir.mkdirs(); + } + + @Test + public void detectCrash() throws Exception { + // Prepare a marker file. + File file = new File(mCacheDir, "detectCrash"); + assertThat(file.createNewFile()).isTrue(); + + FontCrashDetector detector = new FontCrashDetector(file); + assertThat(detector.hasCrashed()).isTrue(); + + detector.clear(); + assertThat(detector.hasCrashed()).isFalse(); + assertThat(file.exists()).isFalse(); + } + + @Test + public void monitorCrash() { + File file = new File(mCacheDir, "monitorCrash"); + FontCrashDetector detector = new FontCrashDetector(file); + assertThat(detector.hasCrashed()).isFalse(); + + FontCrashDetector.MonitoredBlock block = detector.start(); + assertThat(file.exists()).isTrue(); + + block.close(); + assertThat(file.exists()).isFalse(); + } +} diff --git a/services/tests/servicestests/src/com/android/server/graphics/fonts/UpdatableFontDirTest.java b/services/tests/servicestests/src/com/android/server/graphics/fonts/UpdatableFontDirTest.java index d06779048837..833103142ccf 100644 --- a/services/tests/servicestests/src/com/android/server/graphics/fonts/UpdatableFontDirTest.java +++ b/services/tests/servicestests/src/com/android/server/graphics/fonts/UpdatableFontDirTest.java @@ -147,6 +147,7 @@ public final class UpdatableFontDirTest { UpdatableFontDir dirForPreparation = new UpdatableFontDir( mUpdatableFontFilesDir, mPreinstalledFontDirs, parser, fakeFsverityUtil, mConfigFile); + dirForPreparation.loadFontFileMap(); assertThat(dirForPreparation.getSystemFontConfig().getLastModifiedTimeMillis()) .isEqualTo(expectedModifiedDate); installFontFile(dirForPreparation, "foo,1", GOOD_SIGNATURE); @@ -162,6 +163,7 @@ public final class UpdatableFontDirTest { UpdatableFontDir dir = new UpdatableFontDir( mUpdatableFontFilesDir, mPreinstalledFontDirs, parser, fakeFsverityUtil, mConfigFile); + dir.loadFontFileMap(); assertThat(dir.getFontFileMap()).containsKey("foo.ttf"); assertThat(parser.getRevision(dir.getFontFileMap().get("foo.ttf"))).isEqualTo(3); assertThat(dir.getFontFileMap()).containsKey("bar.ttf"); @@ -177,6 +179,7 @@ public final class UpdatableFontDirTest { UpdatableFontDir dir = new UpdatableFontDir( mUpdatableFontFilesDir, mPreinstalledFontDirs, parser, fakeFsverityUtil, mConfigFile); + dir.loadFontFileMap(); assertThat(dir.getFontFileMap()).isEmpty(); } @@ -187,6 +190,7 @@ public final class UpdatableFontDirTest { UpdatableFontDir dirForPreparation = new UpdatableFontDir( mUpdatableFontFilesDir, mPreinstalledFontDirs, parser, fakeFsverityUtil, mConfigFile); + dirForPreparation.loadFontFileMap(); installFontFile(dirForPreparation, "foo,1", GOOD_SIGNATURE); installFontFile(dirForPreparation, "bar,2", GOOD_SIGNATURE); installFontFile(dirForPreparation, "foo,3", GOOD_SIGNATURE); @@ -199,6 +203,7 @@ public final class UpdatableFontDirTest { UpdatableFontDir dir = new UpdatableFontDir( mUpdatableFontFilesDir, mPreinstalledFontDirs, parser, fakeFsverityUtil, mConfigFile); + dir.loadFontFileMap(); assertThat(dir.getFontFileMap()).isEmpty(); // All font dirs (including dir for "bar.ttf") should be deleted. assertThat(mUpdatableFontFilesDir.list()).hasLength(0); @@ -211,6 +216,7 @@ public final class UpdatableFontDirTest { UpdatableFontDir dirForPreparation = new UpdatableFontDir( mUpdatableFontFilesDir, mPreinstalledFontDirs, parser, fakeFsverityUtil, mConfigFile); + dirForPreparation.loadFontFileMap(); installFontFile(dirForPreparation, "foo,1", GOOD_SIGNATURE); installFontFile(dirForPreparation, "bar,2", GOOD_SIGNATURE); installFontFile(dirForPreparation, "foo,3", GOOD_SIGNATURE); @@ -224,6 +230,7 @@ public final class UpdatableFontDirTest { UpdatableFontDir dir = new UpdatableFontDir( mUpdatableFontFilesDir, mPreinstalledFontDirs, parser, fakeFsverityUtil, mConfigFile); + dir.loadFontFileMap(); assertThat(dir.getFontFileMap()).isEmpty(); // All font dirs (including dir for "bar.ttf") should be deleted. assertThat(mUpdatableFontFilesDir.list()).hasLength(0); @@ -236,6 +243,7 @@ public final class UpdatableFontDirTest { UpdatableFontDir dirForPreparation = new UpdatableFontDir( mUpdatableFontFilesDir, mPreinstalledFontDirs, parser, fakeFsverityUtil, mConfigFile); + dirForPreparation.loadFontFileMap(); installFontFile(dirForPreparation, "foo,1", GOOD_SIGNATURE); installFontFile(dirForPreparation, "bar,2", GOOD_SIGNATURE); installFontFile(dirForPreparation, "foo,3", GOOD_SIGNATURE); @@ -250,6 +258,7 @@ public final class UpdatableFontDirTest { UpdatableFontDir dir = new UpdatableFontDir( mUpdatableFontFilesDir, mPreinstalledFontDirs, parser, fakeFsverityUtil, mConfigFile); + dir.loadFontFileMap(); // For foo.ttf, preinstalled font (revision 5) should be used. assertThat(dir.getFontFileMap()).doesNotContainKey("foo.ttf"); // For bar.ttf, updated font (revision 4) should be used. @@ -268,6 +277,7 @@ public final class UpdatableFontDirTest { UpdatableFontDir dir = new UpdatableFontDir( mUpdatableFontFilesDir, mPreinstalledFontDirs, parser, fakeFsverityUtil, new File("/dev/null")); + dir.loadFontFileMap(); assertThat(dir.getFontFileMap()).isEmpty(); } @@ -278,6 +288,7 @@ public final class UpdatableFontDirTest { UpdatableFontDir dir = new UpdatableFontDir( mUpdatableFontFilesDir, mPreinstalledFontDirs, parser, fakeFsverityUtil, mConfigFile); + dir.loadFontFileMap(); installFontFile(dir, "test,1", GOOD_SIGNATURE); assertThat(dir.getFontFileMap()).containsKey("test.ttf"); @@ -295,6 +306,7 @@ public final class UpdatableFontDirTest { UpdatableFontDir dir = new UpdatableFontDir( mUpdatableFontFilesDir, mPreinstalledFontDirs, parser, fakeFsverityUtil, mConfigFile); + dir.loadFontFileMap(); installFontFile(dir, "test,1", GOOD_SIGNATURE); Map<String, File> mapBeforeUpgrade = dir.getFontFileMap(); @@ -313,6 +325,7 @@ public final class UpdatableFontDirTest { UpdatableFontDir dir = new UpdatableFontDir( mUpdatableFontFilesDir, mPreinstalledFontDirs, parser, fakeFsverityUtil, mConfigFile); + dir.loadFontFileMap(); installFontFile(dir, "test,2", GOOD_SIGNATURE); try { @@ -333,6 +346,7 @@ public final class UpdatableFontDirTest { UpdatableFontDir dir = new UpdatableFontDir( mUpdatableFontFilesDir, mPreinstalledFontDirs, parser, fakeFsverityUtil, mConfigFile); + dir.loadFontFileMap(); installFontFile(dir, "foo,1", GOOD_SIGNATURE); installFontFile(dir, "bar,2", GOOD_SIGNATURE); @@ -349,6 +363,7 @@ public final class UpdatableFontDirTest { UpdatableFontDir dir = new UpdatableFontDir( mUpdatableFontFilesDir, mPreinstalledFontDirs, parser, fakeFsverityUtil, mConfigFile); + dir.loadFontFileMap(); try { installFontFile(dir, "test,1", "Invalid signature"); @@ -368,6 +383,7 @@ public final class UpdatableFontDirTest { UpdatableFontDir dir = new UpdatableFontDir( mUpdatableFontFilesDir, mPreinstalledFontDirs, parser, fakeFsverityUtil, mConfigFile); + dir.loadFontFileMap(); try { installFontFile(dir, "test,1", GOOD_SIGNATURE); @@ -398,6 +414,7 @@ public final class UpdatableFontDirTest { UpdatableFontDir dir = new UpdatableFontDir( mUpdatableFontFilesDir, mPreinstalledFontDirs, parser, fakeFsverityUtil, readonlyFile); + dir.loadFontFileMap(); try { installFontFile(dir, "test,2", GOOD_SIGNATURE); @@ -429,6 +446,7 @@ public final class UpdatableFontDirTest { return 0; } }, fakeFsverityUtil, mConfigFile); + dir.loadFontFileMap(); try { installFontFile(dir, "foo,1", GOOD_SIGNATURE); @@ -456,6 +474,7 @@ public final class UpdatableFontDirTest { return 0; } }, fakeFsverityUtil, mConfigFile); + dir.loadFontFileMap(); try { installFontFile(dir, "foo,1", GOOD_SIGNATURE); @@ -491,6 +510,7 @@ public final class UpdatableFontDirTest { UpdatableFontDir dir = new UpdatableFontDir( mUpdatableFontFilesDir, mPreinstalledFontDirs, parser, fakeFsverityUtil, mConfigFile); + dir.loadFontFileMap(); try { installFontFile(dir, "foo,1", GOOD_SIGNATURE); diff --git a/services/tests/servicestests/src/com/android/server/job/WorkTypeConfigTest.java b/services/tests/servicestests/src/com/android/server/job/WorkTypeConfigTest.java index fba36cb402a0..c28292f03357 100644 --- a/services/tests/servicestests/src/com/android/server/job/WorkTypeConfigTest.java +++ b/services/tests/servicestests/src/com/android/server/job/WorkTypeConfigTest.java @@ -18,6 +18,9 @@ package com.android.server.job; import static com.android.server.job.JobConcurrencyManager.WORK_TYPE_BG; import static com.android.server.job.JobConcurrencyManager.WORK_TYPE_TOP; +import static org.junit.Assert.fail; + +import android.annotation.NonNull; import android.annotation.Nullable; import android.provider.DeviceConfig; import android.util.Pair; @@ -32,6 +35,7 @@ import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; +import java.util.ArrayList; import java.util.List; @RunWith(AndroidJUnit4.class) @@ -58,42 +62,90 @@ public class WorkTypeConfigTest { } private void check(@Nullable DeviceConfig.Properties config, - int defaultTotal, int defaultMaxBg, int defaultMinBg, - int expectedTotal, int expectedMaxBg, int expectedMinBg) throws Exception { + int defaultTotal, + @Nullable Pair<Integer, Integer> defaultTopLimits, + @Nullable Pair<Integer, Integer> defaultBgLimits, + boolean expectedValid, int expectedTotal, + @NonNull Pair<Integer, Integer> expectedTopLimits, + @NonNull Pair<Integer, Integer> expectedBgLimits) throws Exception { resetConfig(); if (config != null) { DeviceConfig.setProperties(config); } - final WorkTypeConfig counts = new WorkTypeConfig("test", - defaultTotal, - // defaultMin - List.of(Pair.create(WORK_TYPE_TOP, defaultTotal - defaultMaxBg), - Pair.create(WORK_TYPE_BG, defaultMinBg)), - // defaultMax - List.of(Pair.create(WORK_TYPE_BG, defaultMaxBg))); + List<Pair<Integer, Integer>> defaultMin = new ArrayList<>(); + List<Pair<Integer, Integer>> defaultMax = new ArrayList<>(); + Integer val; + if (defaultTopLimits != null) { + if ((val = defaultTopLimits.first) != null) { + defaultMin.add(Pair.create(WORK_TYPE_TOP, val)); + } + if ((val = defaultTopLimits.second) != null) { + defaultMax.add(Pair.create(WORK_TYPE_TOP, val)); + } + } + if (defaultBgLimits != null) { + if ((val = defaultBgLimits.first) != null) { + defaultMin.add(Pair.create(WORK_TYPE_BG, val)); + } + if ((val = defaultBgLimits.second) != null) { + defaultMax.add(Pair.create(WORK_TYPE_BG, val)); + } + } + + final WorkTypeConfig counts; + try { + counts = new WorkTypeConfig("test", + defaultTotal, defaultMin, defaultMax); + if (!expectedValid) { + fail("Invalid config successfully created"); + return; + } + } catch (IllegalArgumentException e) { + if (expectedValid) { + throw e; + } else { + // Success + return; + } + } counts.update(DeviceConfig.getProperties(DeviceConfig.NAMESPACE_JOB_SCHEDULER)); Assert.assertEquals(expectedTotal, counts.getMaxTotal()); - Assert.assertEquals(expectedMaxBg, counts.getMax(WORK_TYPE_BG)); - Assert.assertEquals(expectedMinBg, counts.getMinReserved(WORK_TYPE_BG)); + Assert.assertEquals((int) expectedTopLimits.first, counts.getMinReserved(WORK_TYPE_TOP)); + Assert.assertEquals((int) expectedTopLimits.second, counts.getMax(WORK_TYPE_TOP)); + Assert.assertEquals((int) expectedBgLimits.first, counts.getMinReserved(WORK_TYPE_BG)); + Assert.assertEquals((int) expectedBgLimits.second, counts.getMax(WORK_TYPE_BG)); } @Test public void test() throws Exception { // Tests with various combinations. - check(null, /*default*/ 5, 1, 0, /*expected*/ 5, 1, 0); - check(null, /*default*/ 5, 0, 0, /*expected*/ 5, 1, 0); - check(null, /*default*/ 0, 0, 0, /*expected*/ 1, 1, 0); - check(null, /*default*/ -1, -1, -1, /*expected*/ 1, 1, 0); - check(null, /*default*/ 5, 5, 5, /*expected*/ 5, 5, 4); - check(null, /*default*/ 6, 5, 6, /*expected*/ 6, 5, 5); - check(null, /*default*/ 4, 5, 6, /*expected*/ 4, 4, 3); - check(null, /*default*/ 5, 1, 1, /*expected*/ 5, 1, 1); - check(null, /*default*/ 15, 15, 15, /*expected*/ 15, 15, 14); - check(null, /*default*/ 16, 16, 16, /*expected*/ 16, 16, 15); - check(null, /*default*/ 20, 20, 20, /*expected*/ 16, 16, 15); + check(null, /*default*/ 5, Pair.create(4, null), Pair.create(0, 1), + /*expected*/ true, 5, Pair.create(4, 5), Pair.create(0, 1)); + check(null, /*default*/ 5, Pair.create(5, null), Pair.create(0, 0), + /*expected*/ true, 5, Pair.create(5, 5), Pair.create(0, 1)); + check(null, /*default*/ 0, Pair.create(5, null), Pair.create(0, 0), + /*expected*/ false, 1, Pair.create(1, 1), Pair.create(0, 1)); + check(null, /*default*/ -1, null, Pair.create(-1, -1), + /*expected*/ false, 1, Pair.create(1, 1), Pair.create(0, 1)); + check(null, /*default*/ 5, null, Pair.create(5, 5), + /*expected*/ true, 5, Pair.create(1, 5), Pair.create(4, 5)); + check(null, /*default*/ 6, Pair.create(1, null), Pair.create(6, 5), + /*expected*/ false, 6, Pair.create(1, 6), Pair.create(5, 5)); + check(null, /*default*/ 4, null, Pair.create(6, 5), + /*expected*/ false, 4, Pair.create(1, 4), Pair.create(3, 4)); + check(null, /*default*/ 5, Pair.create(4, null), Pair.create(1, 1), + /*expected*/ true, 5, Pair.create(4, 5), Pair.create(1, 1)); + check(null, /*default*/ 15, null, Pair.create(15, 15), + /*expected*/ true, 15, Pair.create(1, 15), Pair.create(14, 15)); + check(null, /*default*/ 16, null, Pair.create(16, 16), + /*expected*/ true, 16, Pair.create(1, 16), Pair.create(15, 16)); + check(null, /*default*/ 20, null, Pair.create(20, 20), + /*expected*/ false, 16, Pair.create(1, 16), Pair.create(15, 16)); + check(null, /*default*/ 20, null, Pair.create(16, 16), + /*expected*/ true, 16, Pair.create(1, 16), Pair.create(15, 16)); // Test for overriding with a setting string. check(new DeviceConfig.Properties.Builder(DeviceConfig.NAMESPACE_JOB_SCHEDULER) @@ -101,15 +153,26 @@ public class WorkTypeConfigTest { .setInt(KEY_MAX_BG, 4) .setInt(KEY_MIN_BG, 3) .build(), - /*default*/ 9, 9, 9, /*expected*/ 5, 4, 3); + /*default*/ 9, null, Pair.create(9, 9), + /*expected*/ true, 5, Pair.create(1, 5), Pair.create(3, 4)); check(new DeviceConfig.Properties.Builder(DeviceConfig.NAMESPACE_JOB_SCHEDULER) .setInt(KEY_MAX_TOTAL, 5).build(), - /*default*/ 9, 9, 9, /*expected*/ 5, 5, 4); + /*default*/ 9, null, Pair.create(9, 9), + /*expected*/ true, 5, Pair.create(1, 5), Pair.create(4, 5)); check(new DeviceConfig.Properties.Builder(DeviceConfig.NAMESPACE_JOB_SCHEDULER) .setInt(KEY_MAX_BG, 4).build(), - /*default*/ 9, 9, 9, /*expected*/ 9, 4, 4); + /*default*/ 9, null, Pair.create(9, 9), + /*expected*/ true, 9, Pair.create(1, 9), Pair.create(4, 4)); check(new DeviceConfig.Properties.Builder(DeviceConfig.NAMESPACE_JOB_SCHEDULER) .setInt(KEY_MIN_BG, 3).build(), - /*default*/ 9, 9, 9, /*expected*/ 9, 9, 3); + /*default*/ 9, null, Pair.create(9, 9), + /*expected*/ true, 9, Pair.create(1, 9), Pair.create(3, 9)); + check(new DeviceConfig.Properties.Builder(DeviceConfig.NAMESPACE_JOB_SCHEDULER) + .setInt(KEY_MAX_TOTAL, 20) + .setInt(KEY_MAX_BG, 20) + .setInt(KEY_MIN_BG, 8) + .build(), + /*default*/ 9, null, Pair.create(9, 9), + /*expected*/ true, 16, Pair.create(1, 16), Pair.create(8, 16)); } } diff --git a/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java b/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java index 161d3163c1cf..6e5789686c55 100644 --- a/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java @@ -535,8 +535,11 @@ public final class DataManagerTest { listenerService.onNotificationChannelModified(TEST_PKG_NAME, UserHandle.of(USER_ID_PRIMARY), mNotificationChannel, NOTIFICATION_CHANNEL_OR_GROUP_UPDATED); - assertThat(mDataManager.getConversation(TEST_PKG_NAME, USER_ID_PRIMARY, - TEST_SHORTCUT_ID)).isNotNull(); + ConversationChannel result = mDataManager.getConversation(TEST_PKG_NAME, USER_ID_PRIMARY, + TEST_SHORTCUT_ID); + assertThat(result).isNotNull(); + assertThat(result.hasBirthdayToday()).isFalse(); + assertThat(result.getStatuses()).isEmpty(); } @Test @@ -550,13 +553,15 @@ public final class DataManagerTest { shortcut.setCached(ShortcutInfo.FLAG_PINNED); mDataManager.addOrUpdateConversationInfo(shortcut); assertThat(mDataManager.getConversation(TEST_PKG_NAME, USER_ID_PRIMARY, - TEST_SHORTCUT_ID)).isNotNull(); + TEST_SHORTCUT_ID)).isNotNull(); assertThat(mDataManager.getConversation(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID + "1")).isNull(); NotificationListenerService listenerService = mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY); listenerService.onNotificationPosted(mStatusBarNotification); + ConversationStatus cs = new ConversationStatus.Builder("id", ACTIVITY_ANNIVERSARY).build(); + mDataManager.addOrUpdateStatus(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, cs); ConversationChannel result = mDataManager.getConversation(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID); @@ -568,6 +573,8 @@ public final class DataManagerTest { result.getParentNotificationChannel().getId()); assertEquals(mStatusBarNotification.getPostTime(), result.getLastEventTimestamp()); assertTrue(result.hasActiveNotifications()); + assertFalse(result.hasBirthdayToday()); + assertThat(result.getStatuses()).containsExactly(cs); } @Test diff --git a/services/tests/servicestests/src/com/android/server/vibrator/InputDeviceDelegateTest.java b/services/tests/servicestests/src/com/android/server/vibrator/InputDeviceDelegateTest.java index 28d313b4d4b5..e71c2f5ba8da 100644 --- a/services/tests/servicestests/src/com/android/server/vibrator/InputDeviceDelegateTest.java +++ b/services/tests/servicestests/src/com/android/server/vibrator/InputDeviceDelegateTest.java @@ -294,6 +294,8 @@ public class InputDeviceDelegateTest { private InputDevice createInputDevice(int id, boolean hasVibrator) { return new InputDevice(id, 0, 0, "name", 0, 0, "description", false, 0, 0, - null, hasVibrator, false, false, false /* hasSensor */); + null, hasVibrator, false, false, false /* hasSensor */, false /* hasBattery */); + + } } diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java index 5c67db7ef813..91fd7a2ad0c1 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java @@ -16,8 +16,8 @@ package com.android.server.wm; -import static android.content.ActivityInfoProto.SCREEN_ORIENTATION_PORTRAIT; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; +import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_PRESENTATION; @@ -50,6 +50,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyZeroInteractions; import android.content.pm.ActivityInfo; +import android.content.res.Configuration; import android.graphics.Rect; import android.os.Binder; import android.platform.test.annotations.Presubmit; @@ -408,6 +409,32 @@ public class DisplayAreaTest extends WindowTestsBase { } @Test + public void testRestrictAppBoundsToOverrideBounds() { + final RootDisplayArea root = + new DisplayAreaPolicyBuilderTest.SurfacelessDisplayAreaRoot(mWm); + final DisplayArea<DisplayArea> da = new DisplayArea<>(mWm, ANY, "Test_DA"); + root.addChild(da, POSITION_TOP); + final Rect displayBounds = new Rect(0, 0, 1800, 2800); + final Rect displayAppBounds = new Rect(0, 100, 1800, 2800); + final Rect daBounds = new Rect(0, 1400, 1800, 2800); + root.setBounds(displayBounds); + + // DA inherit parent app bounds. + final Configuration displayConfig = new Configuration(); + displayConfig.windowConfiguration.setAppBounds(displayAppBounds); + root.onRequestedOverrideConfigurationChanged(displayConfig); + + assertEquals(displayAppBounds, da.getConfiguration().windowConfiguration.getAppBounds()); + + // Restrict DA appBounds to override Bounds + da.setBounds(daBounds); + + final Rect expectedDaAppBounds = new Rect(daBounds); + expectedDaAppBounds.intersect(displayAppBounds); + assertEquals(expectedDaAppBounds, da.getConfiguration().windowConfiguration.getAppBounds()); + } + + @Test public void testGetOrientation() { final DisplayArea.Tokens area = new DisplayArea.Tokens(mWm, ABOVE_TASKS, "test"); final WindowToken token = createWindowToken(TYPE_APPLICATION_OVERLAY); diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java index 82ffa765cc27..37fb0e930acc 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java @@ -123,6 +123,15 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { updateDisplayFrames(); } + void addWindowWithRawInsetsState(WindowState win) { + addWindow(win); + // Without mPerformLayout in display content, the window cannot see any insets. Override the + // insets state with the global one. + final InsetsState insetsState = + win.getDisplayContent().getInsetsStateController().getRawInsetsState(); + win.mAboveInsetsState = insetsState; + } + public void setRotation(int rotation, boolean includingWindows) { mRotation = rotation; updateDisplayFrames(); @@ -272,7 +281,7 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { @Test public void layoutWindowLw_fitStatusBars() { mWindow.mAttrs.setFitInsetsTypes(Type.statusBars()); - addWindow(mWindow); + addWindowWithRawInsetsState(mWindow); mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); @@ -283,7 +292,7 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { @Test public void layoutWindowLw_fitNavigationBars() { mWindow.mAttrs.setFitInsetsTypes(Type.navigationBars()); - addWindow(mWindow); + addWindowWithRawInsetsState(mWindow); mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); @@ -294,7 +303,7 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { @Test public void layoutWindowLw_fitAllSides() { mWindow.mAttrs.setFitInsetsSides(Side.all()); - addWindow(mWindow); + addWindowWithRawInsetsState(mWindow); mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); @@ -305,7 +314,7 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { @Test public void layoutWindowLw_fitTopOnly() { mWindow.mAttrs.setFitInsetsSides(Side.TOP); - addWindow(mWindow); + addWindowWithRawInsetsState(mWindow); mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); @@ -315,11 +324,12 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { @Test public void layoutWindowLw_fitInsetsIgnoringVisibility() { - final InsetsState state = mWindow.getInsetsState(); + final InsetsState state = + mDisplayContent.getInsetsStateController().getRawInsetsState(); state.getSource(InsetsState.ITYPE_STATUS_BAR).setVisible(false); state.getSource(InsetsState.ITYPE_NAVIGATION_BAR).setVisible(false); mWindow.mAttrs.setFitInsetsIgnoringVisibility(true); - addWindow(mWindow); + addWindowWithRawInsetsState(mWindow); mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); @@ -329,11 +339,12 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { @Test public void layoutWindowLw_fitInsetsNotIgnoringVisibility() { - final InsetsState state = mWindow.getInsetsState(); + final InsetsState state = + mDisplayContent.getInsetsStateController().getRawInsetsState(); state.getSource(InsetsState.ITYPE_STATUS_BAR).setVisible(false); state.getSource(InsetsState.ITYPE_NAVIGATION_BAR).setVisible(false); mWindow.mAttrs.setFitInsetsIgnoringVisibility(false); - addWindow(mWindow); + addWindowWithRawInsetsState(mWindow); mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); @@ -349,8 +360,7 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { state.getSource(InsetsState.ITYPE_IME).setFrame( 0, DISPLAY_HEIGHT - IME_HEIGHT, DISPLAY_WIDTH, DISPLAY_HEIGHT); mWindow.mAttrs.privateFlags |= PRIVATE_FLAG_INSET_PARENT_FRAME_BY_IME; - mWindow.mBehindIme = true; - addWindow(mWindow); + addWindowWithRawInsetsState(mWindow); mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); @@ -364,7 +374,7 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { mWindow.mAttrs.setFitInsetsTypes(Type.displayCutout()); mWindow.mAttrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; - addWindow(mWindow); + addWindowWithRawInsetsState(mWindow); mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); @@ -379,7 +389,7 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { mWindow.mAttrs.flags = FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; mWindow.mAttrs.setFitInsetsTypes(0 /* types */); - addWindow(mWindow); + addWindowWithRawInsetsState(mWindow); mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); @@ -395,7 +405,7 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; mWindow.mAttrs.setFitInsetsTypes(0 /* types */); mWindow.mAttrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER; - addWindow(mWindow); + addWindowWithRawInsetsState(mWindow); mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); @@ -411,7 +421,7 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; mWindow.mAttrs.setFitInsetsTypes(0 /* types */); mWindow.mAttrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES; - addWindow(mWindow); + addWindowWithRawInsetsState(mWindow); mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); @@ -427,7 +437,7 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; mWindow.mAttrs.setFitInsetsTypes(0 /* types */); mWindow.mAttrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; - addWindow(mWindow); + addWindowWithRawInsetsState(mWindow); mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); @@ -442,7 +452,7 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { mWindow.mAttrs.flags = FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; mWindow.mAttrs.setFitInsetsTypes(0 /* types */); - addWindow(mWindow); + addWindowWithRawInsetsState(mWindow); mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); @@ -457,11 +467,12 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { mWindow.mAttrs.flags = FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; mWindow.mAttrs.setFitInsetsTypes(0 /* types */); - mWindow.getInsetsState().getSource(InsetsState.ITYPE_STATUS_BAR).setVisible(false); + mDisplayContent.getInsetsStateController().getRawInsetsState() + .getSource(InsetsState.ITYPE_STATUS_BAR).setVisible(false); final InsetsState requestedState = new InsetsState(); requestedState.getSource(ITYPE_STATUS_BAR).setVisible(false); mWindow.updateRequestedVisibility(requestedState); - addWindow(mWindow); + addWindowWithRawInsetsState(mWindow); mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); @@ -476,12 +487,13 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { mWindow.mAttrs.flags = FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; mWindow.mAttrs.setFitInsetsTypes(0 /* types */); - mWindow.getInsetsState().getSource(InsetsState.ITYPE_STATUS_BAR).setVisible(false); + mDisplayContent.getInsetsStateController().getRawInsetsState() + .getSource(InsetsState.ITYPE_STATUS_BAR).setVisible(false); final InsetsState requestedState = new InsetsState(); requestedState.getSource(ITYPE_STATUS_BAR).setVisible(false); mWindow.updateRequestedVisibility(requestedState); mWindow.mAttrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; - addWindow(mWindow); + addWindowWithRawInsetsState(mWindow); mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); @@ -497,7 +509,7 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { mWindow.mAttrs.flags = FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; mWindow.mAttrs.setFitInsetsTypes(0 /* types */); - addWindow(mWindow); + addWindowWithRawInsetsState(mWindow); mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); @@ -513,7 +525,7 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { mWindow.mAttrs.flags = FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; mWindow.mAttrs.setFitInsetsTypes(0 /* types */); - addWindow(mWindow); + addWindowWithRawInsetsState(mWindow); mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); @@ -529,7 +541,7 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { mWindow.mAttrs.flags = FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; mWindow.mAttrs.setFitInsetsTypes(0 /* types */); - addWindow(mWindow); + addWindowWithRawInsetsState(mWindow); mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); @@ -545,7 +557,7 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { mWindow.mAttrs.type = TYPE_APPLICATION_OVERLAY; mWindow.mAttrs.width = DISPLAY_WIDTH; mWindow.mAttrs.height = DISPLAY_HEIGHT; - addWindow(mWindow); + addWindowWithRawInsetsState(mWindow); mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); @@ -562,7 +574,7 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; mWindow.mAttrs.setFitInsetsTypes(0 /* types */); mWindow.mAttrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; - addWindow(mWindow); + addWindowWithRawInsetsState(mWindow); mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); @@ -576,7 +588,7 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { mWindow.mAttrs.flags = FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; mWindow.mAttrs.setFitInsetsTypes(0 /* types */); - addWindow(mWindow); + addWindowWithRawInsetsState(mWindow); mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); @@ -592,7 +604,7 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; mWindow.mAttrs.setFitInsetsTypes(0 /* types */); mWindow.mAttrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER; - addWindow(mWindow); + addWindowWithRawInsetsState(mWindow); mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); @@ -608,7 +620,7 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; mWindow.mAttrs.setFitInsetsTypes(0 /* types */); mWindow.mAttrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES; - addWindow(mWindow); + addWindowWithRawInsetsState(mWindow); mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); @@ -624,7 +636,7 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; mWindow.mAttrs.setFitInsetsTypes(0 /* types */); mWindow.mAttrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; - addWindow(mWindow); + addWindowWithRawInsetsState(mWindow); mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); @@ -638,7 +650,7 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; mWindow.mAttrs.setFitInsetsTypes(0 /* types */); mWindow.mAttrs.softInputMode = SOFT_INPUT_ADJUST_NOTHING; - addWindow(mWindow); + addWindowWithRawInsetsState(mWindow); final int forwardedInsetBottom = 50; mDisplayPolicy.setForwardedInsets(Insets.of(0, 0, 0, forwardedInsetBottom)); @@ -776,9 +788,13 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { public void testFixedRotationInsetsSourceFrame() { doReturn((mDisplayContent.getRotation() + 1) % 4).when(mDisplayContent) .rotationForActivityInDifferentOrientation(eq(mWindow.mActivityRecord)); - final Rect frame = mWindow.getInsetsState().getSource(ITYPE_STATUS_BAR).getFrame(); + mWindow.mAboveInsetsState.addSource(mDisplayContent.getInsetsStateController() + .getRawInsetsState().peekSource(ITYPE_STATUS_BAR)); + final Rect frame = mDisplayPolicy.getInsetsPolicy().getInsetsForWindow(mWindow) + .getSource(ITYPE_STATUS_BAR).getFrame(); mDisplayContent.rotateInDifferentOrientationIfNeeded(mWindow.mActivityRecord); - final Rect rotatedFrame = mWindow.getInsetsState().getSource(ITYPE_STATUS_BAR).getFrame(); + final Rect rotatedFrame = mDisplayPolicy.getInsetsPolicy().getInsetsForWindow(mWindow) + .getSource(ITYPE_STATUS_BAR).getFrame(); assertEquals(DISPLAY_WIDTH, frame.width()); assertEquals(DISPLAY_HEIGHT, rotatedFrame.width()); diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java index 77537a9de6be..499507e969cf 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java @@ -300,6 +300,7 @@ public class DisplayPolicyTests extends WindowTestsBase { displayPolicy.addWindowLw(mNavBarWindow, mNavBarWindow.mAttrs); mNavBarWindow.getControllableInsetProvider().setServerVisible(true); final InsetsState state = mDisplayContent.getInsetsStateController().getRawInsetsState(); + mImeWindow.mAboveInsetsState = state; mDisplayContent.mDisplayFrames = new DisplayFrames(mDisplayContent.getDisplayId(), state, displayInfo, null /* displayCutout */); diff --git a/services/tests/wmtests/src/com/android/server/wm/DualDisplayAreaGroupPolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/DualDisplayAreaGroupPolicyTest.java index e6f24da3e7b9..f91c9d0e9853 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DualDisplayAreaGroupPolicyTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/DualDisplayAreaGroupPolicyTest.java @@ -16,7 +16,7 @@ package com.android.server.wm; -import static android.content.ActivityInfoProto.SCREEN_ORIENTATION_LANDSCAPE; +import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java index e0fd3796f2aa..bf3ed692dc8e 100644 --- a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java @@ -45,6 +45,7 @@ import static org.mockito.Mockito.verify; import android.app.StatusBarManager; import android.platform.test.annotations.Presubmit; +import android.view.InsetsSource; import android.view.InsetsSourceControl; import android.view.InsetsState; @@ -272,7 +273,6 @@ public class InsetsPolicyTest extends WindowTestsBase { final WindowState navBar = addNonFocusableWindow(TYPE_NAVIGATION_BAR, "navBar"); navBar.setHasSurface(true); navBar.getControllableInsetProvider().setServerVisible(true); - final InsetsPolicy policy = spy(mDisplayContent.getInsetsPolicy()); doNothing().when(policy).startAnimation(anyBoolean(), any()); @@ -337,11 +337,14 @@ public class InsetsPolicyTest extends WindowTestsBase { @UseTestDisplay(addWindows = W_ACTIVITY) @Test public void testAbortTransientBars_bothCanBeAborted_appGetsBothRealControls() { - addNonFocusableWindow(TYPE_STATUS_BAR, "statusBar") - .getControllableInsetProvider().getSource().setVisible(false); - addNonFocusableWindow(TYPE_NAVIGATION_BAR, "navBar") - .getControllableInsetProvider().getSource().setVisible(false); - + final InsetsSource statusBarSource = addNonFocusableWindow(TYPE_STATUS_BAR, "statusBar") + .getControllableInsetProvider().getSource(); + final InsetsSource navBarSource = addNonFocusableWindow(TYPE_NAVIGATION_BAR, "navBar") + .getControllableInsetProvider().getSource(); + statusBarSource.setVisible(false); + navBarSource.setVisible(false); + mAppWindow.mAboveInsetsState.addSource(navBarSource); + mAppWindow.mAboveInsetsState.addSource(statusBarSource); final InsetsPolicy policy = spy(mDisplayContent.getInsetsPolicy()); doNothing().when(policy).startAnimation(anyBoolean(), any()); policy.updateBarControlTarget(mAppWindow); diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java index 276643847712..2107ab1eeeea 100644 --- a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java @@ -59,25 +59,6 @@ import org.junit.runner.RunWith; public class InsetsStateControllerTest extends WindowTestsBase { @Test - public void testStripForDispatch_notOwn() { - final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar"); - final WindowState app = createWindow(null, TYPE_APPLICATION, "app"); - getController().getSourceProvider(ITYPE_STATUS_BAR).setWindow(statusBar, null, null); - statusBar.setControllableInsetProvider(getController().getSourceProvider(ITYPE_STATUS_BAR)); - assertNotNull(getController().getInsetsForWindow(app).peekSource(ITYPE_STATUS_BAR)); - } - - @Test - public void testStripForDispatch_own() { - final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar"); - mDisplayContent.getInsetsStateController().getSourceProvider(ITYPE_STATUS_BAR) - .setWindow(statusBar, null, null); - statusBar.setControllableInsetProvider(getController().getSourceProvider(ITYPE_STATUS_BAR)); - final InsetsState state = getController().getInsetsForWindow(statusBar); - assertNull(state.peekSource(ITYPE_STATUS_BAR)); - } - - @Test public void testStripForDispatch_navBar() { final WindowState navBar = createWindow(null, TYPE_APPLICATION, "navBar"); final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar"); @@ -142,14 +123,15 @@ public class InsetsStateControllerTest extends WindowTestsBase { getController().getSourceProvider(ITYPE_IME).setWindow(mImeWindow, null, null); final WindowState app1 = createWindow(null, TYPE_APPLICATION, "app1"); - app1.mBehindIme = true; - final WindowState app2 = createWindow(null, TYPE_APPLICATION, "app2"); - app2.mBehindIme = false; + + app1.mAboveInsetsState.addSource(getController().getRawInsetsState().getSource(ITYPE_IME)); getController().getRawInsetsState().setSourceVisible(ITYPE_IME, true); - assertFalse(getController().getInsetsForWindow(app2).getSource(ITYPE_IME).isVisible()); - assertTrue(getController().getInsetsForWindow(app1).getSource(ITYPE_IME).isVisible()); + assertFalse(getController().getInsetsForWindow(app2).getSource(ITYPE_IME) + .isVisible()); + assertTrue(getController().getInsetsForWindow(app1).getSource(ITYPE_IME) + .isVisible()); } @UseTestDisplay(addWindows = W_INPUT_METHOD) @@ -158,7 +140,8 @@ public class InsetsStateControllerTest extends WindowTestsBase { getController().getSourceProvider(ITYPE_IME).setWindow(mImeWindow, null, null); final WindowState app = createWindow(null, TYPE_APPLICATION, "app"); - app.mBehindIme = true; + app.mAboveInsetsState.getSource(ITYPE_IME).setVisible(true); + app.mAboveInsetsState.getSource(ITYPE_IME).setFrame(mImeWindow.getFrame()); getController().getRawInsetsState().setSourceVisible(ITYPE_IME, true); assertTrue(getController().getInsetsForWindow(app).getSource(ITYPE_IME).isVisible()); @@ -170,10 +153,10 @@ public class InsetsStateControllerTest extends WindowTestsBase { getController().getSourceProvider(ITYPE_IME).setWindow(mImeWindow, null, null); final WindowState app = createWindow(null, TYPE_APPLICATION, "app"); - app.mBehindIme = false; getController().getRawInsetsState().setSourceVisible(ITYPE_IME, true); - assertFalse(getController().getInsetsForWindow(app).getSource(ITYPE_IME).isVisible()); + assertFalse(getController().getInsetsForWindow(app).getSource(ITYPE_IME) + .isVisible()); } @UseTestDisplay(addWindows = W_INPUT_METHOD) @@ -210,7 +193,8 @@ public class InsetsStateControllerTest extends WindowTestsBase { // app won't get visible IME insets while above IME even when IME is visible. assertTrue(getController().getRawInsetsState().getSourceOrDefaultVisibility(ITYPE_IME)); - assertFalse(getController().getInsetsForWindow(app).getSource(ITYPE_IME).isVisible()); + assertFalse(getController().getInsetsForWindow(app).getSource(ITYPE_IME) + .isVisible()); // Reset invocation counter. clearInvocations(app); @@ -219,6 +203,8 @@ public class InsetsStateControllerTest extends WindowTestsBase { app.mAttrs.flags &= ~FLAG_NOT_FOCUSABLE; mDisplayContent.computeImeTarget(true); mDisplayContent.applySurfaceChangesTransaction(); + app.mAboveInsetsState.getSource(ITYPE_IME).setVisible(true); + app.mAboveInsetsState.getSource(ITYPE_IME).setFrame(mImeWindow.getFrame()); // Make sure app got notified. verify(app, atLeast(1)).notifyInsetsChanged(); @@ -234,6 +220,8 @@ public class InsetsStateControllerTest extends WindowTestsBase { final WindowState app = createWindow(null, TYPE_APPLICATION, "app"); final WindowState child = createWindow(app, TYPE_APPLICATION, "child"); + app.mAboveInsetsState.set(getController().getRawInsetsState()); + child.mAboveInsetsState.set(getController().getRawInsetsState()); child.mAttrs.flags |= FLAG_ALT_FOCUSABLE_IM; mDisplayContent.computeImeTarget(true); @@ -242,7 +230,8 @@ public class InsetsStateControllerTest extends WindowTestsBase { getController().getRawInsetsState().setSourceVisible(ITYPE_IME, true); assertTrue(getController().getInsetsForWindow(app).getSource(ITYPE_IME).isVisible()); - assertFalse(getController().getInsetsForWindow(child).getSource(ITYPE_IME).isVisible()); + assertFalse(getController().getInsetsForWindow(child).getSource(ITYPE_IME) + .isVisible()); } @UseTestDisplay(addWindows = W_INPUT_METHOD) @@ -252,6 +241,7 @@ public class InsetsStateControllerTest extends WindowTestsBase { final WindowState app = createWindow(null, TYPE_APPLICATION, "app"); final WindowState child = createWindow(app, TYPE_APPLICATION, "child"); + app.mAboveInsetsState.addSource(getController().getRawInsetsState().peekSource(ITYPE_IME)); child.mAttrs.flags |= FLAG_NOT_FOCUSABLE; child.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY); @@ -261,7 +251,8 @@ public class InsetsStateControllerTest extends WindowTestsBase { getController().getRawInsetsState().setSourceVisible(ITYPE_IME, true); assertTrue(getController().getInsetsForWindow(app).getSource(ITYPE_IME).isVisible()); - assertFalse(getController().getInsetsForWindow(child).getSource(ITYPE_IME).isVisible()); + assertFalse(getController().getInsetsForWindow(child).getSource(ITYPE_IME) + .isVisible()); } @Test diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java index 942e1c91989c..bbd89b8d0173 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java @@ -26,6 +26,7 @@ import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; import static android.view.Surface.ROTATION_180; import static android.view.Surface.ROTATION_270; import static android.view.Surface.ROTATION_90; +import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; @@ -480,10 +481,13 @@ public class SizeCompatTests extends WindowTestsBase { /** * Ensures that {@link TaskStackListener} can receive callback about the activity in size * compatibility mode. + * + * TODO(b/178327644) Remove after update DC#handleActivitySizeCompatModeIfNeeded */ @Test public void testHandleActivitySizeCompatMode() { setUpDisplaySizeWithApp(1000, 2000); + doReturn(true).when(mTask).isOrganized(); ActivityRecord activity = mActivity; activity.setState(Task.ActivityState.RESUMED, "testHandleActivitySizeCompatMode"); prepareUnresizable(mActivity, -1.f /* maxAspect */, SCREEN_ORIENTATION_PORTRAIT); @@ -520,6 +524,46 @@ public class SizeCompatTests extends WindowTestsBase { assertEquals(null, compatTokens.get(0)); } + /** + * Ensures that {@link TaskOrganizerController} can receive callback about the activity in size + * compatibility mode. + */ + @Test + public void testHandleActivitySizeCompatModeChanged() { + setUpDisplaySizeWithApp(1000, 2000); + doReturn(true).when(mTask).isOrganized(); + ActivityRecord activity = mActivity; + activity.setState(Task.ActivityState.RESUMED, "testHandleActivitySizeCompatModeChanged"); + prepareUnresizable(mActivity, -1.f /* maxAspect */, SCREEN_ORIENTATION_PORTRAIT); + assertFitted(); + + // Resize the display so that the activity exercises size-compat mode. + resizeDisplay(mTask.mDisplayContent, 1000, 2500); + + // Expect the exact token when the activity is in size compatibility mode. + verify(mTask).onSizeCompatActivityChanged(); + ActivityManager.RunningTaskInfo taskInfo = mTask.getTaskInfo(); + + assertEquals(mActivity.appToken, taskInfo.topActivityToken); + assertTrue(taskInfo.topActivityInSizeCompat); + + // Make the activity resizable again by restarting it + clearInvocations(mTask); + activity.info.resizeMode = RESIZE_MODE_RESIZEABLE; + activity.mVisibleRequested = true; + activity.restartProcessIfVisible(); + // The full lifecycle isn't hooked up so manually set state to resumed + activity.setState(Task.ActivityState.RESUMED, "testHandleActivitySizeCompatModeChanged"); + mTask.mDisplayContent.handleActivitySizeCompatModeIfNeeded(activity); + + // Expect null token when switching to non-size-compat mode activity. + verify(mTask).onSizeCompatActivityChanged(); + taskInfo = mTask.getTaskInfo(); + + assertEquals(mActivity.appToken, taskInfo.topActivityToken); + assertFalse(taskInfo.topActivityInSizeCompat); + } + @Test public void testShouldUseSizeCompatModeOnResizableTask() { setUpDisplaySizeWithApp(1000, 2500); @@ -602,12 +646,11 @@ public class SizeCompatTests extends WindowTestsBase { assertEquals(new Rect(mActivity.getBounds().left, 0, dh - mActivity.getBounds().right, 0), mActivity.getLetterboxInsets()); - final BarController statusBarController = - mActivity.mDisplayContent.getDisplayPolicy().getStatusBarController(); + final DisplayPolicy displayPolicy = mActivity.mDisplayContent.getDisplayPolicy(); // The activity doesn't fill the display, so the letterbox of the rotated activity is // overlapped with the rotated content frame of status bar. Hence the status bar shouldn't // be transparent. - assertFalse(statusBarController.isTransparentAllowed(w)); + assertFalse(displayPolicy.isFullyTransparentAllowed(w, TYPE_STATUS_BAR)); // Make the activity fill the display. prepareUnresizable(mActivity, 10 /* maxAspect */, SCREEN_ORIENTATION_LANDSCAPE); @@ -617,7 +660,7 @@ public class SizeCompatTests extends WindowTestsBase { // The letterbox should only cover the notch area, so status bar can be transparent. assertEquals(new Rect(notchHeight, 0, 0, 0), mActivity.getLetterboxInsets()); - assertTrue(statusBarController.isTransparentAllowed(w)); + assertTrue(displayPolicy.isFullyTransparentAllowed(w, TYPE_STATUS_BAR)); } @Test @@ -977,9 +1020,9 @@ public class SizeCompatTests extends WindowTestsBase { displayPolicy.onConfigurationChanged(); final TestWindowToken token = createTestWindowToken( - WindowManager.LayoutParams.TYPE_STATUS_BAR, displayContent); + TYPE_STATUS_BAR, displayContent); final WindowManager.LayoutParams attrs = - new WindowManager.LayoutParams(WindowManager.LayoutParams.TYPE_STATUS_BAR); + new WindowManager.LayoutParams(TYPE_STATUS_BAR); attrs.gravity = android.view.Gravity.TOP; attrs.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java index 1607f013ee81..a1f89ec75784 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java @@ -275,7 +275,7 @@ public class WindowFrameTests extends WindowTestsBase { imeSource.setFrame(imeFrame); imeSource.setVisible(true); w.updateRequestedVisibility(state); - w.mBehindIme = true; + w.mAboveInsetsState.addSource(imeSource); // With no insets or system decor all the frames incoming from PhoneWindowManager // are identical. diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java index 37983b442425..77fca3d2fdeb 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java @@ -42,6 +42,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.times; import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; import static com.android.dx.mockito.inline.extended.ExtendedMockito.when; import static com.android.server.wm.DisplayArea.Type.ABOVE_TASKS; +import static com.android.server.wm.Task.ActivityState.RESUMED; import static com.android.server.wm.WindowContainer.POSITION_TOP; import static com.android.server.wm.WindowContainer.SYNC_STATE_READY; @@ -55,6 +56,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.clearInvocations; import android.app.ActivityManager; import android.app.ActivityManager.RunningTaskInfo; @@ -1244,6 +1246,54 @@ public class WindowOrganizerTests extends WindowTestsBase { assertEquals(splitPrimaryRootTask, activity.getRootTask()); } + @Test + public void testSizeCompatModeChangedOnFirstOrganizedTask() throws RemoteException { + final ITaskOrganizer organizer = registerMockOrganizer(); + final Task rootTask = createStack(); + final Task task = createTask(rootTask); + final ActivityRecord activity = createActivityRecord(rootTask.mDisplayContent, task); + final ArgumentCaptor<RunningTaskInfo> infoCaptor = + ArgumentCaptor.forClass(RunningTaskInfo.class); + + assertTrue(rootTask.isOrganized()); + + spyOn(activity); + doReturn(true).when(activity).inSizeCompatMode(); + doReturn(true).when(activity).isState(RESUMED); + + // Ensure task info show top activity in size compat. + rootTask.onSizeCompatActivityChanged(); + mWm.mAtmService.mTaskOrganizerController.dispatchPendingEvents(); + verify(organizer).onTaskInfoChanged(infoCaptor.capture()); + RunningTaskInfo info = infoCaptor.getValue(); + assertEquals(rootTask.mTaskId, info.taskId); + assertEquals(activity.appToken, info.topActivityToken); + assertTrue(info.topActivityInSizeCompat); + + // Ensure task info show top activity that is not in foreground as not in size compat. + clearInvocations(organizer); + doReturn(false).when(activity).isState(RESUMED); + rootTask.onSizeCompatActivityChanged(); + mWm.mAtmService.mTaskOrganizerController.dispatchPendingEvents(); + verify(organizer).onTaskInfoChanged(infoCaptor.capture()); + info = infoCaptor.getValue(); + assertEquals(rootTask.mTaskId, info.taskId); + assertEquals(activity.appToken, info.topActivityToken); + assertFalse(info.topActivityInSizeCompat); + + // Ensure task info show non size compat top activity as not in size compat. + clearInvocations(organizer); + doReturn(true).when(activity).isState(RESUMED); + doReturn(false).when(activity).inSizeCompatMode(); + rootTask.onSizeCompatActivityChanged(); + mWm.mAtmService.mTaskOrganizerController.dispatchPendingEvents(); + verify(organizer).onTaskInfoChanged(infoCaptor.capture()); + info = infoCaptor.getValue(); + assertEquals(rootTask.mTaskId, info.taskId); + assertEquals(activity.appToken, info.topActivityToken); + assertFalse(info.topActivityInSizeCompat); + } + /** * Verifies that task vanished is called for a specific task. */ diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java index c85991d8f3b2..8b604a32c512 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java @@ -88,8 +88,8 @@ import android.view.WindowManager.DisplayImePolicy; import android.window.ITaskOrganizer; import android.window.StartingWindowInfo; +import com.android.internal.policy.AttributeCache; import com.android.internal.util.ArrayUtils; -import com.android.server.AttributeCache; import org.junit.Before; import org.junit.BeforeClass; diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java index 3815326b6886..0cb1255c6830 100644 --- a/services/usage/java/com/android/server/usage/UsageStatsService.java +++ b/services/usage/java/com/android/server/usage/UsageStatsService.java @@ -79,7 +79,6 @@ import android.util.ArraySet; import android.util.AtomicFile; import android.util.Slog; import android.util.SparseArray; -import android.util.SparseBooleanArray; import android.util.SparseIntArray; import com.android.internal.annotations.VisibleForTesting; @@ -111,6 +110,7 @@ import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Set; +import java.util.concurrent.CopyOnWriteArraySet; /** * A service that collects, aggregates, and persists application usage data. @@ -162,7 +162,7 @@ public class UsageStatsService extends SystemService implements ShortcutServiceInternal mShortcutServiceInternal; private final SparseArray<UserUsageStatsService> mUserState = new SparseArray<>(); - private final SparseBooleanArray mUserUnlockedStates = new SparseBooleanArray(); + private final CopyOnWriteArraySet<Integer> mUserUnlockedStates = new CopyOnWriteArraySet<>(); private final SparseIntArray mUidToKernelCounter = new SparseIntArray(); int mUsageSource; @@ -333,7 +333,7 @@ public class UsageStatsService extends SystemService implements synchronized (mLock) { // User was started but never unlocked so no need to report a user stopped event - if (!mUserUnlockedStates.get(userId)) { + if (!mUserUnlockedStates.contains(userId)) { persistPendingEventsLocked(userId); return; } @@ -346,7 +346,7 @@ public class UsageStatsService extends SystemService implements if (userService != null) { userService.userStopped(); } - mUserUnlockedStates.put(userId, false); + mUserUnlockedStates.remove(userId); mUserState.put(userId, null); // release the service (mainly for GC) } } @@ -360,6 +360,11 @@ public class UsageStatsService extends SystemService implements UsageStatsIdleService.scheduleUpdateMappingsJob(getContext()); } synchronized (mLock) { + // This should be safe to add this early. Other than reportEventOrAddToQueue, every + // other user grabs the lock before accessing + // mUserUnlockedStates. reportEventOrAddToQueue does not depend on anything other than + // mUserUnlockedStates, and the lock will protect the handler. + mUserUnlockedStates.add(userId); // Create a user unlocked event to report final Event unlockEvent = new Event(USER_UNLOCKED, SystemClock.elapsedRealtime()); unlockEvent.mPackage = Event.DEVICE_EVENT_PACKAGE_NAME; @@ -377,7 +382,6 @@ public class UsageStatsService extends SystemService implements initializeUserUsageStatsServiceLocked(userId, System.currentTimeMillis(), installedPackages); - mUserUnlockedStates.put(userId, true); final UserUsageStatsService userService = getUserUsageStatsServiceLocked(userId); if (userService == null) { Slog.i(TAG, "Attempted to unlock stopped or removed user " + userId); @@ -780,12 +784,11 @@ public class UsageStatsService extends SystemService implements } private void reportEventOrAddToQueue(int userId, Event event) { + if (mUserUnlockedStates.contains(userId)) { + mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget(); + return; + } synchronized (mLock) { - if (mUserUnlockedStates.get(userId)) { - mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget(); - return; - } - LinkedList<Event> events = mReportedEvents.get(userId); if (events == null) { events = new LinkedList<>(); @@ -823,7 +826,7 @@ public class UsageStatsService extends SystemService implements synchronized (mLock) { // This should never be called directly when the user is locked - if (!mUserUnlockedStates.get(userId)) { + if (!mUserUnlockedStates.contains(userId)) { Slog.wtf(TAG, "Failed to report event for locked user " + userId + " (" + event.mPackage + "/" + event.mClass + " eventType:" + event.mEventType @@ -1006,7 +1009,7 @@ public class UsageStatsService extends SystemService implements final int tokenRemoved; synchronized (mLock) { final long timeRemoved = System.currentTimeMillis(); - if (!mUserUnlockedStates.get(userId)) { + if (!mUserUnlockedStates.contains(userId)) { // If user is not unlocked and a package is removed for them, we will handle it // when the user service is initialized and package manager is queried. return; @@ -1030,7 +1033,7 @@ public class UsageStatsService extends SystemService implements */ private boolean pruneUninstalledPackagesData(int userId) { synchronized (mLock) { - if (!mUserUnlockedStates.get(userId)) { + if (!mUserUnlockedStates.contains(userId)) { return false; // user is no longer unlocked } @@ -1050,7 +1053,7 @@ public class UsageStatsService extends SystemService implements // fetch the installed packages outside the lock so it doesn't block package manager. final HashMap<String, Long> installedPkgs = getInstalledPackages(UserHandle.USER_SYSTEM); synchronized (mLock) { - if (!mUserUnlockedStates.get(UserHandle.USER_SYSTEM)) { + if (!mUserUnlockedStates.contains(UserHandle.USER_SYSTEM)) { return false; // user is no longer unlocked } @@ -1069,7 +1072,7 @@ public class UsageStatsService extends SystemService implements List<UsageStats> queryUsageStats(int userId, int bucketType, long beginTime, long endTime, boolean obfuscateInstantApps) { synchronized (mLock) { - if (!mUserUnlockedStates.get(userId)) { + if (!mUserUnlockedStates.contains(userId)) { Slog.w(TAG, "Failed to query usage stats for locked user " + userId); return null; } @@ -1103,7 +1106,7 @@ public class UsageStatsService extends SystemService implements List<ConfigurationStats> queryConfigurationStats(int userId, int bucketType, long beginTime, long endTime) { synchronized (mLock) { - if (!mUserUnlockedStates.get(userId)) { + if (!mUserUnlockedStates.contains(userId)) { Slog.w(TAG, "Failed to query configuration stats for locked user " + userId); return null; } @@ -1122,7 +1125,7 @@ public class UsageStatsService extends SystemService implements List<EventStats> queryEventStats(int userId, int bucketType, long beginTime, long endTime) { synchronized (mLock) { - if (!mUserUnlockedStates.get(userId)) { + if (!mUserUnlockedStates.contains(userId)) { Slog.w(TAG, "Failed to query event stats for locked user " + userId); return null; } @@ -1140,7 +1143,7 @@ public class UsageStatsService extends SystemService implements */ UsageEvents queryEvents(int userId, long beginTime, long endTime, int flags) { synchronized (mLock) { - if (!mUserUnlockedStates.get(userId)) { + if (!mUserUnlockedStates.contains(userId)) { Slog.w(TAG, "Failed to query events for locked user " + userId); return null; } @@ -1159,7 +1162,7 @@ public class UsageStatsService extends SystemService implements UsageEvents queryEventsForPackage(int userId, long beginTime, long endTime, String packageName, boolean includeTaskRoot) { synchronized (mLock) { - if (!mUserUnlockedStates.get(userId)) { + if (!mUserUnlockedStates.contains(userId)) { Slog.w(TAG, "Failed to query package events for locked user " + userId); return null; } @@ -1203,7 +1206,7 @@ public class UsageStatsService extends SystemService implements final int userCount = mUserState.size(); for (int i = 0; i < userCount; i++) { final int userId = mUserState.keyAt(i); - if (!mUserUnlockedStates.get(userId)) { + if (!mUserUnlockedStates.contains(userId)) { persistPendingEventsLocked(userId); continue; } @@ -1261,7 +1264,7 @@ public class UsageStatsService extends SystemService implements final int numUsers = mUserState.size(); for (int user = 0; user < numUsers; user++) { final int userId = mUserState.keyAt(user); - if (!mUserUnlockedStates.get(userId)) { + if (!mUserUnlockedStates.contains(userId)) { continue; } ipw.println("user=" + userId); @@ -1288,7 +1291,7 @@ public class UsageStatsService extends SystemService implements final int numUsers = mUserState.size(); for (int user = 0; user < numUsers; user++) { final int userId = mUserState.keyAt(user); - if (!mUserUnlockedStates.get(userId)) { + if (!mUserUnlockedStates.contains(userId)) { continue; } ipw.println("user=" + userId); @@ -1344,7 +1347,7 @@ public class UsageStatsService extends SystemService implements idpw.printPair("user", userId); idpw.println(); idpw.increaseIndent(); - if (mUserUnlockedStates.get(userId)) { + if (mUserUnlockedStates.contains(userId)) { if (checkin) { mUserState.valueAt(i).checkin(idpw); } else { @@ -1382,7 +1385,7 @@ public class UsageStatsService extends SystemService implements ipw.println("the specified user does not exist."); return UserHandle.USER_NULL; } - if (!mUserUnlockedStates.get(userId)) { + if (!mUserUnlockedStates.contains(userId)) { ipw.println("the specified user is currently in a locked state."); return UserHandle.USER_NULL; } @@ -2250,12 +2253,11 @@ public class UsageStatsService extends SystemService implements @Override public byte[] getBackupPayload(int user, String key) { + if (!mUserUnlockedStates.contains(user)) { + Slog.w(TAG, "Failed to get backup payload for locked user " + user); + return null; + } synchronized (mLock) { - if (!mUserUnlockedStates.get(user)) { - Slog.w(TAG, "Failed to get backup payload for locked user " + user); - return null; - } - // Check to ensure that only user 0's data is b/r for now // Note: if backup and restore is enabled for users other than the system user, the // #onUserUnlocked logic, specifically when the update mappings job is scheduled via @@ -2275,7 +2277,7 @@ public class UsageStatsService extends SystemService implements @Override public void applyRestoredPayload(int user, String key, byte[] payload) { synchronized (mLock) { - if (!mUserUnlockedStates.get(user)) { + if (!mUserUnlockedStates.contains(user)) { Slog.w(TAG, "Failed to apply restored payload for locked user " + user); return; } diff --git a/telephony/java/android/telephony/ims/ImsCallProfile.java b/telephony/java/android/telephony/ims/ImsCallProfile.java index 1faae42f054b..a9dae898fc9f 100644 --- a/telephony/java/android/telephony/ims/ImsCallProfile.java +++ b/telephony/java/android/telephony/ims/ImsCallProfile.java @@ -138,6 +138,8 @@ public final class ImsCallProfile implements Parcelable { * Indicates if the session is for a conference call or not. If not defined, should be * considered {@code false}. * Boolean extra properties - {@code true} / {@code false}. + * + * This extra is set on an instance of {@link ImsCallProfile} via {@link #setCallExtraBoolean}. * @hide */ @SystemApi @@ -174,6 +176,8 @@ public final class ImsCallProfile implements Parcelable { * Indicates if the session can be extended to a conference call. If not defined, should be * considered {@code false}. * Boolean extra properties - {@code true} / {@code false}. + * + * This extra is set on an instance of {@link ImsCallProfile} via {@link #setCallExtraBoolean}. * @hide */ @SystemApi diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl index ee6c36ca6b76..d17415a7354a 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -2356,6 +2356,21 @@ interface ITelephony { int removeContactFromEab(int subId, String contacts); /** + * Get the EAB contact from the EAB database. + */ + String getContactFromEab(String contact); + + /* + * Check whether the device supports RCS User Capability Exchange or not. + */ + boolean getDeviceUceEnabled(); + + /* + * Set the device supports RCS User Capability Exchange. + */ + void setDeviceUceEnabled(boolean isEnabled); + + /** * Set a SignalStrengthUpdateRequest to receive notification when Signal Strength breach the * specified thresholds. */ diff --git a/tests/FlickerTests/TEST_MAPPING b/tests/FlickerTests/TEST_MAPPING deleted file mode 100644 index db251b907caa..000000000000 --- a/tests/FlickerTests/TEST_MAPPING +++ /dev/null @@ -1,13 +0,0 @@ -{ - "postsubmit": [ - // Run tests on real device - { - "name": "FlickerTests", - "keywords": ["primary-device"] - }, - // Also run the tests in the cloud - { - "name": "FlickerTests" - } - ] -}
\ No newline at end of file diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt index 1d69fe40cb9f..b5fd4a50ae66 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt @@ -20,7 +20,6 @@ import android.platform.test.annotations.Presubmit import android.view.Surface import androidx.test.filters.RequiresDevice import androidx.test.platform.app.InstrumentationRegistry -import com.android.server.wm.flicker.Flicker import com.android.server.wm.flicker.FlickerTestRunnerFactory import com.android.server.wm.flicker.FlickerTestRunner import com.android.server.wm.flicker.helpers.SimpleAppHelper @@ -56,18 +55,16 @@ import org.junit.runners.Parameterized @RunWith(Parameterized::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) class CloseAppBackButtonTest( - testName: String, - flickerProvider: () -> Flicker, - cleanUp: Boolean -) : FlickerTestRunner(testName, flickerProvider, cleanUp) { + testSpec: FlickerTestRunnerFactory.TestSpec +) : FlickerTestRunner(testSpec) { companion object { @Parameterized.Parameters(name = "{0}") @JvmStatic fun getParams(): List<Array<Any>> { val instrumentation = InstrumentationRegistry.getInstrumentation() val testApp = SimpleAppHelper(instrumentation) - return FlickerTestRunnerFactory(instrumentation, repetitions = 5) - .buildTest { configuration -> + return FlickerTestRunnerFactory.getInstance() + .buildTest(instrumentation, repetitions = 5) { configuration -> withTestName { buildTestTag("closeAppBackButton", configuration) } repeat { configuration.repetitions } setup { diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt index f1d08c216f47..584e4b16fab7 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt @@ -20,7 +20,6 @@ import android.platform.test.annotations.Presubmit import android.view.Surface import androidx.test.filters.RequiresDevice import androidx.test.platform.app.InstrumentationRegistry -import com.android.server.wm.flicker.Flicker import com.android.server.wm.flicker.FlickerTestRunnerFactory import com.android.server.wm.flicker.FlickerTestRunner import com.android.server.wm.flicker.helpers.SimpleAppHelper @@ -55,18 +54,16 @@ import org.junit.runners.Parameterized @RunWith(Parameterized::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) class CloseAppHomeButtonTest( - testName: String, - flickerProvider: () -> Flicker, - cleanUp: Boolean -) : FlickerTestRunner(testName, flickerProvider, cleanUp) { + testSpec: FlickerTestRunnerFactory.TestSpec +) : FlickerTestRunner(testSpec) { companion object { @Parameterized.Parameters(name = "{0}") @JvmStatic fun getParams(): List<Array<Any>> { val instrumentation = InstrumentationRegistry.getInstrumentation() val testApp = SimpleAppHelper(instrumentation) - return FlickerTestRunnerFactory(instrumentation, repetitions = 5) - .buildTest { configuration -> + return FlickerTestRunnerFactory.getInstance() + .buildTest(instrumentation, repetitions = 5) { configuration -> withTestName { buildTestTag("closeAppHomeButton", configuration) } repeat { configuration.repetitions } setup { diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToAppTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToAppTest.kt index d3eefd06fec1..fde97ba8b4df 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToAppTest.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToAppTest.kt @@ -21,7 +21,6 @@ import android.platform.test.annotations.Presubmit import android.view.Surface import androidx.test.filters.RequiresDevice import androidx.test.platform.app.InstrumentationRegistry -import com.android.server.wm.flicker.Flicker import com.android.server.wm.flicker.FlickerTestRunner import com.android.server.wm.flicker.FlickerTestRunnerFactory import com.android.server.wm.flicker.helpers.ImeAppAutoFocusHelper @@ -55,18 +54,16 @@ import org.junit.runners.Parameterized @FixMethodOrder(MethodSorters.NAME_ASCENDING) @FlakyTest(bugId = 178015460) class CloseImeAutoOpenWindowToAppTest( - testName: String, - flickerProvider: () -> Flicker, - cleanUp: Boolean -) : FlickerTestRunner(testName, flickerProvider, cleanUp) { + testSpec: FlickerTestRunnerFactory.TestSpec +) : FlickerTestRunner(testSpec) { companion object { @Parameterized.Parameters(name = "{0}") @JvmStatic fun getParams(): List<Array<Any>> { val instrumentation = InstrumentationRegistry.getInstrumentation() - return FlickerTestRunnerFactory(instrumentation, repetitions = 5) - .buildTest { configuration -> + return FlickerTestRunnerFactory.getInstance() + .buildTest(instrumentation, repetitions = 5) { configuration -> val testApp = ImeAppAutoFocusHelper(instrumentation, configuration.startRotation) withTestName { buildTestTag("imeToAppAutoOpen", configuration) } diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToHomeTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToHomeTest.kt index f5bb8e1bfb14..ab7c08f7902b 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToHomeTest.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToHomeTest.kt @@ -20,7 +20,6 @@ import android.platform.test.annotations.Presubmit import android.view.Surface import androidx.test.filters.RequiresDevice import androidx.test.platform.app.InstrumentationRegistry -import com.android.server.wm.flicker.Flicker import com.android.server.wm.flicker.FlickerTestRunner import com.android.server.wm.flicker.FlickerTestRunnerFactory import com.android.server.wm.flicker.helpers.ImeAppAutoFocusHelper @@ -53,18 +52,16 @@ import org.junit.runners.Parameterized @RunWith(Parameterized::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) class CloseImeAutoOpenWindowToHomeTest( - testName: String, - flickerProvider: () -> Flicker, - cleanUp: Boolean -) : FlickerTestRunner(testName, flickerProvider, cleanUp) { + testSpec: FlickerTestRunnerFactory.TestSpec +) : FlickerTestRunner(testSpec) { companion object { @Parameterized.Parameters(name = "{0}") @JvmStatic fun getParams(): List<Array<Any>> { val instrumentation = InstrumentationRegistry.getInstrumentation() - return FlickerTestRunnerFactory(instrumentation, repetitions = 5) - .buildTest { configuration -> + return FlickerTestRunnerFactory.getInstance() + .buildTest(instrumentation, repetitions = 5) { configuration -> val testApp = ImeAppAutoFocusHelper(instrumentation, configuration.startRotation) withTestName { @@ -114,7 +111,8 @@ class CloseImeAutoOpenWindowToHomeTest( enabled = !configuration.startRotation.isRotated()) statusBarLayerIsAlwaysVisible( enabled = !configuration.startRotation.isRotated()) - visibleLayersShownMoreThanOneConsecutiveEntry(listOf(IME_WINDOW_TITLE)) + visibleLayersShownMoreThanOneConsecutiveEntry(listOf(IME_WINDOW_TITLE), + enabled = !configuration.startRotation.isRotated()) imeLayerBecomesInvisible() imeAppLayerBecomesInvisible(testApp) diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToAppTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToAppTest.kt index a3631926e3e8..0503cce0fbb1 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToAppTest.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToAppTest.kt @@ -21,7 +21,6 @@ import android.platform.test.annotations.Presubmit import android.view.Surface import androidx.test.filters.RequiresDevice import androidx.test.platform.app.InstrumentationRegistry -import com.android.server.wm.flicker.Flicker import com.android.server.wm.flicker.FlickerTestRunner import com.android.server.wm.flicker.FlickerTestRunnerFactory import com.android.server.wm.flicker.helpers.ImeAppHelper @@ -54,10 +53,8 @@ import org.junit.runners.Parameterized @FixMethodOrder(MethodSorters.NAME_ASCENDING) @FlakyTest(bugId = 178015460) class CloseImeWindowToAppTest( - testName: String, - flickerProvider: () -> Flicker, - cleanUp: Boolean -) : FlickerTestRunner(testName, flickerProvider, cleanUp) { + testSpec: FlickerTestRunnerFactory.TestSpec +) : FlickerTestRunner(testSpec) { companion object { @Parameterized.Parameters(name = "{0}") @@ -65,8 +62,8 @@ class CloseImeWindowToAppTest( fun getParams(): List<Array<Any>> { val instrumentation = InstrumentationRegistry.getInstrumentation() val testApp = ImeAppHelper(instrumentation) - return FlickerTestRunnerFactory(instrumentation, repetitions = 5) - .buildTest { configuration -> + return FlickerTestRunnerFactory.getInstance() + .buildTest(instrumentation, repetitions = 5) { configuration -> withTestName { buildTestTag("imeToApp", configuration) } repeat { configuration.repetitions } setup { diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTest.kt index f474ec2c389c..9cb075b8a0bd 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTest.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTest.kt @@ -21,7 +21,6 @@ import android.platform.test.annotations.Presubmit import android.view.Surface import androidx.test.filters.RequiresDevice import androidx.test.platform.app.InstrumentationRegistry -import com.android.server.wm.flicker.Flicker import com.android.server.wm.flicker.FlickerTestRunner import com.android.server.wm.flicker.FlickerTestRunnerFactory import com.android.server.wm.flicker.helpers.ImeAppHelper @@ -54,18 +53,16 @@ import org.junit.runners.Parameterized @FixMethodOrder(MethodSorters.NAME_ASCENDING) @FlakyTest(bugId = 178015460) class CloseImeWindowToHomeTest( - testName: String, - flickerProvider: () -> Flicker, - cleanUp: Boolean -) : FlickerTestRunner(testName, flickerProvider, cleanUp) { + testSpec: FlickerTestRunnerFactory.TestSpec +) : FlickerTestRunner(testSpec) { companion object { @Parameterized.Parameters(name = "{0}") @JvmStatic fun getParams(): List<Array<Any>> { val instrumentation = InstrumentationRegistry.getInstrumentation() val testApp = ImeAppHelper(instrumentation) - return FlickerTestRunnerFactory(instrumentation, repetitions = 5) - .buildTest { configuration -> + return FlickerTestRunnerFactory.getInstance() + .buildTest(instrumentation, repetitions = 5) { configuration -> withTestName { buildTestTag("imeToHome", configuration) } repeat { configuration.repetitions } setup { diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowTest.kt index ff07398305bc..13c6cd7e6e18 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowTest.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowTest.kt @@ -21,7 +21,6 @@ import android.platform.test.annotations.Presubmit import android.view.Surface import androidx.test.filters.RequiresDevice import androidx.test.platform.app.InstrumentationRegistry -import com.android.server.wm.flicker.Flicker import com.android.server.wm.flicker.FlickerTestRunner import com.android.server.wm.flicker.FlickerTestRunnerFactory import com.android.server.wm.flicker.helpers.ImeAppHelper @@ -57,18 +56,16 @@ import org.junit.runners.Parameterized @FixMethodOrder(MethodSorters.NAME_ASCENDING) @FlakyTest(bugId = 178015460) class OpenImeWindowTest( - testName: String, - flickerProvider: () -> Flicker, - cleanUp: Boolean -) : FlickerTestRunner(testName, flickerProvider, cleanUp) { + testSpec: FlickerTestRunnerFactory.TestSpec +) : FlickerTestRunner(testSpec) { companion object { @Parameterized.Parameters(name = "{0}") @JvmStatic fun getParams(): List<Array<Any>> { val instrumentation = InstrumentationRegistry.getInstrumentation() val testApp = ImeAppHelper(instrumentation) - return FlickerTestRunnerFactory(instrumentation, repetitions = 5) - .buildTest { configuration -> + return FlickerTestRunnerFactory.getInstance() + .buildTest(instrumentation, repetitions = 5) { configuration -> withTestName { buildTestTag("openIme", configuration) } repeat { configuration.repetitions } setup { diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt index d2d5960879ec..6cc64dfd8836 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt @@ -20,7 +20,6 @@ import android.platform.test.annotations.Presubmit import android.view.Surface import androidx.test.filters.RequiresDevice import androidx.test.platform.app.InstrumentationRegistry -import com.android.server.wm.flicker.Flicker import com.android.server.wm.flicker.FlickerTestRunner import com.android.server.wm.flicker.FlickerTestRunnerFactory import com.android.server.wm.flicker.helpers.ImeAppAutoFocusHelper @@ -58,18 +57,16 @@ import org.junit.runners.Parameterized @RunWith(Parameterized::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) class ReOpenImeWindowTest( - testName: String, - flickerProvider: () -> Flicker, - cleanUp: Boolean -) : FlickerTestRunner(testName, flickerProvider, cleanUp) { + testSpec: FlickerTestRunnerFactory.TestSpec +) : FlickerTestRunner(testSpec) { companion object { @Parameterized.Parameters(name = "{0}") @JvmStatic fun getParams(): List<Array<Any>> { val instrumentation = InstrumentationRegistry.getInstrumentation() val testAppComponentName = ActivityOptions.IME_ACTIVITY_AUTO_FOCUS_COMPONENT_NAME - return FlickerTestRunnerFactory(instrumentation, repetitions = 1) - .buildTest { configuration -> + return FlickerTestRunnerFactory.getInstance() + .buildTest(instrumentation, repetitions = 1) { configuration -> val testApp = ImeAppAutoFocusHelper(instrumentation, configuration.startRotation) withTestName { buildTestTag("reOpenImeAutoFocus", configuration) } @@ -90,7 +87,6 @@ class ReOpenImeWindowTest( transitions { device.reopenAppFromOverview() wmHelper.waitImeWindowShown() - // wmHelper.waitForFullScreenApp(testAppComponentName) } teardown { test { diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt index cf259876c409..010ebf2c2788 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt @@ -20,7 +20,6 @@ import android.platform.test.annotations.Presubmit import android.view.Surface import androidx.test.filters.RequiresDevice import androidx.test.platform.app.InstrumentationRegistry -import com.android.server.wm.flicker.Flicker import com.android.server.wm.flicker.FlickerTestRunnerFactory import com.android.server.wm.flicker.FlickerTestRunner import com.android.server.wm.flicker.endRotation @@ -57,18 +56,16 @@ import org.junit.runners.Parameterized @RunWith(Parameterized::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) class OpenAppColdTest( - testName: String, - flickerProvider: () -> Flicker, - cleanUp: Boolean -) : FlickerTestRunner(testName, flickerProvider, cleanUp) { + testSpec: FlickerTestRunnerFactory.TestSpec +) : FlickerTestRunner(testSpec) { companion object { @Parameterized.Parameters(name = "{0}") @JvmStatic fun getParams(): List<Array<Any>> { val instrumentation = InstrumentationRegistry.getInstrumentation() val testApp = SimpleAppHelper(instrumentation) - return FlickerTestRunnerFactory(instrumentation) - .buildTest { configuration -> + return FlickerTestRunnerFactory.getInstance() + .buildTest(instrumentation) { configuration -> withTestName { buildTestTag("openAppCold", testApp, configuration) } repeat { configuration.repetitions } setup { diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt index c957b3ff2d4a..5e08921c2253 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt @@ -20,7 +20,6 @@ import android.platform.test.annotations.Presubmit import android.view.Surface import androidx.test.filters.RequiresDevice import androidx.test.platform.app.InstrumentationRegistry -import com.android.server.wm.flicker.Flicker import com.android.server.wm.flicker.FlickerTestRunnerFactory import com.android.server.wm.flicker.FlickerTestRunner import com.android.server.wm.flicker.endRotation @@ -58,18 +57,16 @@ import org.junit.runners.Parameterized @RunWith(Parameterized::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) class OpenAppFromOverviewTest( - testName: String, - flickerProvider: () -> Flicker, - cleanUp: Boolean -) : FlickerTestRunner(testName, flickerProvider, cleanUp) { + testSpec: FlickerTestRunnerFactory.TestSpec +) : FlickerTestRunner(testSpec) { companion object { @Parameterized.Parameters(name = "{0}") @JvmStatic fun getParams(): List<Array<Any>> { val instrumentation = InstrumentationRegistry.getInstrumentation() val testApp = SimpleAppHelper(instrumentation) - return FlickerTestRunnerFactory(instrumentation, repetitions = 5) - .buildTest { configuration -> + return FlickerTestRunnerFactory.getInstance() + .buildTest(instrumentation, repetitions = 5) { configuration -> withTestName { buildTestTag("openAppFromOverview", configuration) } repeat { configuration.repetitions } setup { @@ -118,7 +115,7 @@ class OpenAppFromOverviewTest( navBarLayerIsAlwaysVisible( enabled = Surface.ROTATION_0 == configuration.endRotation) visibleLayersShownMoreThanOneConsecutiveEntry( - enabled = Surface.ROTATION_0 == configuration.endRotation) + enabled = false) appLayerReplacesWallpaperLayer(testApp.`package`) } diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt index fd99be273dda..092cd4d2dad6 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt @@ -20,7 +20,6 @@ import android.platform.test.annotations.Presubmit import android.view.Surface import androidx.test.filters.RequiresDevice import androidx.test.platform.app.InstrumentationRegistry -import com.android.server.wm.flicker.Flicker import com.android.server.wm.flicker.FlickerTestRunnerFactory import com.android.server.wm.flicker.FlickerTestRunner import com.android.server.wm.flicker.endRotation @@ -56,19 +55,15 @@ import org.junit.runners.Parameterized @RequiresDevice @RunWith(Parameterized::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) -class OpenAppWarmTest( - testName: String, - flickerProvider: () -> Flicker, - cleanUp: Boolean -) : FlickerTestRunner(testName, flickerProvider, cleanUp) { +class OpenAppWarmTest(testSpec: FlickerTestRunnerFactory.TestSpec) : FlickerTestRunner(testSpec) { companion object { @Parameterized.Parameters(name = "{0}") @JvmStatic fun getParams(): List<Array<Any>> { val instrumentation = InstrumentationRegistry.getInstrumentation() val testApp = SimpleAppHelper(instrumentation) - return FlickerTestRunnerFactory(instrumentation) - .buildTest { configuration -> + return FlickerTestRunnerFactory.getInstance() + .buildTest(instrumentation) { configuration -> withTestName { buildTestTag("openAppWarm", testApp, configuration) } repeat { configuration.repetitions } setup { diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt index fe3ab041aa0b..1c44b21c0f9a 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt @@ -20,7 +20,6 @@ import android.os.Bundle import android.platform.test.annotations.Presubmit import androidx.test.filters.RequiresDevice import androidx.test.platform.app.InstrumentationRegistry -import com.android.server.wm.flicker.Flicker import com.android.server.wm.flicker.FlickerTestRunner import com.android.server.wm.flicker.FlickerTestRunnerFactory import com.android.server.wm.flicker.dsl.FlickerBuilder @@ -54,10 +53,8 @@ import org.junit.runners.Parameterized @RunWith(Parameterized::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) class ChangeAppRotationTest( - testName: String, - flickerProvider: () -> Flicker, - cleanUp: Boolean -) : FlickerTestRunner(testName, flickerProvider, cleanUp) { + testSpec: FlickerTestRunnerFactory.TestSpec +) : FlickerTestRunner(testSpec) { companion object : RotationTransition(InstrumentationRegistry.getInstrumentation()) { override val testApp: StandardAppHelper get() = SimpleAppHelper(instrumentation) @@ -66,7 +63,7 @@ class ChangeAppRotationTest( private const val SCREENSHOT_LAYER = "RotationLayer" - @Parameterized.Parameters(name = "{0}") + @Parameterized.Parameters(name = "{0}1}") @JvmStatic fun getParams(): Collection<Array<Any>> { val testSpec: FlickerBuilder.(Bundle) -> Unit = { configuration -> @@ -119,8 +116,8 @@ class ChangeAppRotationTest( } } - return FlickerTestRunnerFactory(instrumentation, repetitions = 5) - .buildRotationTest(transition, testSpec) + return FlickerTestRunnerFactory.getInstance() + .buildRotationTest(instrumentation, transition, testSpec, repetitions = 5) } } }
\ No newline at end of file diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt index e25c734b22c6..f04131b64cd4 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt @@ -20,7 +20,6 @@ import android.os.Bundle import android.platform.test.annotations.Presubmit import androidx.test.filters.RequiresDevice import androidx.test.platform.app.InstrumentationRegistry -import com.android.server.wm.flicker.Flicker import com.android.server.wm.flicker.FlickerTestRunner import com.android.server.wm.flicker.FlickerTestRunnerFactory import com.android.server.wm.flicker.endRotation @@ -32,7 +31,6 @@ import com.android.server.wm.flicker.helpers.StandardAppHelper import com.android.server.wm.flicker.layerAlwaysVisible import com.android.server.wm.flicker.helpers.WindowUtils import com.android.server.wm.flicker.helpers.buildTestTag -import com.android.server.wm.flicker.helpers.isRotated import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible import com.android.server.wm.flicker.navBarLayerRotatesAndScales import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible @@ -58,10 +56,8 @@ import org.junit.runners.Parameterized @RunWith(Parameterized::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) class SeamlessAppRotationTest( - testName: String, - flickerProvider: () -> Flicker, - cleanUp: Boolean -) : FlickerTestRunner(testName, flickerProvider, cleanUp) { + testSpec: FlickerTestRunnerFactory.TestSpec +) : FlickerTestRunner(testSpec) { companion object : RotationTransition(InstrumentationRegistry.getInstrumentation()) { override val testApp: StandardAppHelper get() = SeamlessRotationAppHelper(instrumentation) @@ -70,6 +66,8 @@ class SeamlessAppRotationTest( ActivityOptions.EXTRA_STARVE_UI_THREAD to configuration.starveUiThread.toString() ) + private val testFactory = FlickerTestRunnerFactory.getInstance() + private val Bundle.starveUiThread get() = this.getBoolean(ActivityOptions.EXTRA_STARVE_UI_THREAD, false) @@ -80,8 +78,8 @@ class SeamlessAppRotationTest( } @JvmStatic - private fun FlickerTestRunnerFactory.getConfigurations(): List<Bundle> { - return this.getConfigRotationTests().flatMap { + private fun getConfigurations(): List<Bundle> { + return testFactory.getConfigRotationTests().flatMap { val defaultRun = it.createConfig(starveUiThread = false) val busyUiRun = it.createConfig(starveUiThread = true) listOf(defaultRun, busyUiRun) @@ -91,8 +89,7 @@ class SeamlessAppRotationTest( @Parameterized.Parameters(name = "{0}") @JvmStatic fun getParams(): Collection<Array<Any>> { - val factory = FlickerTestRunnerFactory(instrumentation, repetitions = 2) - val configurations = factory.getConfigurations() + val configurations = getConfigurations() val testSpec: FlickerBuilder.(Bundle) -> Unit = { configuration -> withTestName { val extra = if (configuration.starveUiThread) { @@ -161,7 +158,8 @@ class SeamlessAppRotationTest( } } - return factory.buildRotationTest(transition, testSpec, configurations) + return testFactory.buildRotationTest(instrumentation, transition, testSpec, + deviceConfigurations = configurations, repetitions = 2) } } }
\ No newline at end of file diff --git a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java index 104758de49f1..5381009fdf2b 100644 --- a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java +++ b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java @@ -98,6 +98,8 @@ public class PackageWatchdogTest { private final TestClock mTestClock = new TestClock(); private TestLooper mTestLooper; private Context mSpyContext; + // Keep track of all created watchdogs to apply device config changes + private List<PackageWatchdog> mAllocatedWatchdogs; @Mock private ConnectivityModuleConnector mConnectivityModuleConnector; @Mock @@ -112,7 +114,8 @@ public class PackageWatchdogTest { MockitoAnnotations.initMocks(this); new File(InstrumentationRegistry.getContext().getFilesDir(), "package-watchdog.xml").delete(); - adoptShellPermissions(Manifest.permission.READ_DEVICE_CONFIG); + adoptShellPermissions(Manifest.permission.READ_DEVICE_CONFIG, + Manifest.permission.WRITE_DEVICE_CONFIG); mTestLooper = new TestLooper(); mSpyContext = spy(InstrumentationRegistry.getContext()); when(mSpyContext.getPackageManager()).thenReturn(mMockPackageManager); @@ -157,12 +160,23 @@ public class PackageWatchdogTest { return storedValue == null ? defaultValue : Long.parseLong(storedValue); } ).when(() -> SystemProperties.getLong(anyString(), anyLong())); + + DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK, + PackageWatchdog.PROPERTY_WATCHDOG_EXPLICIT_HEALTH_CHECK_ENABLED, + Boolean.toString(true), false); + + DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK, + PackageWatchdog.PROPERTY_WATCHDOG_TRIGGER_FAILURE_COUNT, + Integer.toString(PackageWatchdog.DEFAULT_TRIGGER_FAILURE_COUNT), false); + + mAllocatedWatchdogs = new ArrayList<>(); } @After public void tearDown() throws Exception { dropShellPermissions(); mSession.finishMocking(); + mAllocatedWatchdogs.clear(); } @Test @@ -611,10 +625,6 @@ public class PackageWatchdogTest { */ @Test public void testExplicitHealthCheckStateChanges() throws Exception { - adoptShellPermissions( - Manifest.permission.WRITE_DEVICE_CONFIG, - Manifest.permission.READ_DEVICE_CONFIG); - TestController controller = new TestController(); PackageWatchdog watchdog = createWatchdog(controller, true /* withPackagesReady */); TestObserver observer = new TestObserver(OBSERVER_NAME_1, @@ -807,9 +817,6 @@ public class PackageWatchdogTest { /** Test default values are used when device property is invalid. */ @Test public void testInvalidConfig_watchdogTriggerFailureCount() { - adoptShellPermissions( - Manifest.permission.WRITE_DEVICE_CONFIG, - Manifest.permission.READ_DEVICE_CONFIG); DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK, PackageWatchdog.PROPERTY_WATCHDOG_TRIGGER_FAILURE_COUNT, Integer.toString(-1), /*makeDefault*/false); @@ -835,9 +842,6 @@ public class PackageWatchdogTest { /** Test default values are used when device property is invalid. */ @Test public void testInvalidConfig_watchdogTriggerDurationMillis() { - adoptShellPermissions( - Manifest.permission.WRITE_DEVICE_CONFIG, - Manifest.permission.READ_DEVICE_CONFIG); DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK, PackageWatchdog.PROPERTY_WATCHDOG_TRIGGER_FAILURE_COUNT, Integer.toString(2), /*makeDefault*/false); @@ -850,7 +854,6 @@ public class PackageWatchdogTest { watchdog.startObservingHealth(observer, Arrays.asList(APP_A, APP_B), Long.MAX_VALUE); watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)), PackageWatchdog.FAILURE_REASON_UNKNOWN); - mTestLooper.dispatchAll(); moveTimeForwardAndDispatch(PackageWatchdog.DEFAULT_TRIGGER_FAILURE_DURATION_MS + 1); watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)), PackageWatchdog.FAILURE_REASON_UNKNOWN); @@ -862,7 +865,6 @@ public class PackageWatchdogTest { watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_B, VERSION_CODE)), PackageWatchdog.FAILURE_REASON_UNKNOWN); - mTestLooper.dispatchAll(); moveTimeForwardAndDispatch(PackageWatchdog.DEFAULT_TRIGGER_FAILURE_DURATION_MS - 1); watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_B, VERSION_CODE)), PackageWatchdog.FAILURE_REASON_UNKNOWN); @@ -917,9 +919,6 @@ public class PackageWatchdogTest { /** Test we are notified when enough failures are triggered within any window. */ @Test public void testFailureTriggerWindow() { - adoptShellPermissions( - Manifest.permission.WRITE_DEVICE_CONFIG, - Manifest.permission.READ_DEVICE_CONFIG); DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK, PackageWatchdog.PROPERTY_WATCHDOG_TRIGGER_FAILURE_COUNT, Integer.toString(3), /*makeDefault*/false); @@ -933,11 +932,9 @@ public class PackageWatchdogTest { // Raise 2 failures at t=0 and t=900 respectively watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)), PackageWatchdog.FAILURE_REASON_UNKNOWN); - mTestLooper.dispatchAll(); moveTimeForwardAndDispatch(900); watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)), PackageWatchdog.FAILURE_REASON_UNKNOWN); - mTestLooper.dispatchAll(); // Raise 2 failures at t=1100 moveTimeForwardAndDispatch(200); @@ -1303,15 +1300,15 @@ public class PackageWatchdogTest { DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK, PackageWatchdog.PROPERTY_WATCHDOG_EXPLICIT_HEALTH_CHECK_ENABLED, Boolean.toString(enabled), /*makeDefault*/false); - //give time for DeviceConfig to broadcast the property value change - try { - Thread.sleep(SHORT_DURATION); - } catch (InterruptedException e) { - fail("Thread.sleep unexpectedly failed!"); + // Call updateConfigs() so device config changes take effect immediately + for (PackageWatchdog watchdog : mAllocatedWatchdogs) { + watchdog.updateConfigs(); } } private void moveTimeForwardAndDispatch(long milliSeconds) { + // Exhaust all due runnables now which shouldn't be executed after time-leap + mTestLooper.dispatchAll(); mTestClock.moveTimeForward(milliSeconds); mTestLooper.moveTimeForward(milliSeconds); mTestLooper.dispatchAll(); @@ -1354,6 +1351,7 @@ public class PackageWatchdogTest { verify(mConnectivityModuleConnector).registerHealthListener( mConnectivityModuleCallbackCaptor.capture()); } + mAllocatedWatchdogs.add(watchdog); return watchdog; } diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java index 0db2b2af7260..7b2a07fd80f8 100644 --- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java +++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java @@ -1225,4 +1225,44 @@ public class RollbackTest { InstallUtils.dropShellPermissionIdentity(); } } + + /** + * Tests an app can be rolled back to the previous signing key. + * + * <p>The rollback capability in the signing lineage allows an app to be updated to an APK + * signed with a previous signing key in the lineage; however this often defeats the purpose + * of key rotation as a compromised key could then be used to roll an app back to the previous + * key. To avoid requiring the rollback capability to support app rollbacks the PackageManager + * allows an app to be rolled back to the previous signing key if the rollback install reason + * is set. + */ + @Test + public void testRollbackAfterKeyRotation() throws Exception { + try { + InstallUtils.adoptShellPermissionIdentity( + Manifest.permission.INSTALL_PACKAGES, + Manifest.permission.DELETE_PACKAGES, + Manifest.permission.TEST_MANAGE_ROLLBACKS, + Manifest.permission.MANAGE_ROLLBACKS); + + // Uninstall TestApp.A + Uninstall.packages(TestApp.A); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(-1); + + // Install v1 of the app with the original signing key (without rollbacks enabled). + Install.single(TestApp.AOriginal1).commit(); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1); + + // Upgrade from v1 to v2 with the rotated signing key, with rollbacks enabled. + Install.single(TestApp.ARotated2).setEnableRollback().commit(); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2); + + // Roll back the app. + RollbackInfo available = waitForAvailableRollback(TestApp.A); + RollbackUtils.rollback(available.getRollbackId()); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1); + } finally { + InstallUtils.dropShellPermissionIdentity(); + } + } } diff --git a/tests/UsbTests/src/com/android/server/usb/UsbHandlerTest.java b/tests/UsbTests/src/com/android/server/usb/UsbHandlerTest.java index ef973acf763b..861d221238ff 100644 --- a/tests/UsbTests/src/com/android/server/usb/UsbHandlerTest.java +++ b/tests/UsbTests/src/com/android/server/usb/UsbHandlerTest.java @@ -182,6 +182,24 @@ public class UsbHandlerTest { @SmallTest @Test + public void setFunctionsNcmAndRndis() { + final long rndisPlusNcm = UsbManager.FUNCTION_RNDIS | UsbManager.FUNCTION_NCM; + + mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_SET_CURRENT_FUNCTIONS, + UsbManager.FUNCTION_NCM)); + assertEquals(UsbManager.FUNCTION_NCM, mUsbHandler.getEnabledFunctions() & rndisPlusNcm); + + mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_SET_CURRENT_FUNCTIONS, + rndisPlusNcm)); + assertEquals(rndisPlusNcm, mUsbHandler.getEnabledFunctions() & rndisPlusNcm); + + mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_SET_CURRENT_FUNCTIONS, + UsbManager.FUNCTION_NCM)); + assertEquals(UsbManager.FUNCTION_NCM, mUsbHandler.getEnabledFunctions() & rndisPlusNcm); + } + + @SmallTest + @Test public void enableAdb() { sendBootCompleteMessages(mUsbHandler); Message msg = mUsbHandler.obtainMessage(MSG_ENABLE_ADB); diff --git a/tests/UsbTests/src/com/android/server/usb/UsbManagerNoPermTest.java b/tests/UsbTests/src/com/android/server/usb/UsbManagerNoPermTest.java index a0fd9d40506b..b8bd98ea3f21 100644 --- a/tests/UsbTests/src/com/android/server/usb/UsbManagerNoPermTest.java +++ b/tests/UsbTests/src/com/android/server/usb/UsbManagerNoPermTest.java @@ -16,6 +16,8 @@ package com.android.server.usb; +import static org.junit.Assert.assertEquals; + import android.content.Context; import android.hardware.usb.UsbManager; @@ -23,12 +25,12 @@ import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; +import com.android.server.usblib.UsbManagerTestLib; + import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; -import com.android.server.usblib.UsbManagerTestLib; - /** * Unit tests for {@link android.hardware.usb.UsbManager}. * Note: NOT claimed MANAGE_USB permission in Manifest @@ -78,4 +80,35 @@ public class UsbManagerNoPermTest { public void testUsbApi_SetCurrentFunctions_OnSecurityException() throws Exception { mUsbManagerTestLib.testSetCurrentFunctionsEx(UsbManager.FUNCTION_NONE); } + + public void assertSettableFunctions(boolean settable, long functions) { + assertEquals( + "areSettableFunctions(" + UsbManager.usbFunctionsToString(functions) + "):", + settable, UsbManager.areSettableFunctions(functions)); + } + + /** + * Tests the behaviour of the static areSettableFunctions method. This method performs no IPCs + * and requires no permissions. + */ + @Test + public void testUsbManager_AreSettableFunctions() { + // NONE is settable. + assertSettableFunctions(true, UsbManager.FUNCTION_NONE); + + // MTP, PTP, RNDIS, MIDI, NCM are all settable by themselves. + assertSettableFunctions(true, UsbManager.FUNCTION_MTP); + assertSettableFunctions(true, UsbManager.FUNCTION_PTP); + assertSettableFunctions(true, UsbManager.FUNCTION_RNDIS); + assertSettableFunctions(true, UsbManager.FUNCTION_MIDI); + assertSettableFunctions(true, UsbManager.FUNCTION_NCM); + + // Setting two functions at the same time is not allowed... + assertSettableFunctions(false, UsbManager.FUNCTION_MTP | UsbManager.FUNCTION_PTP); + assertSettableFunctions(false, UsbManager.FUNCTION_PTP | UsbManager.FUNCTION_RNDIS); + assertSettableFunctions(false, UsbManager.FUNCTION_MIDI | UsbManager.FUNCTION_NCM); + + // ... except in the special case of RNDIS and NCM. + assertSettableFunctions(true, UsbManager.FUNCTION_RNDIS | UsbManager.FUNCTION_NCM); + } } diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 14229c5d000f..bf73134952ee 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -380,6 +380,10 @@ public class ConnectivityServiceTest { private QosCallbackMockHelper mQosCallbackMockHelper; private QosCallbackTracker mQosCallbackTracker; + // State variables required to emulate NetworkPolicyManagerService behaviour. + private int mUidRules = RULE_NONE; + private boolean mRestrictBackground = false; + @Mock DeviceIdleInternal mDeviceIdleInternal; @Mock INetworkManagementService mNetworkManagementService; @Mock INetworkStatsService mStatsService; @@ -1278,12 +1282,23 @@ public class ConnectivityServiceTest { } } + private void updateUidNetworkingBlocked() { + doAnswer(i -> NetworkPolicyManagerInternal.isUidNetworkingBlocked( + i.getArgument(0) /* uid */, mUidRules, i.getArgument(1) /* metered */, + mRestrictBackground) + ).when(mNetworkPolicyManager).isUidNetworkingBlocked(anyInt(), anyBoolean()); + } + private void setUidRulesChanged(int uidRules) throws RemoteException { - mPolicyListener.onUidRulesChanged(Process.myUid(), uidRules); + mUidRules = uidRules; + updateUidNetworkingBlocked(); + mPolicyListener.onUidRulesChanged(Process.myUid(), mUidRules); } private void setRestrictBackgroundChanged(boolean restrictBackground) throws RemoteException { - mPolicyListener.onRestrictBackgroundChanged(restrictBackground); + mRestrictBackground = restrictBackground; + updateUidNetworkingBlocked(); + mPolicyListener.onRestrictBackgroundChanged(mRestrictBackground); } private Nat464Xlat getNat464Xlat(NetworkAgentWrapper mna) { @@ -6842,9 +6857,15 @@ public class ConnectivityServiceTest { mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); mCellNetworkAgent.connect(true); cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); + assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); + assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED); + assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED); setUidRulesChanged(RULE_REJECT_ALL); cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent); + assertNull(mCm.getActiveNetwork()); + assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED); + assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED); // ConnectivityService should cache it not to invoke the callback again. setUidRulesChanged(RULE_REJECT_METERED); @@ -6852,32 +6873,60 @@ public class ConnectivityServiceTest { setUidRulesChanged(RULE_NONE); cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent); + assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); + assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED); + assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED); setUidRulesChanged(RULE_REJECT_METERED); cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent); + assertNull(mCm.getActiveNetwork()); + assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED); + assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED); // Restrict the network based on UID rule and NOT_METERED capability change. mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED); cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_METERED, mCellNetworkAgent); cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent); + assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); + assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED); + assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED); + mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED); cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED, mCellNetworkAgent); cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent); + assertNull(mCm.getActiveNetwork()); + assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED); + assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED); + setUidRulesChanged(RULE_ALLOW_METERED); cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent); + assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); + assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED); + assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED); setUidRulesChanged(RULE_NONE); cellNetworkCallback.assertNoCallback(); - // Restrict the network based on BackgroundRestricted. + // Restrict background data. Networking is not blocked because the network is unmetered. setRestrictBackgroundChanged(true); cellNetworkCallback.expectBlockedStatusCallback(true, mCellNetworkAgent); + assertNull(mCm.getActiveNetwork()); + assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED); + assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED); setRestrictBackgroundChanged(true); cellNetworkCallback.assertNoCallback(); - setRestrictBackgroundChanged(false); + + setUidRulesChanged(RULE_ALLOW_METERED); cellNetworkCallback.expectBlockedStatusCallback(false, mCellNetworkAgent); + assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED); + assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED); + + setRestrictBackgroundChanged(false); cellNetworkCallback.assertNoCallback(); + assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); + assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED); + assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED); mCm.unregisterNetworkCallback(cellNetworkCallback); } diff --git a/wifi/java/src/android/net/wifi/nl80211/WifiNl80211Manager.java b/wifi/java/src/android/net/wifi/nl80211/WifiNl80211Manager.java index ef2653204af5..c64f4bc605f1 100644 --- a/wifi/java/src/android/net/wifi/nl80211/WifiNl80211Manager.java +++ b/wifi/java/src/android/net/wifi/nl80211/WifiNl80211Manager.java @@ -20,6 +20,7 @@ import android.annotation.CallbackExecutor; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.annotation.SystemService; import android.app.AlarmManager; @@ -948,8 +949,9 @@ public class WifiNl80211Manager { * has been set up). */ public boolean startScan(@NonNull String ifaceName, @WifiAnnotations.ScanType int scanType, - @Nullable Set<Integer> freqs, @Nullable List<byte[]> hiddenNetworkSSIDs, - @Nullable Bundle extraScanningParams) { + @SuppressLint("NullableCollection") @Nullable Set<Integer> freqs, + @SuppressLint("NullableCollection") @Nullable List<byte[]> hiddenNetworkSSIDs, + @SuppressLint("NullableCollection") @Nullable Bundle extraScanningParams) { IWifiScannerImpl scannerImpl = getScannerImpl(ifaceName); if (scannerImpl == null) { Log.e(TAG, "No valid wificond scanner interface handler for iface=" + ifaceName); |