Merge "Unhide getLockTaskPackages"
diff --git a/Android.mk b/Android.mk
index 1da4783..a1e9ed9 100644
--- a/Android.mk
+++ b/Android.mk
@@ -295,6 +295,10 @@
core/java/android/print/IWriteResultCallback.aidl \
core/java/android/printservice/IPrintService.aidl \
core/java/android/printservice/IPrintServiceClient.aidl \
+ core/java/android/companion/ICompanionDeviceManager.aidl \
+ core/java/android/companion/ICompanionDeviceManagerService.aidl \
+ core/java/android/companion/ICompanionDeviceManagerServiceCallback.aidl \
+ core/java/android/companion/IOnAssociateCallback.aidl \
core/java/android/service/dreams/IDreamManager.aidl \
core/java/android/service/dreams/IDreamService.aidl \
core/java/android/service/persistentdata/IPersistentDataBlockService.aidl \
diff --git a/api/current.txt b/api/current.txt
index 51d5bbd..50f7338 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -2688,11 +2688,25 @@
package android.accessibilityservice {
+ public final class AccessibilityButtonController {
+ method public boolean isAccessibilityButtonAvailable();
+ method public void registerAccessibilityButtonCallback(android.accessibilityservice.AccessibilityButtonController.AccessibilityButtonCallback);
+ method public void registerAccessibilityButtonCallback(android.accessibilityservice.AccessibilityButtonController.AccessibilityButtonCallback, android.os.Handler);
+ method public void unregisterAccessibilityButtonCallback(android.accessibilityservice.AccessibilityButtonController.AccessibilityButtonCallback);
+ }
+
+ public static abstract class AccessibilityButtonController.AccessibilityButtonCallback {
+ ctor public AccessibilityButtonController.AccessibilityButtonCallback();
+ method public void onAvailabilityChanged(android.accessibilityservice.AccessibilityButtonController, boolean);
+ method public void onClicked(android.accessibilityservice.AccessibilityButtonController);
+ }
+
public abstract class AccessibilityService extends android.app.Service {
ctor public AccessibilityService();
method public final void disableSelf();
method public final boolean dispatchGesture(android.accessibilityservice.GestureDescription, android.accessibilityservice.AccessibilityService.GestureResultCallback, android.os.Handler);
method public android.view.accessibility.AccessibilityNodeInfo findFocus(int);
+ method public final android.accessibilityservice.AccessibilityButtonController getAccessibilityButtonController();
method public final android.accessibilityservice.FingerprintGestureController getFingerprintGestureController();
method public final android.accessibilityservice.AccessibilityService.MagnificationController getMagnificationController();
method public android.view.accessibility.AccessibilityNodeInfo getRootInActiveWindow();
@@ -2805,6 +2819,7 @@
field public static final int FLAG_ENABLE_ACCESSIBILITY_VOLUME = 128; // 0x80
field public static final int FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 2; // 0x2
field public static final int FLAG_REPORT_VIEW_IDS = 16; // 0x10
+ field public static final int FLAG_REQUEST_ACCESSIBILITY_BUTTON = 256; // 0x100
field public static final int FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY = 8; // 0x8
field public static final int FLAG_REQUEST_FILTER_KEY_EVENTS = 32; // 0x20
field public static final int FLAG_REQUEST_TOUCH_EXPLORATION_MODE = 4; // 0x4
@@ -5046,14 +5061,19 @@
ctor public Notification(android.os.Parcel);
method public android.app.Notification clone();
method public int describeContents();
+ method public int getBadgeIcon();
method public java.lang.String getChannel();
method public java.lang.String getGroup();
method public android.graphics.drawable.Icon getLargeIcon();
+ method public java.lang.String getShortcutId();
method public android.graphics.drawable.Icon getSmallIcon();
method public java.lang.String getSortKey();
method public long getTimeout();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.media.AudioAttributes AUDIO_ATTRIBUTES_DEFAULT;
+ field public static final int BADGE_ICON_LARGE = 2; // 0x2
+ field public static final int BADGE_ICON_NONE = 0; // 0x0
+ field public static final int BADGE_ICON_SMALL = 1; // 0x1
field public static final java.lang.String CATEGORY_ALARM = "alarm";
field public static final java.lang.String CATEGORY_CALL = "call";
field public static final java.lang.String CATEGORY_EMAIL = "email";
@@ -5145,7 +5165,7 @@
field public deprecated int ledARGB;
field public deprecated int ledOffMS;
field public deprecated int ledOnMS;
- field public deprecated int number;
+ field public int number;
field public deprecated int priority;
field public android.app.Notification publicVersion;
field public deprecated android.net.Uri sound;
@@ -5233,6 +5253,7 @@
method public android.app.Notification.Builder addExtras(android.os.Bundle);
method public android.app.Notification.Builder addPerson(java.lang.String);
method public android.app.Notification build();
+ method public android.app.Notification.Builder chooseBadgeIcon(int);
method public android.widget.RemoteViews createBigContentView();
method public android.widget.RemoteViews createContentView();
method public android.widget.RemoteViews createHeadsUpContentView();
@@ -5265,13 +5286,14 @@
method public android.app.Notification.Builder setLargeIcon(android.graphics.drawable.Icon);
method public deprecated android.app.Notification.Builder setLights(int, int, int);
method public android.app.Notification.Builder setLocalOnly(boolean);
- method public deprecated android.app.Notification.Builder setNumber(int);
+ method public android.app.Notification.Builder setNumber(int);
method public android.app.Notification.Builder setOngoing(boolean);
method public android.app.Notification.Builder setOnlyAlertOnce(boolean);
method public deprecated android.app.Notification.Builder setPriority(int);
method public android.app.Notification.Builder setProgress(int, int, boolean);
method public android.app.Notification.Builder setPublicVersion(android.app.Notification);
method public android.app.Notification.Builder setRemoteInputHistory(java.lang.CharSequence[]);
+ method public android.app.Notification.Builder setShortcutId(java.lang.String);
method public android.app.Notification.Builder setShowWhen(boolean);
method public android.app.Notification.Builder setSmallIcon(int);
method public android.app.Notification.Builder setSmallIcon(int, int);
@@ -7944,6 +7966,65 @@
}
+package android.companion {
+
+ public final class AssociationRequest<F extends android.companion.DeviceFilter> implements android.os.Parcelable {
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.companion.AssociationRequest> CREATOR;
+ }
+
+ public static final class AssociationRequest.Builder<F extends android.companion.DeviceFilter> {
+ method public android.companion.AssociationRequest<F> build();
+ method public static android.companion.AssociationRequest.Builder<android.companion.BluetoothDeviceFilter> createForBluetoothDevice();
+ method public static android.companion.AssociationRequest.Builder<android.companion.BluetoothLEDeviceFilter> createForBluetoothLEDevice();
+ method public android.companion.AssociationRequest.Builder<F> setDeviceFilter(F);
+ method public android.companion.AssociationRequest.Builder<F> setSingleDevice(boolean);
+ }
+
+ public final class BluetoothDeviceFilter implements android.companion.DeviceFilter {
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.companion.BluetoothDeviceFilter> CREATOR;
+ }
+
+ public static final class BluetoothDeviceFilter.Builder {
+ ctor public BluetoothDeviceFilter.Builder();
+ method public android.companion.BluetoothDeviceFilter.Builder addServiceUuid(android.os.ParcelUuid, android.os.ParcelUuid);
+ method public android.companion.BluetoothDeviceFilter build();
+ method public android.companion.BluetoothDeviceFilter.Builder setAddress(java.lang.String);
+ method public android.companion.BluetoothDeviceFilter.Builder setNamePattern(java.util.regex.Pattern);
+ }
+
+ public final class BluetoothLEDeviceFilter implements android.companion.DeviceFilter {
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.companion.BluetoothLEDeviceFilter> CREATOR;
+ }
+
+ public static final class BluetoothLEDeviceFilter.Builder {
+ ctor public BluetoothLEDeviceFilter.Builder();
+ method public android.companion.BluetoothLEDeviceFilter build();
+ method public android.companion.BluetoothLEDeviceFilter.Builder setNamePattern(java.util.regex.Pattern);
+ method public android.companion.BluetoothLEDeviceFilter.Builder setScanFilter(android.bluetooth.le.ScanFilter);
+ }
+
+ public final class CompanionDeviceManager {
+ method public void associate(android.companion.AssociationRequest<?>, android.companion.CompanionDeviceManager.Callback, android.os.Handler);
+ field public static final java.lang.String EXTRA_DEVICE = "android.companion.extra.DEVICE";
+ }
+
+ public static abstract class CompanionDeviceManager.Callback {
+ ctor public CompanionDeviceManager.Callback();
+ method public abstract void onDeviceFound(android.content.IntentSender);
+ method public abstract void onFailure(java.lang.CharSequence);
+ }
+
+ public abstract interface DeviceFilter<D extends android.os.Parcelable> implements android.os.Parcelable {
+ }
+
+}
+
package android.content {
public abstract class AbstractThreadedSyncAdapter {
@@ -8556,6 +8637,7 @@
field public static final java.lang.String CAPTIONING_SERVICE = "captioning";
field public static final java.lang.String CARRIER_CONFIG_SERVICE = "carrier_config";
field public static final java.lang.String CLIPBOARD_SERVICE = "clipboard";
+ field public static final java.lang.String COMPANION_DEVICE_SERVICE = "companion_device";
field public static final java.lang.String CONNECTIVITY_SERVICE = "connectivity";
field public static final java.lang.String CONSUMER_IR_SERVICE = "consumer_ir";
field public static final int CONTEXT_IGNORE_SECURITY = 2; // 0x2
@@ -10332,6 +10414,7 @@
field public static final java.lang.String FEATURE_VERIFIED_BOOT = "android.software.verified_boot";
field public static final java.lang.String FEATURE_VR_MODE = "android.software.vr.mode";
field public static final java.lang.String FEATURE_VR_MODE_HIGH_PERFORMANCE = "android.hardware.vr.high_performance";
+ field public static final java.lang.String FEATURE_VULKAN_HARDWARE_COMPUTE = "android.hardware.vulkan.compute";
field public static final java.lang.String FEATURE_VULKAN_HARDWARE_LEVEL = "android.hardware.vulkan.level";
field public static final java.lang.String FEATURE_VULKAN_HARDWARE_VERSION = "android.hardware.vulkan.version";
field public static final java.lang.String FEATURE_WATCH = "android.hardware.type.watch";
@@ -20448,6 +20531,7 @@
method public int getContentType();
method public int getFlags();
method public int getUsage();
+ method public static int getVolumeControlStream(android.media.AudioAttributes);
method public void writeToParcel(android.os.Parcel, int);
field public static final int CONTENT_TYPE_MOVIE = 3; // 0x3
field public static final int CONTENT_TYPE_MUSIC = 2; // 0x2
@@ -23591,6 +23675,8 @@
public final class MediaController {
ctor public MediaController(android.content.Context, android.media.session.MediaSession.Token);
+ method public void addQueueItem(android.media.MediaDescription);
+ method public void addQueueItem(android.media.MediaDescription, int);
method public void adjustVolume(int, int);
method public boolean dispatchMediaButtonEvent(android.view.KeyEvent);
method public android.os.Bundle getExtras();
@@ -23609,6 +23695,8 @@
method public boolean isShuffleModeEnabled();
method public void registerCallback(android.media.session.MediaController.Callback);
method public void registerCallback(android.media.session.MediaController.Callback, android.os.Handler);
+ method public void removeQueueItem(android.media.MediaDescription);
+ method public void removeQueueItemAt(int);
method public void sendCommand(java.lang.String, android.os.Bundle, android.os.ResultReceiver);
method public void setVolumeTo(int, int);
method public void unregisterCallback(android.media.session.MediaController.Callback);
@@ -23686,11 +23774,14 @@
method public void setSessionActivity(android.app.PendingIntent);
method public void setShuffleModeEnabled(boolean);
field public static final int FLAG_HANDLES_MEDIA_BUTTONS = 1; // 0x1
+ field public static final int FLAG_HANDLES_QUEUE_COMMANDS = 4; // 0x4
field public static final int FLAG_HANDLES_TRANSPORT_CONTROLS = 2; // 0x2
}
public static abstract class MediaSession.Callback {
ctor public MediaSession.Callback();
+ method public void onAddQueueItem(android.media.MediaDescription);
+ method public void onAddQueueItem(android.media.MediaDescription, int);
method public void onCommand(java.lang.String, android.os.Bundle, android.os.ResultReceiver);
method public void onCustomAction(java.lang.String, android.os.Bundle);
method public void onFastForward();
@@ -23704,6 +23795,8 @@
method public void onPrepareFromMediaId(java.lang.String, android.os.Bundle);
method public void onPrepareFromSearch(java.lang.String, android.os.Bundle);
method public void onPrepareFromUri(android.net.Uri, android.os.Bundle);
+ method public void onRemoveQueueItem(android.media.MediaDescription);
+ method public void onRemoveQueueItemAt(int);
method public void onRewind();
method public void onSeekTo(long);
method public void onSetRating(android.media.Rating);
@@ -44357,8 +44450,8 @@
method public void drawableHotspotChanged(float, float);
method protected void drawableStateChanged();
method public android.view.View findFocus();
- method public final <T extends android.view.View> T findViewById(int);
- method public final <T extends android.view.View> T findViewWithTag(java.lang.Object);
+ method public final android.view.View findViewById(int);
+ method public final android.view.View findViewWithTag(java.lang.Object);
method public void findViewsWithText(java.util.ArrayList<android.view.View>, java.lang.CharSequence, int);
method protected deprecated boolean fitSystemWindows(android.graphics.Rect);
method public android.view.View focusSearch(int);
@@ -50537,6 +50630,7 @@
method public void setIs24HourView(java.lang.Boolean);
method public void setMinute(int);
method public void setOnTimeChangedListener(android.widget.TimePicker.OnTimeChangedListener);
+ method public boolean validateInput();
}
public static abstract interface TimePicker.OnTimeChangedListener {
@@ -54231,12 +54325,15 @@
}
public abstract class MethodHandle {
+ method public java.lang.invoke.MethodHandle asCollector(java.lang.Class<?>, int);
method public java.lang.invoke.MethodHandle asFixedArity();
+ method public java.lang.invoke.MethodHandle asSpreader(java.lang.Class<?>, int);
method public java.lang.invoke.MethodHandle asType(java.lang.invoke.MethodType);
method public java.lang.invoke.MethodHandle asVarargsCollector(java.lang.Class<?>);
method public java.lang.invoke.MethodHandle bindTo(java.lang.Object);
method public final java.lang.Object invoke(java.lang.Object...) throws java.lang.Throwable;
method public final java.lang.Object invokeExact(java.lang.Object...) throws java.lang.Throwable;
+ method public java.lang.Object invokeWithArguments(java.lang.Object...) throws java.lang.Throwable;
method public java.lang.Object invokeWithArguments(java.util.List<?>) throws java.lang.Throwable;
method public boolean isVarargsCollector();
method public java.lang.invoke.MethodType type();
@@ -54270,17 +54367,23 @@
method public static java.lang.invoke.MethodHandle arrayElementGetter(java.lang.Class<?>) throws java.lang.IllegalArgumentException;
method public static java.lang.invoke.MethodHandle arrayElementSetter(java.lang.Class<?>) throws java.lang.IllegalArgumentException;
method public static java.lang.invoke.MethodHandle catchException(java.lang.invoke.MethodHandle, java.lang.Class<? extends java.lang.Throwable>, java.lang.invoke.MethodHandle);
+ method public static java.lang.invoke.MethodHandle collectArguments(java.lang.invoke.MethodHandle, int, java.lang.invoke.MethodHandle);
method public static java.lang.invoke.MethodHandle constant(java.lang.Class<?>, java.lang.Object);
method public static java.lang.invoke.MethodHandle dropArguments(java.lang.invoke.MethodHandle, int, java.util.List<java.lang.Class<?>>);
method public static java.lang.invoke.MethodHandle dropArguments(java.lang.invoke.MethodHandle, int, java.lang.Class<?>...);
method public static java.lang.invoke.MethodHandle exactInvoker(java.lang.invoke.MethodType);
+ method public static java.lang.invoke.MethodHandle filterArguments(java.lang.invoke.MethodHandle, int, java.lang.invoke.MethodHandle...);
method public static java.lang.invoke.MethodHandle filterReturnValue(java.lang.invoke.MethodHandle, java.lang.invoke.MethodHandle);
+ method public static java.lang.invoke.MethodHandle foldArguments(java.lang.invoke.MethodHandle, java.lang.invoke.MethodHandle);
method public static java.lang.invoke.MethodHandle guardWithTest(java.lang.invoke.MethodHandle, java.lang.invoke.MethodHandle, java.lang.invoke.MethodHandle);
method public static java.lang.invoke.MethodHandle identity(java.lang.Class<?>);
+ method public static java.lang.invoke.MethodHandle insertArguments(java.lang.invoke.MethodHandle, int, java.lang.Object...);
method public static java.lang.invoke.MethodHandle invoker(java.lang.invoke.MethodType);
method public static java.lang.invoke.MethodHandles.Lookup lookup();
method public static java.lang.invoke.MethodHandle permuteArguments(java.lang.invoke.MethodHandle, java.lang.invoke.MethodType, int...);
method public static java.lang.invoke.MethodHandles.Lookup publicLookup();
+ method public static <T extends java.lang.reflect.Member> T reflectAs(java.lang.Class<T>, java.lang.invoke.MethodHandle);
+ method public static java.lang.invoke.MethodHandle spreadInvoker(java.lang.invoke.MethodType, int);
method public static java.lang.invoke.MethodHandle throwException(java.lang.Class<?>, java.lang.Class<? extends java.lang.Throwable>);
}
@@ -54297,6 +54400,7 @@
method public java.lang.invoke.MethodHandles.Lookup in(java.lang.Class<?>);
method public java.lang.Class<?> lookupClass();
method public int lookupModes();
+ method public java.lang.invoke.MethodHandleInfo revealDirect(java.lang.invoke.MethodHandle);
method public void throwMakeAccessException(java.lang.String, java.lang.Object) throws java.lang.IllegalAccessException;
method public java.lang.invoke.MethodHandle unreflect(java.lang.reflect.Method) throws java.lang.IllegalAccessException;
method public java.lang.invoke.MethodHandle unreflectConstructor(java.lang.reflect.Constructor<?>) throws java.lang.IllegalAccessException;
diff --git a/api/system-current.txt b/api/system-current.txt
index 6a69a80f..e73ad4d 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -2807,11 +2807,25 @@
package android.accessibilityservice {
+ public final class AccessibilityButtonController {
+ method public boolean isAccessibilityButtonAvailable();
+ method public void registerAccessibilityButtonCallback(android.accessibilityservice.AccessibilityButtonController.AccessibilityButtonCallback);
+ method public void registerAccessibilityButtonCallback(android.accessibilityservice.AccessibilityButtonController.AccessibilityButtonCallback, android.os.Handler);
+ method public void unregisterAccessibilityButtonCallback(android.accessibilityservice.AccessibilityButtonController.AccessibilityButtonCallback);
+ }
+
+ public static abstract class AccessibilityButtonController.AccessibilityButtonCallback {
+ ctor public AccessibilityButtonController.AccessibilityButtonCallback();
+ method public void onAvailabilityChanged(android.accessibilityservice.AccessibilityButtonController, boolean);
+ method public void onClicked(android.accessibilityservice.AccessibilityButtonController);
+ }
+
public abstract class AccessibilityService extends android.app.Service {
ctor public AccessibilityService();
method public final void disableSelf();
method public final boolean dispatchGesture(android.accessibilityservice.GestureDescription, android.accessibilityservice.AccessibilityService.GestureResultCallback, android.os.Handler);
method public android.view.accessibility.AccessibilityNodeInfo findFocus(int);
+ method public final android.accessibilityservice.AccessibilityButtonController getAccessibilityButtonController();
method public final android.accessibilityservice.FingerprintGestureController getFingerprintGestureController();
method public final android.accessibilityservice.AccessibilityService.MagnificationController getMagnificationController();
method public android.view.accessibility.AccessibilityNodeInfo getRootInActiveWindow();
@@ -2924,6 +2938,7 @@
field public static final int FLAG_ENABLE_ACCESSIBILITY_VOLUME = 128; // 0x80
field public static final int FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 2; // 0x2
field public static final int FLAG_REPORT_VIEW_IDS = 16; // 0x10
+ field public static final int FLAG_REQUEST_ACCESSIBILITY_BUTTON = 256; // 0x100
field public static final int FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY = 8; // 0x8
field public static final int FLAG_REQUEST_FILTER_KEY_EVENTS = 32; // 0x20
field public static final int FLAG_REQUEST_TOUCH_EXPLORATION_MODE = 4; // 0x4
@@ -5206,15 +5221,20 @@
ctor public Notification(android.os.Parcel);
method public android.app.Notification clone();
method public int describeContents();
+ method public int getBadgeIcon();
method public java.lang.String getChannel();
method public java.lang.String getGroup();
method public android.graphics.drawable.Icon getLargeIcon();
method public static java.lang.Class<? extends android.app.Notification.Style> getNotificationStyleClass(java.lang.String);
+ method public java.lang.String getShortcutId();
method public android.graphics.drawable.Icon getSmallIcon();
method public java.lang.String getSortKey();
method public long getTimeout();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.media.AudioAttributes AUDIO_ATTRIBUTES_DEFAULT;
+ field public static final int BADGE_ICON_LARGE = 2; // 0x2
+ field public static final int BADGE_ICON_NONE = 0; // 0x0
+ field public static final int BADGE_ICON_SMALL = 1; // 0x1
field public static final java.lang.String CATEGORY_ALARM = "alarm";
field public static final java.lang.String CATEGORY_CALL = "call";
field public static final java.lang.String CATEGORY_EMAIL = "email";
@@ -5308,7 +5328,7 @@
field public deprecated int ledARGB;
field public deprecated int ledOffMS;
field public deprecated int ledOnMS;
- field public deprecated int number;
+ field public int number;
field public deprecated int priority;
field public android.app.Notification publicVersion;
field public deprecated android.net.Uri sound;
@@ -5396,6 +5416,7 @@
method public android.app.Notification.Builder addExtras(android.os.Bundle);
method public android.app.Notification.Builder addPerson(java.lang.String);
method public android.app.Notification build();
+ method public android.app.Notification.Builder chooseBadgeIcon(int);
method public android.widget.RemoteViews createBigContentView();
method public android.widget.RemoteViews createContentView();
method public android.widget.RemoteViews createHeadsUpContentView();
@@ -5428,13 +5449,14 @@
method public android.app.Notification.Builder setLargeIcon(android.graphics.drawable.Icon);
method public deprecated android.app.Notification.Builder setLights(int, int, int);
method public android.app.Notification.Builder setLocalOnly(boolean);
- method public deprecated android.app.Notification.Builder setNumber(int);
+ method public android.app.Notification.Builder setNumber(int);
method public android.app.Notification.Builder setOngoing(boolean);
method public android.app.Notification.Builder setOnlyAlertOnce(boolean);
method public deprecated android.app.Notification.Builder setPriority(int);
method public android.app.Notification.Builder setProgress(int, int, boolean);
method public android.app.Notification.Builder setPublicVersion(android.app.Notification);
method public android.app.Notification.Builder setRemoteInputHistory(java.lang.CharSequence[]);
+ method public android.app.Notification.Builder setShortcutId(java.lang.String);
method public android.app.Notification.Builder setShowWhen(boolean);
method public android.app.Notification.Builder setSmallIcon(int);
method public android.app.Notification.Builder setSmallIcon(int, int);
@@ -8334,6 +8356,65 @@
}
+package android.companion {
+
+ public final class AssociationRequest<F extends android.companion.DeviceFilter> implements android.os.Parcelable {
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.companion.AssociationRequest> CREATOR;
+ }
+
+ public static final class AssociationRequest.Builder<F extends android.companion.DeviceFilter> {
+ method public android.companion.AssociationRequest<F> build();
+ method public static android.companion.AssociationRequest.Builder<android.companion.BluetoothDeviceFilter> createForBluetoothDevice();
+ method public static android.companion.AssociationRequest.Builder<android.companion.BluetoothLEDeviceFilter> createForBluetoothLEDevice();
+ method public android.companion.AssociationRequest.Builder<F> setDeviceFilter(F);
+ method public android.companion.AssociationRequest.Builder<F> setSingleDevice(boolean);
+ }
+
+ public final class BluetoothDeviceFilter implements android.companion.DeviceFilter {
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.companion.BluetoothDeviceFilter> CREATOR;
+ }
+
+ public static final class BluetoothDeviceFilter.Builder {
+ ctor public BluetoothDeviceFilter.Builder();
+ method public android.companion.BluetoothDeviceFilter.Builder addServiceUuid(android.os.ParcelUuid, android.os.ParcelUuid);
+ method public android.companion.BluetoothDeviceFilter build();
+ method public android.companion.BluetoothDeviceFilter.Builder setAddress(java.lang.String);
+ method public android.companion.BluetoothDeviceFilter.Builder setNamePattern(java.util.regex.Pattern);
+ }
+
+ public final class BluetoothLEDeviceFilter implements android.companion.DeviceFilter {
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.companion.BluetoothLEDeviceFilter> CREATOR;
+ }
+
+ public static final class BluetoothLEDeviceFilter.Builder {
+ ctor public BluetoothLEDeviceFilter.Builder();
+ method public android.companion.BluetoothLEDeviceFilter build();
+ method public android.companion.BluetoothLEDeviceFilter.Builder setNamePattern(java.util.regex.Pattern);
+ method public android.companion.BluetoothLEDeviceFilter.Builder setScanFilter(android.bluetooth.le.ScanFilter);
+ }
+
+ public final class CompanionDeviceManager {
+ method public void associate(android.companion.AssociationRequest<?>, android.companion.CompanionDeviceManager.Callback, android.os.Handler);
+ field public static final java.lang.String EXTRA_DEVICE = "android.companion.extra.DEVICE";
+ }
+
+ public static abstract class CompanionDeviceManager.Callback {
+ ctor public CompanionDeviceManager.Callback();
+ method public abstract void onDeviceFound(android.content.IntentSender);
+ method public abstract void onFailure(java.lang.CharSequence);
+ }
+
+ public abstract interface DeviceFilter<D extends android.os.Parcelable> implements android.os.Parcelable {
+ }
+
+}
+
package android.content {
public abstract class AbstractThreadedSyncAdapter {
@@ -8953,6 +9034,7 @@
field public static final java.lang.String CAPTIONING_SERVICE = "captioning";
field public static final java.lang.String CARRIER_CONFIG_SERVICE = "carrier_config";
field public static final java.lang.String CLIPBOARD_SERVICE = "clipboard";
+ field public static final java.lang.String COMPANION_DEVICE_SERVICE = "companion_device";
field public static final java.lang.String CONNECTIVITY_SERVICE = "connectivity";
field public static final java.lang.String CONSUMER_IR_SERVICE = "consumer_ir";
field public static final java.lang.String CONTEXTHUB_SERVICE = "contexthub";
@@ -10825,6 +10907,7 @@
field public static final java.lang.String FEATURE_VERIFIED_BOOT = "android.software.verified_boot";
field public static final java.lang.String FEATURE_VR_MODE = "android.software.vr.mode";
field public static final java.lang.String FEATURE_VR_MODE_HIGH_PERFORMANCE = "android.hardware.vr.high_performance";
+ field public static final java.lang.String FEATURE_VULKAN_HARDWARE_COMPUTE = "android.hardware.vulkan.compute";
field public static final java.lang.String FEATURE_VULKAN_HARDWARE_LEVEL = "android.hardware.vulkan.level";
field public static final java.lang.String FEATURE_VULKAN_HARDWARE_VERSION = "android.hardware.vulkan.version";
field public static final java.lang.String FEATURE_WATCH = "android.hardware.type.watch";
@@ -22009,6 +22092,7 @@
method public int getContentType();
method public int getFlags();
method public int getUsage();
+ method public static int getVolumeControlStream(android.media.AudioAttributes);
method public void writeToParcel(android.os.Parcel, int);
field public static final int CONTENT_TYPE_MOVIE = 3; // 0x3
field public static final int CONTENT_TYPE_MUSIC = 2; // 0x2
@@ -25285,6 +25369,8 @@
public final class MediaController {
ctor public MediaController(android.content.Context, android.media.session.MediaSession.Token);
+ method public void addQueueItem(android.media.MediaDescription);
+ method public void addQueueItem(android.media.MediaDescription, int);
method public void adjustVolume(int, int);
method public boolean dispatchMediaButtonEvent(android.view.KeyEvent);
method public android.os.Bundle getExtras();
@@ -25303,6 +25389,8 @@
method public boolean isShuffleModeEnabled();
method public void registerCallback(android.media.session.MediaController.Callback);
method public void registerCallback(android.media.session.MediaController.Callback, android.os.Handler);
+ method public void removeQueueItem(android.media.MediaDescription);
+ method public void removeQueueItemAt(int);
method public void sendCommand(java.lang.String, android.os.Bundle, android.os.ResultReceiver);
method public void setVolumeTo(int, int);
method public void unregisterCallback(android.media.session.MediaController.Callback);
@@ -25380,11 +25468,14 @@
method public void setSessionActivity(android.app.PendingIntent);
method public void setShuffleModeEnabled(boolean);
field public static final int FLAG_HANDLES_MEDIA_BUTTONS = 1; // 0x1
+ field public static final int FLAG_HANDLES_QUEUE_COMMANDS = 4; // 0x4
field public static final int FLAG_HANDLES_TRANSPORT_CONTROLS = 2; // 0x2
}
public static abstract class MediaSession.Callback {
ctor public MediaSession.Callback();
+ method public void onAddQueueItem(android.media.MediaDescription);
+ method public void onAddQueueItem(android.media.MediaDescription, int);
method public void onCommand(java.lang.String, android.os.Bundle, android.os.ResultReceiver);
method public void onCustomAction(java.lang.String, android.os.Bundle);
method public void onFastForward();
@@ -25398,6 +25489,8 @@
method public void onPrepareFromMediaId(java.lang.String, android.os.Bundle);
method public void onPrepareFromSearch(java.lang.String, android.os.Bundle);
method public void onPrepareFromUri(android.net.Uri, android.os.Bundle);
+ method public void onRemoveQueueItem(android.media.MediaDescription);
+ method public void onRemoveQueueItemAt(int);
method public void onRewind();
method public void onSeekTo(long);
method public void onSetRating(android.media.Rating);
@@ -47764,8 +47857,8 @@
method public void drawableHotspotChanged(float, float);
method protected void drawableStateChanged();
method public android.view.View findFocus();
- method public final <T extends android.view.View> T findViewById(int);
- method public final <T extends android.view.View> T findViewWithTag(java.lang.Object);
+ method public final android.view.View findViewById(int);
+ method public final android.view.View findViewWithTag(java.lang.Object);
method public void findViewsWithText(java.util.ArrayList<android.view.View>, java.lang.CharSequence, int);
method protected deprecated boolean fitSystemWindows(android.graphics.Rect);
method public android.view.View focusSearch(int);
@@ -54308,6 +54401,7 @@
method public void setIs24HourView(java.lang.Boolean);
method public void setMinute(int);
method public void setOnTimeChangedListener(android.widget.TimePicker.OnTimeChangedListener);
+ method public boolean validateInput();
}
public static abstract interface TimePicker.OnTimeChangedListener {
@@ -58002,12 +58096,15 @@
}
public abstract class MethodHandle {
+ method public java.lang.invoke.MethodHandle asCollector(java.lang.Class<?>, int);
method public java.lang.invoke.MethodHandle asFixedArity();
+ method public java.lang.invoke.MethodHandle asSpreader(java.lang.Class<?>, int);
method public java.lang.invoke.MethodHandle asType(java.lang.invoke.MethodType);
method public java.lang.invoke.MethodHandle asVarargsCollector(java.lang.Class<?>);
method public java.lang.invoke.MethodHandle bindTo(java.lang.Object);
method public final java.lang.Object invoke(java.lang.Object...) throws java.lang.Throwable;
method public final java.lang.Object invokeExact(java.lang.Object...) throws java.lang.Throwable;
+ method public java.lang.Object invokeWithArguments(java.lang.Object...) throws java.lang.Throwable;
method public java.lang.Object invokeWithArguments(java.util.List<?>) throws java.lang.Throwable;
method public boolean isVarargsCollector();
method public java.lang.invoke.MethodType type();
@@ -58041,17 +58138,23 @@
method public static java.lang.invoke.MethodHandle arrayElementGetter(java.lang.Class<?>) throws java.lang.IllegalArgumentException;
method public static java.lang.invoke.MethodHandle arrayElementSetter(java.lang.Class<?>) throws java.lang.IllegalArgumentException;
method public static java.lang.invoke.MethodHandle catchException(java.lang.invoke.MethodHandle, java.lang.Class<? extends java.lang.Throwable>, java.lang.invoke.MethodHandle);
+ method public static java.lang.invoke.MethodHandle collectArguments(java.lang.invoke.MethodHandle, int, java.lang.invoke.MethodHandle);
method public static java.lang.invoke.MethodHandle constant(java.lang.Class<?>, java.lang.Object);
method public static java.lang.invoke.MethodHandle dropArguments(java.lang.invoke.MethodHandle, int, java.util.List<java.lang.Class<?>>);
method public static java.lang.invoke.MethodHandle dropArguments(java.lang.invoke.MethodHandle, int, java.lang.Class<?>...);
method public static java.lang.invoke.MethodHandle exactInvoker(java.lang.invoke.MethodType);
+ method public static java.lang.invoke.MethodHandle filterArguments(java.lang.invoke.MethodHandle, int, java.lang.invoke.MethodHandle...);
method public static java.lang.invoke.MethodHandle filterReturnValue(java.lang.invoke.MethodHandle, java.lang.invoke.MethodHandle);
+ method public static java.lang.invoke.MethodHandle foldArguments(java.lang.invoke.MethodHandle, java.lang.invoke.MethodHandle);
method public static java.lang.invoke.MethodHandle guardWithTest(java.lang.invoke.MethodHandle, java.lang.invoke.MethodHandle, java.lang.invoke.MethodHandle);
method public static java.lang.invoke.MethodHandle identity(java.lang.Class<?>);
+ method public static java.lang.invoke.MethodHandle insertArguments(java.lang.invoke.MethodHandle, int, java.lang.Object...);
method public static java.lang.invoke.MethodHandle invoker(java.lang.invoke.MethodType);
method public static java.lang.invoke.MethodHandles.Lookup lookup();
method public static java.lang.invoke.MethodHandle permuteArguments(java.lang.invoke.MethodHandle, java.lang.invoke.MethodType, int...);
method public static java.lang.invoke.MethodHandles.Lookup publicLookup();
+ method public static <T extends java.lang.reflect.Member> T reflectAs(java.lang.Class<T>, java.lang.invoke.MethodHandle);
+ method public static java.lang.invoke.MethodHandle spreadInvoker(java.lang.invoke.MethodType, int);
method public static java.lang.invoke.MethodHandle throwException(java.lang.Class<?>, java.lang.Class<? extends java.lang.Throwable>);
}
@@ -58068,6 +58171,7 @@
method public java.lang.invoke.MethodHandles.Lookup in(java.lang.Class<?>);
method public java.lang.Class<?> lookupClass();
method public int lookupModes();
+ method public java.lang.invoke.MethodHandleInfo revealDirect(java.lang.invoke.MethodHandle);
method public void throwMakeAccessException(java.lang.String, java.lang.Object) throws java.lang.IllegalAccessException;
method public java.lang.invoke.MethodHandle unreflect(java.lang.reflect.Method) throws java.lang.IllegalAccessException;
method public java.lang.invoke.MethodHandle unreflectConstructor(java.lang.reflect.Constructor<?>) throws java.lang.IllegalAccessException;
diff --git a/api/test-current.txt b/api/test-current.txt
index e8b2700..3cb21d2 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -2688,11 +2688,25 @@
package android.accessibilityservice {
+ public final class AccessibilityButtonController {
+ method public boolean isAccessibilityButtonAvailable();
+ method public void registerAccessibilityButtonCallback(android.accessibilityservice.AccessibilityButtonController.AccessibilityButtonCallback);
+ method public void registerAccessibilityButtonCallback(android.accessibilityservice.AccessibilityButtonController.AccessibilityButtonCallback, android.os.Handler);
+ method public void unregisterAccessibilityButtonCallback(android.accessibilityservice.AccessibilityButtonController.AccessibilityButtonCallback);
+ }
+
+ public static abstract class AccessibilityButtonController.AccessibilityButtonCallback {
+ ctor public AccessibilityButtonController.AccessibilityButtonCallback();
+ method public void onAvailabilityChanged(android.accessibilityservice.AccessibilityButtonController, boolean);
+ method public void onClicked(android.accessibilityservice.AccessibilityButtonController);
+ }
+
public abstract class AccessibilityService extends android.app.Service {
ctor public AccessibilityService();
method public final void disableSelf();
method public final boolean dispatchGesture(android.accessibilityservice.GestureDescription, android.accessibilityservice.AccessibilityService.GestureResultCallback, android.os.Handler);
method public android.view.accessibility.AccessibilityNodeInfo findFocus(int);
+ method public final android.accessibilityservice.AccessibilityButtonController getAccessibilityButtonController();
method public final android.accessibilityservice.FingerprintGestureController getFingerprintGestureController();
method public final android.accessibilityservice.AccessibilityService.MagnificationController getMagnificationController();
method public android.view.accessibility.AccessibilityNodeInfo getRootInActiveWindow();
@@ -2805,6 +2819,7 @@
field public static final int FLAG_ENABLE_ACCESSIBILITY_VOLUME = 128; // 0x80
field public static final int FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 2; // 0x2
field public static final int FLAG_REPORT_VIEW_IDS = 16; // 0x10
+ field public static final int FLAG_REQUEST_ACCESSIBILITY_BUTTON = 256; // 0x100
field public static final int FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY = 8; // 0x8
field public static final int FLAG_REQUEST_FILTER_KEY_EVENTS = 32; // 0x20
field public static final int FLAG_REQUEST_TOUCH_EXPLORATION_MODE = 4; // 0x4
@@ -5056,14 +5071,19 @@
ctor public Notification(android.os.Parcel);
method public android.app.Notification clone();
method public int describeContents();
+ method public int getBadgeIcon();
method public java.lang.String getChannel();
method public java.lang.String getGroup();
method public android.graphics.drawable.Icon getLargeIcon();
+ method public java.lang.String getShortcutId();
method public android.graphics.drawable.Icon getSmallIcon();
method public java.lang.String getSortKey();
method public long getTimeout();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.media.AudioAttributes AUDIO_ATTRIBUTES_DEFAULT;
+ field public static final int BADGE_ICON_LARGE = 2; // 0x2
+ field public static final int BADGE_ICON_NONE = 0; // 0x0
+ field public static final int BADGE_ICON_SMALL = 1; // 0x1
field public static final java.lang.String CATEGORY_ALARM = "alarm";
field public static final java.lang.String CATEGORY_CALL = "call";
field public static final java.lang.String CATEGORY_EMAIL = "email";
@@ -5155,7 +5175,7 @@
field public deprecated int ledARGB;
field public deprecated int ledOffMS;
field public deprecated int ledOnMS;
- field public deprecated int number;
+ field public int number;
field public deprecated int priority;
field public android.app.Notification publicVersion;
field public deprecated android.net.Uri sound;
@@ -5243,6 +5263,7 @@
method public android.app.Notification.Builder addExtras(android.os.Bundle);
method public android.app.Notification.Builder addPerson(java.lang.String);
method public android.app.Notification build();
+ method public android.app.Notification.Builder chooseBadgeIcon(int);
method public android.widget.RemoteViews createBigContentView();
method public android.widget.RemoteViews createContentView();
method public android.widget.RemoteViews createHeadsUpContentView();
@@ -5275,13 +5296,14 @@
method public android.app.Notification.Builder setLargeIcon(android.graphics.drawable.Icon);
method public deprecated android.app.Notification.Builder setLights(int, int, int);
method public android.app.Notification.Builder setLocalOnly(boolean);
- method public deprecated android.app.Notification.Builder setNumber(int);
+ method public android.app.Notification.Builder setNumber(int);
method public android.app.Notification.Builder setOngoing(boolean);
method public android.app.Notification.Builder setOnlyAlertOnce(boolean);
method public deprecated android.app.Notification.Builder setPriority(int);
method public android.app.Notification.Builder setProgress(int, int, boolean);
method public android.app.Notification.Builder setPublicVersion(android.app.Notification);
method public android.app.Notification.Builder setRemoteInputHistory(java.lang.CharSequence[]);
+ method public android.app.Notification.Builder setShortcutId(java.lang.String);
method public android.app.Notification.Builder setShowWhen(boolean);
method public android.app.Notification.Builder setSmallIcon(int);
method public android.app.Notification.Builder setSmallIcon(int, int);
@@ -7967,6 +7989,65 @@
}
+package android.companion {
+
+ public final class AssociationRequest<F extends android.companion.DeviceFilter> implements android.os.Parcelable {
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.companion.AssociationRequest> CREATOR;
+ }
+
+ public static final class AssociationRequest.Builder<F extends android.companion.DeviceFilter> {
+ method public android.companion.AssociationRequest<F> build();
+ method public static android.companion.AssociationRequest.Builder<android.companion.BluetoothDeviceFilter> createForBluetoothDevice();
+ method public static android.companion.AssociationRequest.Builder<android.companion.BluetoothLEDeviceFilter> createForBluetoothLEDevice();
+ method public android.companion.AssociationRequest.Builder<F> setDeviceFilter(F);
+ method public android.companion.AssociationRequest.Builder<F> setSingleDevice(boolean);
+ }
+
+ public final class BluetoothDeviceFilter implements android.companion.DeviceFilter {
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.companion.BluetoothDeviceFilter> CREATOR;
+ }
+
+ public static final class BluetoothDeviceFilter.Builder {
+ ctor public BluetoothDeviceFilter.Builder();
+ method public android.companion.BluetoothDeviceFilter.Builder addServiceUuid(android.os.ParcelUuid, android.os.ParcelUuid);
+ method public android.companion.BluetoothDeviceFilter build();
+ method public android.companion.BluetoothDeviceFilter.Builder setAddress(java.lang.String);
+ method public android.companion.BluetoothDeviceFilter.Builder setNamePattern(java.util.regex.Pattern);
+ }
+
+ public final class BluetoothLEDeviceFilter implements android.companion.DeviceFilter {
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.companion.BluetoothLEDeviceFilter> CREATOR;
+ }
+
+ public static final class BluetoothLEDeviceFilter.Builder {
+ ctor public BluetoothLEDeviceFilter.Builder();
+ method public android.companion.BluetoothLEDeviceFilter build();
+ method public android.companion.BluetoothLEDeviceFilter.Builder setNamePattern(java.util.regex.Pattern);
+ method public android.companion.BluetoothLEDeviceFilter.Builder setScanFilter(android.bluetooth.le.ScanFilter);
+ }
+
+ public final class CompanionDeviceManager {
+ method public void associate(android.companion.AssociationRequest<?>, android.companion.CompanionDeviceManager.Callback, android.os.Handler);
+ field public static final java.lang.String EXTRA_DEVICE = "android.companion.extra.DEVICE";
+ }
+
+ public static abstract class CompanionDeviceManager.Callback {
+ ctor public CompanionDeviceManager.Callback();
+ method public abstract void onDeviceFound(android.content.IntentSender);
+ method public abstract void onFailure(java.lang.CharSequence);
+ }
+
+ public abstract interface DeviceFilter<D extends android.os.Parcelable> implements android.os.Parcelable {
+ }
+
+}
+
package android.content {
public abstract class AbstractThreadedSyncAdapter {
@@ -8581,6 +8662,7 @@
field public static final java.lang.String CAPTIONING_SERVICE = "captioning";
field public static final java.lang.String CARRIER_CONFIG_SERVICE = "carrier_config";
field public static final java.lang.String CLIPBOARD_SERVICE = "clipboard";
+ field public static final java.lang.String COMPANION_DEVICE_SERVICE = "companion_device";
field public static final java.lang.String CONNECTIVITY_SERVICE = "connectivity";
field public static final java.lang.String CONSUMER_IR_SERVICE = "consumer_ir";
field public static final int CONTEXT_IGNORE_SECURITY = 2; // 0x2
@@ -10364,6 +10446,7 @@
field public static final java.lang.String FEATURE_VERIFIED_BOOT = "android.software.verified_boot";
field public static final java.lang.String FEATURE_VR_MODE = "android.software.vr.mode";
field public static final java.lang.String FEATURE_VR_MODE_HIGH_PERFORMANCE = "android.hardware.vr.high_performance";
+ field public static final java.lang.String FEATURE_VULKAN_HARDWARE_COMPUTE = "android.hardware.vulkan.compute";
field public static final java.lang.String FEATURE_VULKAN_HARDWARE_LEVEL = "android.hardware.vulkan.level";
field public static final java.lang.String FEATURE_VULKAN_HARDWARE_VERSION = "android.hardware.vulkan.version";
field public static final java.lang.String FEATURE_WATCH = "android.hardware.type.watch";
@@ -20540,6 +20623,7 @@
method public int getContentType();
method public int getFlags();
method public int getUsage();
+ method public static int getVolumeControlStream(android.media.AudioAttributes);
method public void writeToParcel(android.os.Parcel, int);
field public static final int CONTENT_TYPE_MOVIE = 3; // 0x3
field public static final int CONTENT_TYPE_MUSIC = 2; // 0x2
@@ -23683,6 +23767,8 @@
public final class MediaController {
ctor public MediaController(android.content.Context, android.media.session.MediaSession.Token);
+ method public void addQueueItem(android.media.MediaDescription);
+ method public void addQueueItem(android.media.MediaDescription, int);
method public void adjustVolume(int, int);
method public boolean dispatchMediaButtonEvent(android.view.KeyEvent);
method public android.os.Bundle getExtras();
@@ -23701,6 +23787,8 @@
method public boolean isShuffleModeEnabled();
method public void registerCallback(android.media.session.MediaController.Callback);
method public void registerCallback(android.media.session.MediaController.Callback, android.os.Handler);
+ method public void removeQueueItem(android.media.MediaDescription);
+ method public void removeQueueItemAt(int);
method public void sendCommand(java.lang.String, android.os.Bundle, android.os.ResultReceiver);
method public void setVolumeTo(int, int);
method public void unregisterCallback(android.media.session.MediaController.Callback);
@@ -23778,11 +23866,14 @@
method public void setSessionActivity(android.app.PendingIntent);
method public void setShuffleModeEnabled(boolean);
field public static final int FLAG_HANDLES_MEDIA_BUTTONS = 1; // 0x1
+ field public static final int FLAG_HANDLES_QUEUE_COMMANDS = 4; // 0x4
field public static final int FLAG_HANDLES_TRANSPORT_CONTROLS = 2; // 0x2
}
public static abstract class MediaSession.Callback {
ctor public MediaSession.Callback();
+ method public void onAddQueueItem(android.media.MediaDescription);
+ method public void onAddQueueItem(android.media.MediaDescription, int);
method public void onCommand(java.lang.String, android.os.Bundle, android.os.ResultReceiver);
method public void onCustomAction(java.lang.String, android.os.Bundle);
method public void onFastForward();
@@ -23796,6 +23887,8 @@
method public void onPrepareFromMediaId(java.lang.String, android.os.Bundle);
method public void onPrepareFromSearch(java.lang.String, android.os.Bundle);
method public void onPrepareFromUri(android.net.Uri, android.os.Bundle);
+ method public void onRemoveQueueItem(android.media.MediaDescription);
+ method public void onRemoveQueueItemAt(int);
method public void onRewind();
method public void onSeekTo(long);
method public void onSetRating(android.media.Rating);
@@ -44663,8 +44756,8 @@
method public void drawableHotspotChanged(float, float);
method protected void drawableStateChanged();
method public android.view.View findFocus();
- method public final <T extends android.view.View> T findViewById(int);
- method public final <T extends android.view.View> T findViewWithTag(java.lang.Object);
+ method public final android.view.View findViewById(int);
+ method public final android.view.View findViewWithTag(java.lang.Object);
method public void findViewsWithText(java.util.ArrayList<android.view.View>, java.lang.CharSequence, int);
method protected deprecated boolean fitSystemWindows(android.graphics.Rect);
method public android.view.View focusSearch(int);
@@ -50862,6 +50955,7 @@
method public void setIs24HourView(java.lang.Boolean);
method public void setMinute(int);
method public void setOnTimeChangedListener(android.widget.TimePicker.OnTimeChangedListener);
+ method public boolean validateInput();
field public static final int MODE_CLOCK = 2; // 0x2
field public static final int MODE_SPINNER = 1; // 0x1
}
@@ -54559,12 +54653,15 @@
}
public abstract class MethodHandle {
+ method public java.lang.invoke.MethodHandle asCollector(java.lang.Class<?>, int);
method public java.lang.invoke.MethodHandle asFixedArity();
+ method public java.lang.invoke.MethodHandle asSpreader(java.lang.Class<?>, int);
method public java.lang.invoke.MethodHandle asType(java.lang.invoke.MethodType);
method public java.lang.invoke.MethodHandle asVarargsCollector(java.lang.Class<?>);
method public java.lang.invoke.MethodHandle bindTo(java.lang.Object);
method public final java.lang.Object invoke(java.lang.Object...) throws java.lang.Throwable;
method public final java.lang.Object invokeExact(java.lang.Object...) throws java.lang.Throwable;
+ method public java.lang.Object invokeWithArguments(java.lang.Object...) throws java.lang.Throwable;
method public java.lang.Object invokeWithArguments(java.util.List<?>) throws java.lang.Throwable;
method public boolean isVarargsCollector();
method public java.lang.invoke.MethodType type();
@@ -54598,17 +54695,23 @@
method public static java.lang.invoke.MethodHandle arrayElementGetter(java.lang.Class<?>) throws java.lang.IllegalArgumentException;
method public static java.lang.invoke.MethodHandle arrayElementSetter(java.lang.Class<?>) throws java.lang.IllegalArgumentException;
method public static java.lang.invoke.MethodHandle catchException(java.lang.invoke.MethodHandle, java.lang.Class<? extends java.lang.Throwable>, java.lang.invoke.MethodHandle);
+ method public static java.lang.invoke.MethodHandle collectArguments(java.lang.invoke.MethodHandle, int, java.lang.invoke.MethodHandle);
method public static java.lang.invoke.MethodHandle constant(java.lang.Class<?>, java.lang.Object);
method public static java.lang.invoke.MethodHandle dropArguments(java.lang.invoke.MethodHandle, int, java.util.List<java.lang.Class<?>>);
method public static java.lang.invoke.MethodHandle dropArguments(java.lang.invoke.MethodHandle, int, java.lang.Class<?>...);
method public static java.lang.invoke.MethodHandle exactInvoker(java.lang.invoke.MethodType);
+ method public static java.lang.invoke.MethodHandle filterArguments(java.lang.invoke.MethodHandle, int, java.lang.invoke.MethodHandle...);
method public static java.lang.invoke.MethodHandle filterReturnValue(java.lang.invoke.MethodHandle, java.lang.invoke.MethodHandle);
+ method public static java.lang.invoke.MethodHandle foldArguments(java.lang.invoke.MethodHandle, java.lang.invoke.MethodHandle);
method public static java.lang.invoke.MethodHandle guardWithTest(java.lang.invoke.MethodHandle, java.lang.invoke.MethodHandle, java.lang.invoke.MethodHandle);
method public static java.lang.invoke.MethodHandle identity(java.lang.Class<?>);
+ method public static java.lang.invoke.MethodHandle insertArguments(java.lang.invoke.MethodHandle, int, java.lang.Object...);
method public static java.lang.invoke.MethodHandle invoker(java.lang.invoke.MethodType);
method public static java.lang.invoke.MethodHandles.Lookup lookup();
method public static java.lang.invoke.MethodHandle permuteArguments(java.lang.invoke.MethodHandle, java.lang.invoke.MethodType, int...);
method public static java.lang.invoke.MethodHandles.Lookup publicLookup();
+ method public static <T extends java.lang.reflect.Member> T reflectAs(java.lang.Class<T>, java.lang.invoke.MethodHandle);
+ method public static java.lang.invoke.MethodHandle spreadInvoker(java.lang.invoke.MethodType, int);
method public static java.lang.invoke.MethodHandle throwException(java.lang.Class<?>, java.lang.Class<? extends java.lang.Throwable>);
}
@@ -54625,6 +54728,7 @@
method public java.lang.invoke.MethodHandles.Lookup in(java.lang.Class<?>);
method public java.lang.Class<?> lookupClass();
method public int lookupModes();
+ method public java.lang.invoke.MethodHandleInfo revealDirect(java.lang.invoke.MethodHandle);
method public void throwMakeAccessException(java.lang.String, java.lang.Object) throws java.lang.IllegalAccessException;
method public java.lang.invoke.MethodHandle unreflect(java.lang.reflect.Method) throws java.lang.IllegalAccessException;
method public java.lang.invoke.MethodHandle unreflectConstructor(java.lang.reflect.Constructor<?>) throws java.lang.IllegalAccessException;
diff --git a/core/java/android/accessibilityservice/AccessibilityButtonController.java b/core/java/android/accessibilityservice/AccessibilityButtonController.java
new file mode 100644
index 0000000..c3a5dab
--- /dev/null
+++ b/core/java/android/accessibilityservice/AccessibilityButtonController.java
@@ -0,0 +1,223 @@
+/*
+ * Copyright (C) 2017 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.accessibilityservice;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Handler;
+import android.os.RemoteException;
+import android.util.ArrayMap;
+import android.util.Slog;
+
+/**
+ * Controller for the accessibility button within the system's navigation area
+ * <p>
+ * This class may be used to query the accessibility button's state and register
+ * callbacks for interactions with and state changes to the accessibility button when
+ * {@link AccessibilityServiceInfo#FLAG_REQUEST_ACCESSIBILITY_BUTTON} is set.
+ * </p>
+ * <p>
+ * <strong>Note:</strong> This class and
+ * {@link AccessibilityServiceInfo#FLAG_REQUEST_ACCESSIBILITY_BUTTON} should not be used as
+ * the sole means for offering functionality to users via an {@link AccessibilityService}.
+ * Some device implementations may choose not to provide a software-rendered system
+ * navigation area, making this affordance permanently unavailable.
+ * </p>
+ * <p>
+ * <strong>Note:</strong> On device implementations where the accessibility button is
+ * supported, it may not be available at all times, such as when a foreground application uses
+ * {@link android.view.View#SYSTEM_UI_FLAG_HIDE_NAVIGATION}. A user may also choose to assign
+ * this button to another accessibility service or feature. In each of these cases, a
+ * registered {@link AccessibilityButtonCallback}'s
+ * {@link AccessibilityButtonCallback#onAvailabilityChanged(AccessibilityButtonController, boolean)}
+ * method will be invoked to provide notifications of changes in the accessibility button's
+ * availability to the registering service.
+ * </p>
+ */
+public final class AccessibilityButtonController {
+ private static final String LOG_TAG = "A11yButtonController";
+
+ private final IAccessibilityServiceConnection mServiceConnection;
+ private final Object mLock;
+ private ArrayMap<AccessibilityButtonCallback, Handler> mCallbacks;
+
+ AccessibilityButtonController(@NonNull IAccessibilityServiceConnection serviceConnection) {
+ mServiceConnection = serviceConnection;
+ mLock = new Object();
+ }
+
+ /**
+ * Retrieves whether the accessibility button in the system's navigation area is
+ * available to the calling service.
+ * <p>
+ * <strong>Note:</strong> If the service is not yet connected (e.g.
+ * {@link AccessibilityService#onServiceConnected()} has not yet been called) or the
+ * service has been disconnected, this method will have no effect and return {@code false}.
+ * </p>
+ *
+ * @return {@code true} if the accessibility button in the system's navigation area is
+ * available to the calling service, {@code false} otherwise
+ */
+ public boolean isAccessibilityButtonAvailable() {
+ try {
+ return mServiceConnection.isAccessibilityButtonAvailable();
+ } catch (RemoteException re) {
+ Slog.w(LOG_TAG, "Failed to get accessibility button availability.", re);
+ re.rethrowFromSystemServer();
+ return false;
+ }
+ }
+
+ /**
+ * Registers the provided {@link AccessibilityButtonCallback} for interaction and state
+ * changes callbacks related to the accessibility button.
+ *
+ * @param callback the callback to add, must be non-null
+ */
+ public void registerAccessibilityButtonCallback(@NonNull AccessibilityButtonCallback callback) {
+ registerAccessibilityButtonCallback(callback, null);
+ }
+
+ /**
+ * Registers the provided {@link AccessibilityButtonCallback} for interaction and state
+ * change callbacks related to the accessibility button. The callback will occur on the
+ * specified {@link Handler}'s thread, or on the services's main thread if the handler is
+ * {@code null}.
+ *
+ * @param callback the callback to add, must be non-null
+ * @param handler the handler on which to callback should execute, or {@code null} to
+ * execute on the service's main thread
+ */
+ public void registerAccessibilityButtonCallback(@NonNull AccessibilityButtonCallback callback,
+ @Nullable Handler handler) {
+ synchronized (mLock) {
+ if (mCallbacks == null) {
+ mCallbacks = new ArrayMap<>();
+ }
+
+ mCallbacks.put(callback, handler);
+ }
+ }
+
+ /**
+ * Unregisters the provided {@link AccessibilityButtonCallback} for interaction and state
+ * change callbacks related to the accessibility button.
+ *
+ * @param callback the callback to remove, must be non-null
+ */
+ public void unregisterAccessibilityButtonCallback(
+ @NonNull AccessibilityButtonCallback callback) {
+ synchronized (mLock) {
+ if (mCallbacks == null) {
+ return;
+ }
+
+ final int keyIndex = mCallbacks.indexOfKey(callback);
+ final boolean hasKey = keyIndex >= 0;
+ if (hasKey) {
+ mCallbacks.removeAt(keyIndex);
+ }
+ }
+ }
+
+ /**
+ * Dispatches the accessibility button click to any registered callbacks. This should
+ * be called on the service's main thread.
+ */
+ void dispatchAccessibilityButtonClicked() {
+ final ArrayMap<AccessibilityButtonCallback, Handler> entries;
+ synchronized (mLock) {
+ if (mCallbacks == null || mCallbacks.isEmpty()) {
+ Slog.w(LOG_TAG, "Received accessibility button click with no callbacks!");
+ return;
+ }
+
+ // Callbacks may remove themselves. Perform a shallow copy to avoid concurrent
+ // modification.
+ entries = new ArrayMap<>(mCallbacks);
+ }
+
+ for (int i = 0, count = entries.size(); i < count; i++) {
+ final AccessibilityButtonCallback callback = entries.keyAt(i);
+ final Handler handler = entries.valueAt(i);
+ if (handler != null) {
+ handler.post(() -> callback.onClicked(this));
+ } else {
+ // We're already on the main thread, just run the callback.
+ callback.onClicked(this);
+ }
+ }
+ }
+
+ /**
+ * Dispatches the accessibility button availability changes to any registered callbacks.
+ * This should be called on the service's main thread.
+ */
+ void dispatchAccessibilityButtonAvailabilityChanged(boolean available) {
+ final ArrayMap<AccessibilityButtonCallback, Handler> entries;
+ synchronized (mLock) {
+ if (mCallbacks == null || mCallbacks.isEmpty()) {
+ Slog.w(LOG_TAG,
+ "Received accessibility button availability change with no callbacks!");
+ return;
+ }
+
+ // Callbacks may remove themselves. Perform a shallow copy to avoid concurrent
+ // modification.
+ entries = new ArrayMap<>(mCallbacks);
+ }
+
+ for (int i = 0, count = entries.size(); i < count; i++) {
+ final AccessibilityButtonCallback callback = entries.keyAt(i);
+ final Handler handler = entries.valueAt(i);
+ if (handler != null) {
+ handler.post(() -> callback.onAvailabilityChanged(this, available));
+ } else {
+ // We're already on the main thread, just run the callback.
+ callback.onAvailabilityChanged(this, available);
+ }
+ }
+ }
+
+ /**
+ * Callback for interaction with and changes to state of the accessibility button
+ * within the system's navigation area.
+ */
+ public static abstract class AccessibilityButtonCallback {
+
+ /**
+ * Called when the accessibility button in the system's navigation area is clicked.
+ *
+ * @param controller the controller used to register for this callback
+ */
+ public void onClicked(AccessibilityButtonController controller) {}
+
+ /**
+ * Called when the availability of the accessibility button in the system's
+ * navigation area has changed. The accessibility button may become unavailable
+ * because the device shopped showing the button, the button was assigned to another
+ * service, or for other reasons.
+ *
+ * @param controller the controller used to register for this callback
+ * @param available {@code true} if the accessibility button is available to this
+ * service, {@code false} otherwise
+ */
+ public void onAvailabilityChanged(AccessibilityButtonController controller,
+ boolean available) {
+ }
+ }
+}
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index a036b6a..9e486d5 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -378,6 +378,8 @@
void onPerformGestureResult(int sequence, boolean completedSuccessfully);
void onFingerprintCapturingGesturesChanged(boolean active);
void onFingerprintGesture(int gesture);
+ void onAccessibilityButtonClicked();
+ void onAccessibilityButtonAvailabilityChanged(boolean available);
}
/**
@@ -400,6 +402,7 @@
private MagnificationController mMagnificationController;
private SoftKeyboardController mSoftKeyboardController;
+ private AccessibilityButtonController mAccessibilityButtonController;
private int mGestureStatusCallbackSequence;
@@ -431,6 +434,9 @@
if (mMagnificationController != null) {
mMagnificationController.onServiceConnected();
}
+ if (mSoftKeyboardController != null) {
+ mSoftKeyboardController.onServiceConnected();
+ }
// The client gets to handle service connection last, after we've set
// up any state upon which their code may rely.
@@ -809,12 +815,10 @@
}
/**
- * Removes all instances of the specified change listener from the list
- * of magnification change listeners.
+ * Removes the specified change listener from the list of magnification change listeners.
*
* @param listener the listener to remove, must be non-null
- * @return {@code true} if at least one instance of the listener was
- * removed
+ * @return {@code true} if the listener was removed, {@code false} otherwise
*/
public boolean removeListener(@NonNull OnMagnificationChangedListener listener) {
if (mListeners == null) {
@@ -1203,11 +1207,11 @@
}
/**
- * Removes all instances of the specified change listener from the list of magnification
- * change listeners.
+ * Removes the specified change listener from the list of keyboard show mode change
+ * listeners.
*
* @param listener the listener to remove, must be non-null
- * @return {@code true} if at least one instance of the listener was removed
+ * @return {@code true} if the listener was removed, {@code false} otherwise
*/
public boolean removeOnShowModeChangedListener(@NonNull OnShowModeChangedListener listener) {
if (mListeners == null) {
@@ -1252,7 +1256,7 @@
final ArrayMap<OnShowModeChangedListener, Handler> entries;
synchronized (mLock) {
if (mListeners == null || mListeners.isEmpty()) {
- Slog.d(LOG_TAG, "Received soft keyboard show mode changed callback"
+ Slog.w(LOG_TAG, "Received soft keyboard show mode changed callback"
+ " with no listeners registered!");
setSoftKeyboardCallbackEnabled(false);
return;
@@ -1308,9 +1312,9 @@
* The lastto this method will be honored, regardless of any previous calls (including those
* made by other AccessibilityServices).
* <p>
- * <strong>Note:</strong> If the service is not yet conected (e.g.
+ * <strong>Note:</strong> If the service is not yet connected (e.g.
* {@link AccessibilityService#onServiceConnected()} has not yet been called) or the
- * service has been disconnected, this method will hav no effect and return {@code false}.
+ * service has been disconnected, this method will have no effect and return {@code false}.
*
* @param showMode the new show mode for the soft keyboard
* @return {@code true} on success
@@ -1349,6 +1353,39 @@
}
/**
+ * Returns the controller for the accessibility button within the system's navigation area.
+ * This instance may be used to query the accessibility button's state and register listeners
+ * for interactions with and state changes for the accessibility button when
+ * {@link AccessibilityServiceInfo#FLAG_REQUEST_ACCESSIBILITY_BUTTON} is set.
+ * <p>
+ * <strong>Note:</strong> Not all devices are capable of displaying the accessibility button
+ * within a navigation area, and as such, use of this class should be considered only as an
+ * optional feature or shortcut on supported device implementations.
+ * </p>
+ *
+ * @return the accessibility button controller for this {@link AccessibilityService}
+ */
+ @NonNull
+ public final AccessibilityButtonController getAccessibilityButtonController() {
+ synchronized (mLock) {
+ if (mAccessibilityButtonController == null) {
+ mAccessibilityButtonController = new AccessibilityButtonController(
+ AccessibilityInteractionClient.getInstance().getConnection(mConnectionId));
+ }
+ return mAccessibilityButtonController;
+ }
+ }
+
+ private void onAccessibilityButtonClicked() {
+ getAccessibilityButtonController().dispatchAccessibilityButtonClicked();
+ }
+
+ private void onAccessibilityButtonAvailabilityChanged(boolean available) {
+ getAccessibilityButtonController().dispatchAccessibilityButtonAvailabilityChanged(
+ available);
+ }
+
+ /**
* Performs a global action. Such an action can be performed
* at any moment regardless of the current application or user
* location in that application. For example going back, going
@@ -1543,6 +1580,16 @@
public void onFingerprintGesture(int gesture) {
AccessibilityService.this.onFingerprintGesture(gesture);
}
+
+ @Override
+ public void onAccessibilityButtonClicked() {
+ AccessibilityService.this.onAccessibilityButtonClicked();
+ }
+
+ @Override
+ public void onAccessibilityButtonAvailabilityChanged(boolean available) {
+ AccessibilityService.this.onAccessibilityButtonAvailabilityChanged(available);
+ }
});
}
@@ -1565,6 +1612,8 @@
private static final int DO_GESTURE_COMPLETE = 9;
private static final int DO_ON_FINGERPRINT_ACTIVE_CHANGED = 10;
private static final int DO_ON_FINGERPRINT_GESTURE = 11;
+ private static final int DO_ACCESSIBILITY_BUTTON_CLICKED = 12;
+ private static final int DO_ACCESSIBILITY_BUTTON_AVAILABILITY_CHANGED = 13;
private final HandlerCaller mCaller;
@@ -1645,6 +1694,17 @@
mCaller.sendMessage(mCaller.obtainMessageI(DO_ON_FINGERPRINT_GESTURE, gesture));
}
+ public void onAccessibilityButtonClicked() {
+ final Message message = mCaller.obtainMessage(DO_ACCESSIBILITY_BUTTON_CLICKED);
+ mCaller.sendMessage(message);
+ }
+
+ public void onAccessibilityButtonAvailabilityChanged(boolean available) {
+ final Message message = mCaller.obtainMessageI(
+ DO_ACCESSIBILITY_BUTTON_AVAILABILITY_CHANGED, (available ? 1 : 0));
+ mCaller.sendMessage(message);
+ }
+
@Override
public void executeMessage(Message message) {
switch (message.what) {
@@ -1750,6 +1810,15 @@
mCallback.onFingerprintGesture(message.arg1);
} return;
+ case (DO_ACCESSIBILITY_BUTTON_CLICKED): {
+ mCallback.onAccessibilityButtonClicked();
+ } return;
+
+ case (DO_ACCESSIBILITY_BUTTON_AVAILABILITY_CHANGED): {
+ final boolean available = (message.arg1 != 0);
+ mCallback.onAccessibilityButtonAvailabilityChanged(available);
+ } return;
+
default :
Log.w(LOG_TAG, "Unknown message type " + message.what);
}
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
index 18e57cb..e135ffd 100644
--- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
+++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
@@ -306,6 +306,12 @@
*/
public static final int FLAG_ENABLE_ACCESSIBILITY_VOLUME = 0x00000080;
+ /**
+ * This flag indicates to the system that the accessibility service requests that an
+ * accessibility button be shown within the system's navigation area, if available.
+ */
+ public static final int FLAG_REQUEST_ACCESSIBILITY_BUTTON = 0x00000100;
+
/**
* This flag requests that all fingerprint gestures be sent to the accessibility service.
* It is handled in {@link FingerprintGestureController}
@@ -396,6 +402,8 @@
* @see #FLAG_REQUEST_FILTER_KEY_EVENTS
* @see #FLAG_REPORT_VIEW_IDS
* @see #FLAG_RETRIEVE_INTERACTIVE_WINDOWS
+ * @see #FLAG_ENABLE_ACCESSIBILITY_VOLUME
+ * @see #FLAG_REQUEST_ACCESSIBILITY_BUTTON
*/
public int flags;
@@ -631,7 +639,7 @@
* @see #CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT
* @see #CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION
* @see #CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY
- * @see #CAPABILITY_FILTER_KEY_EVENTS
+ * @see #CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS
* @see #CAPABILITY_CAN_CONTROL_MAGNIFICATION
* @see #CAPABILITY_CAN_PERFORM_GESTURES
*/
@@ -648,7 +656,7 @@
* @see #CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT
* @see #CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION
* @see #CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY
- * @see #CAPABILITY_FILTER_KEY_EVENTS
+ * @see #CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS
* @see #CAPABILITY_CAN_CONTROL_MAGNIFICATION
* @see #CAPABILITY_CAN_PERFORM_GESTURES
*
@@ -936,6 +944,8 @@
return "FLAG_RETRIEVE_INTERACTIVE_WINDOWS";
case FLAG_ENABLE_ACCESSIBILITY_VOLUME:
return "FLAG_ENABLE_ACCESSIBILITY_VOLUME";
+ case FLAG_REQUEST_ACCESSIBILITY_BUTTON:
+ return "FLAG_REQUEST_ACCESSIBILITY_BUTTON";
case FLAG_CAPTURE_FINGERPRINT_GESTURES:
return "FLAG_CAPTURE_FINGERPRINT_GESTURES";
default:
@@ -960,7 +970,7 @@
case CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY:
return "CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY";
case CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS:
- return "CAPABILITY_CAN_FILTER_KEY_EVENTS";
+ return "CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS";
case CAPABILITY_CAN_CONTROL_MAGNIFICATION:
return "CAPABILITY_CAN_CONTROL_MAGNIFICATION";
case CAPABILITY_CAN_PERFORM_GESTURES:
diff --git a/core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl b/core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl
index 3f778ad..4e96b8f 100644
--- a/core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl
+++ b/core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl
@@ -50,4 +50,8 @@
void onFingerprintCapturingGesturesChanged(boolean capturing);
void onFingerprintGesture(int gesture);
+
+ void onAccessibilityButtonClicked();
+
+ void onAccessibilityButtonAvailabilityChanged(boolean available);
}
diff --git a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
index 5499bd5..5bd37220 100644
--- a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
+++ b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
@@ -88,6 +88,8 @@
void setSoftKeyboardCallbackEnabled(boolean enabled);
+ boolean isAccessibilityButtonAvailable();
+
void sendGesture(int sequence, in ParceledListSlice gestureSteps);
boolean isFingerprintGestureDetectionAvailable();
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 4f68ec7..b7c0737 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -2077,8 +2077,6 @@
} else {
record.trackAddedFragmentsInPop(mTmpAddedFragments);
}
- final int bumpAmount = isPop ? -1 : 1;
- record.bumpBackStackNesting(bumpAmount);
addToBackStack = addToBackStack || record.mAddToBackStack;
}
mTmpAddedFragments.clear();
@@ -2281,8 +2279,10 @@
final BackStackRecord record = records.get(i);
final boolean isPop = isRecordPop.get(i);
if (isPop) {
+ record.bumpBackStackNesting(-1);
record.executePopOps();
} else {
+ record.bumpBackStackNesting(1);
record.executeOps();
}
}
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 2c1cdd6..44e328e 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -28,6 +28,7 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ShortcutInfo;
import android.content.res.ColorStateList;
import android.graphics.Bitmap;
import android.graphics.Canvas;
@@ -223,13 +224,11 @@
* superimposed over the icon in the status bar. Starting with
* {@link android.os.Build.VERSION_CODES#HONEYCOMB}, the template used by
* {@link Notification.Builder} has displayed the number in the expanded notification view.
+ * Starting with {@link android.os.Build.VERSION_CODES#O}, the number may be displayed as a
+ * badge icon in Launchers that support badging.
*
- * If the number is 0 or negative, it is never shown.
- *
- * @deprecated this number is not shown anymore
*/
- @Deprecated
- public int number;
+ public int number = 1;
/**
* The intent to execute when the expanded status entry is clicked. If
@@ -634,9 +633,10 @@
/**
* Special value of {@link #color} used as a place holder for an invalid color.
+ * @hide
*/
@ColorInt
- private static final int COLOR_INVALID = 1;
+ public static final int COLOR_INVALID = 1;
/**
* Sphere of visibility of this notification, which affects how and when the SystemUI reveals
@@ -1074,6 +1074,26 @@
private String mChannelId;
private long mTimeout;
+ private String mShortcutId;
+
+ /**
+ * If this notification is being shown as a badge, always show as a number.
+ */
+ public static final int BADGE_ICON_NONE = 0;
+
+ /**
+ * If this notification is being shown as a badge, use the {@link #getSmallIcon()} to
+ * represent this notification.
+ */
+ public static final int BADGE_ICON_SMALL = 1;
+
+ /**
+ * If this notification is being shown as a badge, use the {@link #getLargeIcon()} to
+ * represent this notification.
+ */
+ public static final int BADGE_ICON_LARGE = 2;
+ private int mBadgeIcon = BADGE_ICON_LARGE;
+
/**
* Structure to encapsulate a named action that can be shown as part of this notification.
* It must include an icon, a label, and a {@link PendingIntent} to be fired when the action is
@@ -1818,6 +1838,12 @@
mChannelId = parcel.readString();
}
mTimeout = parcel.readLong();
+
+ if (parcel.readInt() != 0) {
+ mShortcutId = parcel.readString();
+ }
+
+ mBadgeIcon = parcel.readInt();
}
@Override
@@ -2042,7 +2068,7 @@
}
try {
// IMPORTANT: Add marshaling code in writeToParcelImpl as we
- // want to intercept all pending events written to the pacel.
+ // want to intercept all pending events written to the parcel.
writeToParcelImpl(parcel, flags);
// Must be written last!
parcel.writeArraySet(allPendingIntents);
@@ -2185,6 +2211,15 @@
parcel.writeInt(0);
}
parcel.writeLong(mTimeout);
+
+ if (mShortcutId != null) {
+ parcel.writeInt(1);
+ parcel.writeString(mShortcutId);
+ } else {
+ parcel.writeInt(0);
+ }
+
+ parcel.writeInt(mBadgeIcon);
}
/**
@@ -2382,13 +2417,30 @@
}
/**
- * Returns the time at which this notification should be canceled, if it's not canceled already.
+ * Returns the time at which this notification should be canceled by the system, if it's not
+ * canceled already.
*/
public long getTimeout() {
return mTimeout;
}
/**
+ * Returns what icon should be shown for this notification if it is being displayed in a
+ * Launcher that supports badging. Will be one of {@link #BADGE_ICON_NONE},
+ * {@link #BADGE_ICON_SMALL}, or {@link #BADGE_ICON_LARGE}.
+ */
+ public int getBadgeIcon() {
+ return mBadgeIcon;
+ }
+
+ /**
+ * Returns the {@link ShortcutInfo#getId() id} that this notification supersedes, if any.
+ */
+ public String getShortcutId() {
+ return mShortcutId;
+ }
+
+ /**
* The small icon representing this notification in the status bar and content view.
*
* @return the small icon representing this notification.
@@ -2483,7 +2535,6 @@
private NotificationColorUtil mColorUtil;
private boolean mIsLegacy;
private boolean mIsLegacyInitialized;
- private boolean mColorUtilInited = false;
/**
* Caches a contrast-enhanced version of {@link #mCachedContrastColorIsFor}.
@@ -2601,16 +2652,42 @@
}
private NotificationColorUtil getColorUtil() {
- if (!mColorUtilInited) {
- mColorUtilInited = true;
- if (isLegacy() || isColorized()) {
- mColorUtil = NotificationColorUtil.getInstance(mContext);
- }
+ if (mColorUtil == null) {
+ mColorUtil = NotificationColorUtil.getInstance(mContext);
}
return mColorUtil;
}
/**
+ * If this notification is duplicative of a Launcher shortcut, sets the
+ * {@link ShortcutInfo#getId() id} of the shortcut, in case the Launcher wants to hide
+ * the shortcut.
+ *
+ * This field will be ignored by Launchers that don't support badging or
+ * {@link android.content.pm.ShortcutManager shortcuts}.
+ *
+ * @param shortcutId the {@link ShortcutInfo#getId() id} of the shortcut this notification
+ * supersedes
+ */
+ public Builder setShortcutId(String shortcutId) {
+ mN.mShortcutId = shortcutId;
+ return this;
+ }
+
+ /**
+ * Sets which icon to display as a badge for this notification.
+ *
+ * Must be one of {@link #BADGE_ICON_NONE}, {@link #BADGE_ICON_SMALL},
+ * {@link #BADGE_ICON_LARGE}.
+ *
+ * Note: This value might be ignored, for launchers that don't support badge icons.
+ */
+ public Builder chooseBadgeIcon(int icon) {
+ mN.mBadgeIcon = icon;
+ return this;
+ }
+
+ /**
* Specifies the channel the notification should be delivered on.
*/
public Builder setChannel(String channelId) {
@@ -2805,13 +2882,9 @@
}
/**
- * Set the large number at the right-hand side of the notification. This is
- * equivalent to setContentInfo, although it might show the number in a different
- * font size for readability.
- *
- * @deprecated this number is not shown anywhere anymore
+ * Sets the number of items this notification represents. May be displayed as a badge count
+ * for Launchers that support badging.
*/
- @Deprecated
public Builder setNumber(int number) {
mN.number = number;
return this;
@@ -3096,12 +3169,16 @@
* Set whether this notification should be colorized. When set, the color set with
* {@link #setColor(int)} will be used as the background color of this notification.
* <p>
- * The coloring will only be applied if the notification is ongoing.
* This should only be used for high priority ongoing tasks like navigation, an ongoing
* call, or other similarly high-priority events for the user.
+ * <p>
+ * For most styles, the coloring will only be applied if the notification is ongoing.
+ * However, for {@link MediaStyle} and {@link DecoratedMediaCustomViewStyle} notifications
+ * that have a media session attached there is no requirement for it to be ongoing.
*
* @see Builder#setOngoing(boolean)
* @see Builder#setColor(int)
+ * @see MediaStyle#setMediaSession(MediaSession.Token)
*/
public Builder setColorized(boolean colorize) {
mN.extras.putBoolean(EXTRA_COLORIZED, colorize);
@@ -3682,13 +3759,21 @@
}
private void bindExpandButton(RemoteViews contentView) {
- int color = isColorized() ? getPrimaryTextColor() : resolveContrastColor();
+ int color = getPrimaryHighlightColor();
contentView.setDrawableParameters(R.id.expand_button, false, -1, color,
PorterDuff.Mode.SRC_ATOP, -1);
contentView.setInt(R.id.notification_header, "setOriginalNotificationColor",
color);
}
+ /**
+ * @return the color that is used as the first primary highlight color. This is applied
+ * in several places like the action buttons or the app name in the header.
+ */
+ private int getPrimaryHighlightColor() {
+ return isColorized() ? getPrimaryTextColor() : resolveContrastColor();
+ }
+
private void bindHeaderChronometerAndTime(RemoteViews contentView) {
if (showsTimeOrChronometer()) {
contentView.setViewVisibility(R.id.time_divider, View.VISIBLE);
@@ -4265,7 +4350,7 @@
}
private CharSequence processLegacyText(CharSequence charSequence) {
- if (isLegacy() || isColorized()) {
+ if (isLegacy() || textColorsNeedInversion()) {
return getColorUtil().invertCharSequenceColors(charSequence);
} else {
return charSequence;
@@ -4278,7 +4363,7 @@
private void processSmallIconColor(Icon smallIcon, RemoteViews contentView,
boolean ambient) {
boolean colorable = !isLegacy() || getColorUtil().isGrayscaleIcon(mContext, smallIcon);
- int color = ambient ? resolveAmbientColor() : resolveContrastColor();
+ int color = ambient ? resolveAmbientColor() : getPrimaryHighlightColor();
if (colorable) {
contentView.setDrawableParameters(R.id.icon, false, -1, color,
PorterDuff.Mode.SRC_ATOP, -1);
@@ -4539,6 +4624,15 @@
private boolean isColorized() {
return mN.isColorized();
}
+
+ private boolean textColorsNeedInversion() {
+ if (mStyle == null || !MediaStyle.class.equals(mStyle.getClass())) {
+ return false;
+ }
+ int targetSdkVersion = mContext.getApplicationInfo().targetSdkVersion;
+ return targetSdkVersion > Build.VERSION_CODES.M
+ && targetSdkVersion < Build.VERSION_CODES.O;
+ }
}
/**
@@ -4551,6 +4645,14 @@
}
/**
+ * @return whether this notification has a media session attached
+ * @hide
+ */
+ public boolean hasMediaSession() {
+ return extras.getParcelable(Notification.EXTRA_MEDIA_SESSION) != null;
+ }
+
+ /**
* @return the style class of this notification
* @hide
*/
@@ -4564,12 +4666,23 @@
}
/**
- * @return true if this notification is colorized. This also factors in wheather the
+ * @return true if this notification is colorized. This also factors in whether the
* notification is ongoing.
*
* @hide
*/
public boolean isColorized() {
+ Class<? extends Style> style = getNotificationStyle();
+ if (MediaStyle.class.equals(style)) {
+ Boolean colorized = (Boolean) extras.get(EXTRA_COLORIZED);
+ if ((colorized == null || colorized) && hasMediaSession()) {
+ return true;
+ }
+ } else if (DecoratedMediaCustomViewStyle.class.equals(style)) {
+ if (extras.getBoolean(EXTRA_COLORIZED) && hasMediaSession()) {
+ return true;
+ }
+ }
return extras.getBoolean(EXTRA_COLORIZED) && isOngoing();
}
@@ -5815,21 +5928,27 @@
* shown as icon-only pushbuttons, suitable for transport controls. The Bitmap given to
* {@link Notification.Builder#setLargeIcon(android.graphics.Bitmap) setLargeIcon()} will be
* treated as album artwork.
- *
+ * <p>
* Unlike the other styles provided here, MediaStyle can also modify the standard-size
* {@link Notification#contentView}; by providing action indices to
* {@link #setShowActionsInCompactView(int...)} you can promote up to 3 actions to be displayed
* in the standard view alongside the usual content.
- *
+ * <p>
* Notifications created with MediaStyle will have their category set to
* {@link Notification#CATEGORY_TRANSPORT CATEGORY_TRANSPORT} unless you set a different
* category using {@link Notification.Builder#setCategory(String) setCategory()}.
- *
+ * <p>
* Finally, if you attach a {@link android.media.session.MediaSession.Token} using
* {@link android.app.Notification.MediaStyle#setMediaSession(MediaSession.Token)},
* the System UI can identify this as a notification representing an active media session
* and respond accordingly (by showing album artwork in the lockscreen, for example).
*
+ * <p>
+ * Starting at {@link android.os.Build.VERSION_CODES#O Android O} any notification that has a
+ * media session attached with {@link #setMediaSession(MediaSession.Token)} will be colorized.
+ * You can opt-out of this behavior by using {@link Notification.Builder#setColorized(boolean)}.
+ * <p>
+ *
* To use this style with your Notification, feed it to
* {@link Notification.Builder#setStyle(android.app.Notification.Style)} like so:
* <pre class="prettyprint">
@@ -5844,6 +5963,7 @@
* </pre>
*
* @see Notification#bigContentView
+ * @see Notification.Builder#setColorized(boolean)
*/
public static class MediaStyle extends Style {
static final int MAX_MEDIA_BUTTONS_IN_COMPACT = 3;
@@ -5981,7 +6101,7 @@
final Action action = mBuilder.mActions.get(mActionsToShowInCompact[i]);
final RemoteViews button = generateMediaActionButton(action,
- mBuilder.resolveContrastColor());
+ getPrimaryHighlightColor());
view.addView(com.android.internal.R.id.media_actions, button);
}
}
@@ -5995,6 +6115,10 @@
return view;
}
+ private int getPrimaryHighlightColor() {
+ return mBuilder.getPrimaryHighlightColor();
+ }
+
private RemoteViews makeMediaBigContentView() {
final int actionCount = Math.min(mBuilder.mActions.size(), MAX_MEDIA_BUTTONS);
// Dont add an expanded view if there is no more content to be revealed
@@ -6012,7 +6136,7 @@
big.removeAllViews(com.android.internal.R.id.media_actions);
for (int i = 0; i < actionCount; i++) {
final RemoteViews button = generateMediaActionButton(mBuilder.mActions.get(i),
- mBuilder.resolveContrastColor());
+ getPrimaryHighlightColor());
big.addView(com.android.internal.R.id.media_actions, button);
}
}
@@ -6157,7 +6281,10 @@
* {@link android.app.Notification.Builder#setCustomBigContentView(RemoteViews)} and
* {@link android.app.Notification.Builder#setCustomHeadsUpContentView(RemoteViews)} to set the
* corresponding custom views to display.
- *
+ * <p>
+ * Contrary to {@link MediaStyle} a developer has to opt-in to the colorizing of the
+ * notification by using {@link Notification.Builder#setColorized(boolean)}.
+ * <p>
* To use this style with your Notification, feed it to
* {@link Notification.Builder#setStyle(android.app.Notification.Style)} like so:
* <pre class="prettyprint">
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index fc1d613..44db326 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -30,6 +30,8 @@
import android.app.usage.UsageStatsManager;
import android.appwidget.AppWidgetManager;
import android.bluetooth.BluetoothManager;
+import android.companion.CompanionDeviceManager;
+import android.companion.ICompanionDeviceManager;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.IRestrictionsManager;
@@ -634,6 +636,18 @@
UserHandle.getAppId(Process.myUid()));
}});
+ registerService(Context.COMPANION_DEVICE_SERVICE, CompanionDeviceManager.class,
+ new CachedServiceFetcher<CompanionDeviceManager>() {
+ @Override
+ public CompanionDeviceManager createService(ContextImpl ctx)
+ throws ServiceNotFoundException {
+ IBinder iBinder =
+ ServiceManager.getServiceOrThrow(Context.COMPANION_DEVICE_SERVICE);
+ ICompanionDeviceManager service =
+ ICompanionDeviceManager.Stub.asInterface(iBinder);
+ return new CompanionDeviceManager(service, ctx);
+ }});
+
registerService(Context.CONSUMER_IR_SERVICE, ConsumerIrManager.class,
new CachedServiceFetcher<ConsumerIrManager>() {
@Override
diff --git a/core/java/android/app/TimePickerDialog.java b/core/java/android/app/TimePickerDialog.java
index 3f467a0..b219f2a 100644
--- a/core/java/android/app/TimePickerDialog.java
+++ b/core/java/android/app/TimePickerDialog.java
@@ -145,14 +145,25 @@
}
@Override
+ public void show() {
+ super.show();
+ getButton(BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ if (mTimePicker.validateInput()) {
+ if (mTimeSetListener != null) {
+ mTimeSetListener.onTimeSet(mTimePicker, mTimePicker.getCurrentHour(),
+ mTimePicker.getCurrentMinute());
+ }
+ dismiss();
+ }
+ }
+ });
+ }
+
+ @Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
- case BUTTON_POSITIVE:
- if (mTimeSetListener != null) {
- mTimeSetListener.onTimeSet(mTimePicker, mTimePicker.getCurrentHour(),
- mTimePicker.getCurrentMinute());
- }
- break;
case BUTTON_NEGATIVE:
cancel();
break;
diff --git a/core/java/android/app/UiAutomation.java b/core/java/android/app/UiAutomation.java
index 6d1d1a3..1d6f42e 100644
--- a/core/java/android/app/UiAutomation.java
+++ b/core/java/android/app/UiAutomation.java
@@ -1118,6 +1118,16 @@
public void onFingerprintGesture(int gesture) {
/* do nothing */
}
+
+ @Override
+ public void onAccessibilityButtonClicked() {
+ /* do nothing */
+ }
+
+ @Override
+ public void onAccessibilityButtonAvailabilityChanged(boolean available) {
+ /* do nothing */
+ }
});
}
}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 03d29a9..f1ccabe 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -377,7 +377,7 @@
* @hide
*/
public static final String ACTION_BUGREPORT_SHARING_ACCEPTED =
- "com.android.server.action.BUGREPORT_SHARING_ACCEPTED";
+ "com.android.server.action.REMOTE_BUGREPORT_SHARING_ACCEPTED";
/**
* Action: Bugreport sharing with device owner has been declined by the user.
@@ -385,7 +385,7 @@
* @hide
*/
public static final String ACTION_BUGREPORT_SHARING_DECLINED =
- "com.android.server.action.BUGREPORT_SHARING_DECLINED";
+ "com.android.server.action.REMOTE_BUGREPORT_SHARING_DECLINED";
/**
* Action: Bugreport has been collected and is dispatched to {@code DevicePolicyManagerService}.
diff --git a/core/java/android/app/admin/SecurityLog.java b/core/java/android/app/admin/SecurityLog.java
index 2858991..91b87d7 100644
--- a/core/java/android/app/admin/SecurityLog.java
+++ b/core/java/android/app/admin/SecurityLog.java
@@ -144,8 +144,7 @@
}
/**
- * Returns the payload contained in this log. Each call to this method will
- * retrieve the next payload item. If no more payload exists, it returns {@code null}.
+ * Returns the payload contained in this log entry or {@code null} if there is no payload.
*/
public Object getData() {
return mEvent.getData();
diff --git a/core/java/android/bluetooth/BluetoothCodecConfig.java b/core/java/android/bluetooth/BluetoothCodecConfig.java
index a482103..176e48f 100644
--- a/core/java/android/bluetooth/BluetoothCodecConfig.java
+++ b/core/java/android/bluetooth/BluetoothCodecConfig.java
@@ -37,9 +37,11 @@
public static final int SOURCE_CODEC_TYPE_APTX = 2;
public static final int SOURCE_CODEC_TYPE_APTX_HD = 3;
public static final int SOURCE_CODEC_TYPE_LDAC = 4;
+ public static final int SOURCE_CODEC_TYPE_MAX = 5;
public static final int SOURCE_CODEC_TYPE_INVALID = 1000 * 1000;
+ public static final int CODEC_PRIORITY_DISABLED = -1;
public static final int CODEC_PRIORITY_DEFAULT = 0;
public static final int CODEC_PRIORITY_HIGHEST = 1000 * 1000;
@@ -72,7 +74,7 @@
public BluetoothCodecConfig(int codecType, int codecPriority,
int sampleRate, int bitsPerSample,
- int channelMode,long codecSpecific1,
+ int channelMode, long codecSpecific1,
long codecSpecific2, long codecSpecific3,
long codecSpecific4) {
mCodecType = codecType;
diff --git a/core/java/android/bluetooth/le/ScanFilter.java b/core/java/android/bluetooth/le/ScanFilter.java
index 17a802d..b89c64a 100644
--- a/core/java/android/bluetooth/le/ScanFilter.java
+++ b/core/java/android/bluetooth/le/ScanFilter.java
@@ -67,7 +67,9 @@
private final byte[] mManufacturerData;
@Nullable
private final byte[] mManufacturerDataMask;
- private static final ScanFilter EMPTY = new ScanFilter.Builder().build() ;
+
+ /** @hide */
+ public static final ScanFilter EMPTY = new ScanFilter.Builder().build() ;
private ScanFilter(String name, String deviceAddress, ParcelUuid uuid,
@@ -318,8 +320,12 @@
return true;
}
- // Check if the uuid pattern is contained in a list of parcel uuids.
- private boolean matchesServiceUuids(ParcelUuid uuid, ParcelUuid parcelUuidMask,
+ /**
+ * Check if the uuid pattern is contained in a list of parcel uuids.
+ *
+ * @hide
+ */
+ public static boolean matchesServiceUuids(ParcelUuid uuid, ParcelUuid parcelUuidMask,
List<ParcelUuid> uuids) {
if (uuid == null) {
return true;
@@ -338,7 +344,7 @@
}
// Check if the uuid pattern matches the particular service uuid.
- private boolean matchesServiceUuid(UUID uuid, UUID mask, UUID data) {
+ private static boolean matchesServiceUuid(UUID uuid, UUID mask, UUID data) {
if (mask == null) {
return uuid.equals(data);
}
diff --git a/core/java/android/companion/AssociationRequest.aidl b/core/java/android/companion/AssociationRequest.aidl
new file mode 100644
index 0000000..6c91062
--- /dev/null
+++ b/core/java/android/companion/AssociationRequest.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2017 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.companion;
+
+parcelable AssociationRequest;
diff --git a/core/java/android/companion/AssociationRequest.java b/core/java/android/companion/AssociationRequest.java
new file mode 100644
index 0000000..d477f43
--- /dev/null
+++ b/core/java/android/companion/AssociationRequest.java
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2017 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.companion;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.provider.OneTimeUseBuilder;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * A request for the user to select a companion device to associate with.
+ *
+ * You can optionally set a {@link Builder#setDeviceFilter filter} for which devices to show to the
+ * user to select from.
+ * The exact type and fields of the filter you can set depend on the
+ * medium type. See {@link Builder}'s static factory methods for specific protocols that are
+ * supported.
+ *
+ * You can also set {@link Builder#setSingleDevice single device} to request a popup with single
+ * device to be shown instead of a list to choose from
+ *
+ * @param <F> Device filter type
+ */
+public final class AssociationRequest<F extends DeviceFilter> implements Parcelable {
+
+ /** @hide */
+ public static final int MEDIUM_TYPE_BLUETOOTH = 0;
+ /** @hide */
+ public static final int MEDIUM_TYPE_BLUETOOTH_LE = 1;
+ /** @hide */
+ public static final int MEDIUM_TYPE_WIFI = 2;
+
+ /** @hide */
+ @IntDef({MEDIUM_TYPE_BLUETOOTH, MEDIUM_TYPE_BLUETOOTH_LE, MEDIUM_TYPE_WIFI})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface MediumType {}
+
+ private final boolean mSingleDevice;
+ private final int mMediumType;
+ private final F mDeviceFilter;
+
+ private AssociationRequest(boolean singleDevice, int mMediumType, F deviceFilter) {
+ this.mSingleDevice = singleDevice;
+ this.mMediumType = mMediumType;
+ this.mDeviceFilter = deviceFilter;
+ }
+
+ private AssociationRequest(Parcel in) {
+ this(
+ in.readByte() != 0,
+ in.readInt(),
+ in.readParcelable(AssociationRequest.class.getClassLoader()));
+ }
+
+ /** @hide */
+ public boolean isSingleDevice() {
+ return mSingleDevice;
+ }
+
+ /** @hide */
+ @MediumType
+ public int getMediumType() {
+ return mMediumType;
+ }
+
+ /** @hide */
+ @Nullable
+ public F getDeviceFilter() {
+ return mDeviceFilter;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeByte((byte) (mSingleDevice ? 1 : 0));
+ dest.writeInt(mMediumType);
+ dest.writeParcelable(mDeviceFilter, flags);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ public static final Creator<AssociationRequest> CREATOR = new Creator<AssociationRequest>() {
+ @Override
+ public AssociationRequest createFromParcel(Parcel in) {
+ return new AssociationRequest(in);
+ }
+
+ @Override
+ public AssociationRequest[] newArray(int size) {
+ return new AssociationRequest[size];
+ }
+ };
+
+ /**
+ * A builder for {@link AssociationRequest}
+ *
+ * @param <F> the type of filter for the request.
+ */
+ public static final class Builder<F extends DeviceFilter>
+ extends OneTimeUseBuilder<AssociationRequest<F>> {
+ private boolean mSingleDevice = false;
+ @MediumType private int mMediumType;
+ @Nullable private F mDeviceFilter = null;
+
+ private Builder() {}
+
+ /**
+ * Create a new builder for an association request with a Bluetooth LE device
+ */
+ @NonNull
+ public static Builder<BluetoothLEDeviceFilter> createForBluetoothLEDevice() {
+ return new Builder<BluetoothLEDeviceFilter>()
+ .setMediumType(MEDIUM_TYPE_BLUETOOTH_LE);
+ }
+
+ /**
+ * Create a new builder for an association request with a Bluetooth(non-LE) device
+ */
+ @NonNull
+ public static Builder<BluetoothDeviceFilter> createForBluetoothDevice() {
+ return new Builder<BluetoothDeviceFilter>()
+ .setMediumType(MEDIUM_TYPE_BLUETOOTH);
+ }
+
+ //TODO implement, once specific filter classes are available
+// public static Builder<> createForWiFiDevice()
+// public static Builder<> createForNanDevice()
+
+ /**
+ * @param singleDevice if true, scanning for a device will stop as soon as at least one
+ * fitting device is found
+ */
+ @NonNull
+ public Builder<F> setSingleDevice(boolean singleDevice) {
+ checkNotUsed();
+ this.mSingleDevice = singleDevice;
+ return this;
+ }
+
+ /**
+ * @param deviceFilter if set, only devices matching the given filter will be shown to the
+ * user
+ */
+ @NonNull
+ public Builder<F> setDeviceFilter(@Nullable F deviceFilter) {
+ checkNotUsed();
+ this.mDeviceFilter = deviceFilter;
+ return this;
+ }
+
+ /**
+ * @param deviceType A type of medium over which to discover devices
+ *
+ * @see MediumType
+ */
+ @NonNull
+ private Builder<F> setMediumType(@MediumType int deviceType) {
+ mMediumType = deviceType;
+ return this;
+ }
+
+ /** @inheritDoc */
+ @NonNull
+ @Override
+ public AssociationRequest<F> build() {
+ markUsed();
+ return new AssociationRequest<>(mSingleDevice, mMediumType, mDeviceFilter);
+ }
+ }
+}
diff --git a/core/java/android/companion/BluetoothDeviceFilter.java b/core/java/android/companion/BluetoothDeviceFilter.java
new file mode 100644
index 0000000..5a69955
--- /dev/null
+++ b/core/java/android/companion/BluetoothDeviceFilter.java
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2017 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.companion;
+
+import static android.companion.BluetoothDeviceFilterUtils.matchesAddress;
+import static android.companion.BluetoothDeviceFilterUtils.matchesName;
+import static android.companion.BluetoothDeviceFilterUtils.matchesServiceUuids;
+import static android.companion.BluetoothDeviceFilterUtils.patternFromString;
+import static android.companion.BluetoothDeviceFilterUtils.patternToString;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.bluetooth.BluetoothDevice;
+import android.os.Parcel;
+import android.os.ParcelUuid;
+import android.provider.OneTimeUseBuilder;
+
+import com.android.internal.util.ArrayUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Pattern;
+
+/**
+ * A filter for Bluetooth(non-LE) devices
+ */
+public final class BluetoothDeviceFilter implements DeviceFilter<BluetoothDevice> {
+
+ private static BluetoothDeviceFilter NO_OP;
+
+ private final Pattern mNamePattern;
+ private final String mAddress;
+ private final List<ParcelUuid> mServiceUuids;
+ private final List<ParcelUuid> mServiceUuidMasks;
+
+ private BluetoothDeviceFilter(
+ Pattern namePattern,
+ String address,
+ List<ParcelUuid> serviceUuids,
+ List<ParcelUuid> serviceUuidMasks) {
+ mNamePattern = namePattern;
+ mAddress = address;
+ mServiceUuids = ArrayUtils.emptyIfNull(serviceUuids);
+ mServiceUuidMasks = ArrayUtils.emptyIfNull(serviceUuidMasks);
+ }
+
+ private BluetoothDeviceFilter(Parcel in) {
+ this(
+ patternFromString(in.readString()),
+ in.readString(),
+ readUuids(in),
+ readUuids(in));
+ }
+
+ private static List<ParcelUuid> readUuids(Parcel in) {
+ final ArrayList<ParcelUuid> list = new ArrayList<>();
+ in.readParcelableList(list, ParcelUuid.class.getClassLoader());
+ return list;
+ }
+
+ /** @hide */
+ @NonNull
+ public static BluetoothDeviceFilter nullsafe(@Nullable BluetoothDeviceFilter nullable) {
+ return nullable != null ? nullable : noOp();
+ }
+
+ /** @hide */
+ @NonNull
+ public static BluetoothDeviceFilter noOp() {
+ if (NO_OP == null) NO_OP = new Builder().build();
+ return NO_OP;
+ }
+
+ /** @hide */
+ @Override
+ public boolean matches(BluetoothDevice device) {
+ return matchesAddress(mAddress, device)
+ && matchesServiceUuids(mServiceUuids, mServiceUuidMasks, device)
+ && matchesName(getNamePattern(), device);
+ }
+
+ /** @hide */
+ @Nullable
+ public Pattern getNamePattern() {
+ return mNamePattern;
+ }
+
+ /** @hide */
+ @Nullable
+ public String getAddress() {
+ return mAddress;
+ }
+
+ /** @hide */
+ @NonNull
+ public List<ParcelUuid> getServiceUuids() {
+ return mServiceUuids;
+ }
+
+ /** @hide */
+ @NonNull
+ public List<ParcelUuid> getServiceUuidMasks() {
+ return mServiceUuidMasks;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(patternToString(getNamePattern()));
+ dest.writeString(mAddress);
+ dest.writeParcelableList(mServiceUuids, flags);
+ dest.writeParcelableList(mServiceUuidMasks, flags);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ public static final Creator<BluetoothDeviceFilter> CREATOR
+ = new Creator<BluetoothDeviceFilter>() {
+ @Override
+ public BluetoothDeviceFilter createFromParcel(Parcel in) {
+ return new BluetoothDeviceFilter(in);
+ }
+
+ @Override
+ public BluetoothDeviceFilter[] newArray(int size) {
+ return new BluetoothDeviceFilter[size];
+ }
+ };
+
+ /**
+ * A builder for {@link BluetoothDeviceFilter}
+ */
+ public static final class Builder extends OneTimeUseBuilder<BluetoothDeviceFilter> {
+ private Pattern mNamePattern;
+ private String mAddress;
+ private ArrayList<ParcelUuid> mServiceUuid;
+ private ArrayList<ParcelUuid> mServiceUuidMask;
+
+ /**
+ * @param regex if set, only devices with {@link BluetoothDevice#getName name} matching the
+ * given regular expression will be shown
+ */
+ public Builder setNamePattern(@Nullable Pattern regex) {
+ checkNotUsed();
+ mNamePattern = regex;
+ return this;
+ }
+
+ /**
+ * @param address if set, only devices with MAC address exactly matching the given one will
+ * pass the filter
+ */
+ @NonNull
+ public Builder setAddress(@Nullable String address) {
+ checkNotUsed();
+ mAddress = address;
+ return this;
+ }
+
+ /**
+ * Add filtering by certain bits of {@link BluetoothDevice#getUuids()}
+ *
+ * A device with any uuid matching the given bits is considered passing
+ *
+ * @param serviceUuid the values for the bits to match
+ * @param serviceUuidMask if provided, only those bits would have to match.
+ */
+ @NonNull
+ public Builder addServiceUuid(
+ @Nullable ParcelUuid serviceUuid, @Nullable ParcelUuid serviceUuidMask) {
+ checkNotUsed();
+ mServiceUuid = ArrayUtils.add(mServiceUuid, serviceUuid);
+ mServiceUuidMask = ArrayUtils.add(mServiceUuidMask, serviceUuidMask);
+ return this;
+ }
+
+ /** @inheritDoc */
+ @Override
+ @NonNull
+ public BluetoothDeviceFilter build() {
+ markUsed();
+ return new BluetoothDeviceFilter(
+ mNamePattern, mAddress, mServiceUuid, mServiceUuidMask);
+ }
+ }
+}
diff --git a/core/java/android/companion/BluetoothDeviceFilterUtils.java b/core/java/android/companion/BluetoothDeviceFilterUtils.java
new file mode 100644
index 0000000..289f995
--- /dev/null
+++ b/core/java/android/companion/BluetoothDeviceFilterUtils.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2017 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.companion;
+
+import static android.text.TextUtils.firstNotEmpty;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.le.ScanFilter;
+import android.os.ParcelUuid;
+import android.util.Log;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.regex.Pattern;
+
+/** @hide */
+public class BluetoothDeviceFilterUtils {
+ private BluetoothDeviceFilterUtils() {}
+
+ private static final boolean DEBUG = false;
+ private static final String LOG_TAG = "BluetoothDeviceFilterUtil";
+
+ @Nullable
+ static String patternToString(@Nullable Pattern p) {
+ return p == null ? null : p.pattern();
+ }
+
+ @Nullable
+ static Pattern patternFromString(@Nullable String s) {
+ return s == null ? null : Pattern.compile(s);
+ }
+
+ static boolean matches(ScanFilter filter, BluetoothDevice device) {
+ return matchesAddress(filter.getDeviceAddress(), device)
+ && matchesServiceUuid(filter.getServiceUuid(), filter.getServiceUuidMask(), device);
+ }
+
+ static boolean matchesAddress(String deviceAddress, BluetoothDevice device) {
+ final boolean result = deviceAddress == null
+ || (device == null || !deviceAddress.equals(device.getAddress()));
+ if (DEBUG) debugLogMatchResult(result, device, deviceAddress);
+ return result;
+ }
+
+ static boolean matchesServiceUuids(List<ParcelUuid> serviceUuids,
+ List<ParcelUuid> serviceUuidMasks, BluetoothDevice device) {
+ for (int i = 0; i < serviceUuids.size(); i++) {
+ ParcelUuid uuid = serviceUuids.get(i);
+ ParcelUuid uuidMask = serviceUuidMasks.get(i);
+ if (!matchesServiceUuid(uuid, uuidMask, device)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ static boolean matchesServiceUuid(ParcelUuid serviceUuid, ParcelUuid serviceUuidMask,
+ BluetoothDevice device) {
+ final boolean result = serviceUuid == null ||
+ ScanFilter.matchesServiceUuids(
+ serviceUuid,
+ serviceUuidMask,
+ Arrays.asList(device.getUuids()));
+ if (DEBUG) debugLogMatchResult(result, device, serviceUuid);
+ return result;
+ }
+
+ static boolean matchesName(@Nullable Pattern namePattern, BluetoothDevice device) {
+ boolean result;
+ if (namePattern == null) {
+ result = true;
+ } else if (device == null) {
+ result = false;
+ } else {
+ final String name = device.getName();
+ result = name != null && namePattern.matcher(name).find();
+ }
+ if (DEBUG) debugLogMatchResult(result, device, namePattern);
+ return result;
+ }
+
+ private static void debugLogMatchResult(
+ boolean result, BluetoothDevice device, Object criteria) {
+ Log.i(LOG_TAG, getDeviceDisplayName(device) + (result ? " ~ " : " !~ ") + criteria);
+ }
+
+ public static String getDeviceDisplayName(@NonNull BluetoothDevice device) {
+ return firstNotEmpty(device.getAliasName(), device.getAddress());
+ }
+}
diff --git a/core/java/android/companion/BluetoothLEDeviceFilter.aidl b/core/java/android/companion/BluetoothLEDeviceFilter.aidl
new file mode 100644
index 0000000..628cf7b
--- /dev/null
+++ b/core/java/android/companion/BluetoothLEDeviceFilter.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2017 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.companion;
+
+parcelable BluetoothLEDeviceFilter;
diff --git a/core/java/android/companion/BluetoothLEDeviceFilter.java b/core/java/android/companion/BluetoothLEDeviceFilter.java
new file mode 100644
index 0000000..4a481ca
--- /dev/null
+++ b/core/java/android/companion/BluetoothLEDeviceFilter.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2017 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.companion;
+
+import static android.companion.BluetoothDeviceFilterUtils.patternFromString;
+import static android.companion.BluetoothDeviceFilterUtils.patternToString;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SuppressLint;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.le.ScanFilter;
+import android.os.Parcel;
+import android.provider.OneTimeUseBuilder;
+
+import com.android.internal.util.ObjectUtils;
+
+import java.util.regex.Pattern;
+
+/**
+ * A filter for Bluetooth LE devices
+ *
+ * @see ScanFilter
+ */
+public final class BluetoothLEDeviceFilter implements DeviceFilter<BluetoothDevice> {
+
+ private static BluetoothLEDeviceFilter NO_OP;
+
+ private final Pattern mNamePattern;
+ private final ScanFilter mScanFilter;
+
+ private BluetoothLEDeviceFilter(Pattern namePattern, ScanFilter scanFilter) {
+ mNamePattern = namePattern;
+ mScanFilter = ObjectUtils.firstNotNull(scanFilter, ScanFilter.EMPTY);
+ }
+
+ @SuppressLint("ParcelClassLoader")
+ private BluetoothLEDeviceFilter(Parcel in) {
+ this(
+ patternFromString(in.readString()),
+ in.readParcelable(null));
+ }
+
+ /** @hide */
+ @NonNull
+ public static BluetoothLEDeviceFilter nullsafe(@Nullable BluetoothLEDeviceFilter nullable) {
+ return nullable != null ? nullable : noOp();
+ }
+
+ /** @hide */
+ @NonNull
+ public static BluetoothLEDeviceFilter noOp() {
+ if (NO_OP == null) NO_OP = new Builder().build();
+ return NO_OP;
+ }
+
+ /** @hide */
+ @Nullable
+ public Pattern getNamePattern() {
+ return mNamePattern;
+ }
+
+ /** @hide */
+ @NonNull
+ public ScanFilter getScanFilter() {
+ return mScanFilter;
+ }
+
+ /** @hide */
+ @Override
+ public boolean matches(BluetoothDevice device) {
+ return BluetoothDeviceFilterUtils.matches(getScanFilter(), device)
+ && BluetoothDeviceFilterUtils.matchesName(getNamePattern(), device);
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(patternToString(getNamePattern()));
+ dest.writeParcelable(mScanFilter, flags);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ public static final Creator<BluetoothLEDeviceFilter> CREATOR
+ = new Creator<BluetoothLEDeviceFilter>() {
+ @Override
+ public BluetoothLEDeviceFilter createFromParcel(Parcel in) {
+ return new BluetoothLEDeviceFilter(in);
+ }
+
+ @Override
+ public BluetoothLEDeviceFilter[] newArray(int size) {
+ return new BluetoothLEDeviceFilter[size];
+ }
+ };
+
+ /**
+ * Builder for {@link BluetoothLEDeviceFilter}
+ */
+ public static final class Builder extends OneTimeUseBuilder<BluetoothLEDeviceFilter> {
+ private ScanFilter mScanFilter;
+ private Pattern mNamePattern;
+
+ /**
+ * @param regex if set, only devices with {@link BluetoothDevice#getName name} matching the
+ * given regular expression will be shown
+ */
+ public Builder setNamePattern(@Nullable Pattern regex) {
+ checkNotUsed();
+ mNamePattern = regex;
+ return this;
+ }
+
+ /**
+ * @param scanFilter a {@link ScanFilter} to filter devices by
+ *
+ * @see ScanFilter for specific details on its various fields
+ */
+ @NonNull
+ public Builder setScanFilter(@Nullable ScanFilter scanFilter) {
+ checkNotUsed();
+ mScanFilter = scanFilter;
+ return this;
+ }
+
+ /** @inheritDoc */
+ @Override
+ @NonNull
+ public BluetoothLEDeviceFilter build() {
+ markUsed();
+ return new BluetoothLEDeviceFilter(mNamePattern, mScanFilter);
+ }
+ }
+}
diff --git a/core/java/android/companion/CompanionDeviceManager.java b/core/java/android/companion/CompanionDeviceManager.java
new file mode 100644
index 0000000..b379c7c
--- /dev/null
+++ b/core/java/android/companion/CompanionDeviceManager.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2017 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.companion;
+
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.IntentSender;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.RemoteException;
+
+/**
+ * System level service for managing companion devices
+ *
+ * Usage:
+ * To obtain an instance call
+ * {@link Context#getSystemService}({@link Context#COMPANION_DEVICE_SERVICE})
+ *
+ * Then, call {@link #associate} to initiate the flow of associating current package
+ * with a device selected by user
+ *
+ * @see AssociationRequest
+ */
+public final class CompanionDeviceManager {
+
+ /**
+ * A device, returned in the activity result of the {@link IntentSender} received in
+ * {@link Callback#onDeviceFound}
+ */
+ public static final String EXTRA_DEVICE = "android.companion.extra.DEVICE";
+
+ /**
+ * A callback to receive once at least one suitable device is found, or the search failed
+ * (e.g. timed out)
+ */
+ public abstract static class Callback {
+
+ /**
+ * Called once at least one suitable device is found
+ *
+ * @param chooserLauncher a {@link IntentSender} to launch the UI for user to select a
+ * device
+ */
+ public abstract void onDeviceFound(IntentSender chooserLauncher);
+
+ /**
+ * Called if there was an error looking for device(s), e.g. timeout
+ *
+ * @param error the cause of the error
+ */
+ public abstract void onFailure(CharSequence error);
+ }
+
+ private final ICompanionDeviceManager mService;
+ private final Context mContext;
+
+ /** @hide */
+ public CompanionDeviceManager(
+ @NonNull ICompanionDeviceManager service, @NonNull Context context) {
+ mService = service;
+ mContext = context;
+ }
+
+ /**
+ * Associate this app with a companion device, selected by user
+ *
+ * Once at least one appropriate device is found, {@code callback} will be called with a
+ * {@link PendingIntent} that can be used to show the list of available devices for the user
+ * to select.
+ * It should be started for result (i.e. using
+ * {@link android.app.Activity#startIntentSenderForResult}), as the resulting
+ * {@link android.content.Intent} will contain extra {@link #EXTRA_DEVICE}, with the selected
+ * device. (e.g. {@link android.bluetooth.BluetoothDevice})
+ *
+ * @param request specific details about this request
+ * @param callback will be called once there's at least one device found for user to choose from
+ * @param handler A handler to control which thread the callback will be delivered on, or null,
+ * to deliver it on main thread
+ *
+ * @see AssociationRequest
+ */
+ public void associate(
+ @NonNull AssociationRequest<?> request,
+ @NonNull Callback callback,
+ @Nullable Handler handler) {
+ final Handler finalHandler = handler != null
+ ? handler
+ : new Handler(Looper.getMainLooper());
+ try {
+ mService.associate(
+ request,
+ new IOnAssociateCallback.Stub() {
+
+ @Override
+ public void onSuccess(PendingIntent launcher) throws RemoteException {
+ finalHandler.post(() -> {
+ callback.onDeviceFound(launcher.getIntentSender());
+ });
+ }
+
+ @Override
+ public void onFailure(CharSequence reason) throws RemoteException {
+ finalHandler.post(() -> callback.onFailure(reason));
+ }
+ },
+ mContext.getPackageName());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /** @hide */
+ public void requestNotificationAccess() {
+ //TODO implement
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ /** @hide */
+ public boolean haveNotificationAccess() {
+ //TODO implement
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+}
diff --git a/core/java/android/companion/DeviceFilter.java b/core/java/android/companion/DeviceFilter.java
new file mode 100644
index 0000000..8362b2d
--- /dev/null
+++ b/core/java/android/companion/DeviceFilter.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2017 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.companion;
+
+import android.annotation.Nullable;
+import android.os.Parcelable;
+
+/**
+ * A filter for companion devices of type {@code D}
+ *
+ * @param <D> Type of devices, filtered by this filter,
+ * e.g. {@link android.bluetooth.BluetoothDevice}, {@link android.net.wifi.WifiInfo}
+ */
+public interface DeviceFilter<D extends Parcelable> extends Parcelable {
+
+ /**
+ * @return whether the given device matches this filter
+ *
+ * @hide
+ */
+ boolean matches(D device);
+
+ /**
+ * A nullsafe {@link #matches(Parcelable)}, returning true if the filter is null
+ *
+ * @hide
+ */
+ static <D extends Parcelable> boolean matches(@Nullable DeviceFilter<D> filter, D device) {
+ return filter == null || filter.matches(device);
+ }
+}
diff --git a/core/java/android/companion/ICompanionDeviceManager.aidl b/core/java/android/companion/ICompanionDeviceManager.aidl
new file mode 100644
index 0000000..065e31b
--- /dev/null
+++ b/core/java/android/companion/ICompanionDeviceManager.aidl
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2017 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.companion;
+
+import android.companion.IOnAssociateCallback;
+import android.companion.AssociationRequest;
+
+/**
+ * Interface for communication with the core companion device manager service.
+ *
+ * @hide
+ */
+interface ICompanionDeviceManager {
+ void associate(in AssociationRequest request,
+ in IOnAssociateCallback callback,
+ in String callingPackage); //TODO int userId?
+
+ //TODO add these
+// boolean haveNotificationAccess(String packageName);
+// oneway void requestNotificationAccess(String packageName);
+}
diff --git a/core/java/android/companion/ICompanionDeviceManagerService.aidl b/core/java/android/companion/ICompanionDeviceManagerService.aidl
new file mode 100644
index 0000000..ff2a7eb
--- /dev/null
+++ b/core/java/android/companion/ICompanionDeviceManagerService.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2017 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.companion;
+
+import android.companion.AssociationRequest;
+import android.companion.IOnAssociateCallback;
+
+
+/** @hide */
+interface ICompanionDeviceManagerService {
+ void startDiscovery(
+ in AssociationRequest request,
+ in IOnAssociateCallback callback,
+ in String callingPackage);
+}
diff --git a/core/java/android/companion/ICompanionDeviceManagerServiceCallback.aidl b/core/java/android/companion/ICompanionDeviceManagerServiceCallback.aidl
new file mode 100644
index 0000000..c9dd345
--- /dev/null
+++ b/core/java/android/companion/ICompanionDeviceManagerServiceCallback.aidl
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2017 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 per missions and
+ * limitations under the License.
+ */
+
+package android.companion;
+
+import android.bluetooth.BluetoothDevice;
+
+/** @hide */
+interface ICompanionDeviceManagerServiceCallback {
+ void onDeviceSelected(in BluetoothDevice device);
+}
diff --git a/core/java/android/companion/IOnAssociateCallback.aidl b/core/java/android/companion/IOnAssociateCallback.aidl
new file mode 100644
index 0000000..4867eadd
--- /dev/null
+++ b/core/java/android/companion/IOnAssociateCallback.aidl
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2017 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 per missions and
+ * limitations under the License.
+ */
+
+package android.companion;
+
+import android.app.PendingIntent;
+
+/** @hide */
+interface IOnAssociateCallback {
+ void onSuccess(in PendingIntent launcher);
+ void onFailure(in CharSequence reason);
+}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index a7d5ac6..06f7303 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -3600,6 +3600,14 @@
public static final String PRINT_SERVICE = "print";
/**
+ * {@link android.companion.CompanionDeviceManager} for managing companion devices
+ *
+ * @see #getSystemService
+ * @see android.companion.CompanionDeviceManager
+ */
+ public static final String COMPANION_DEVICE_SERVICE = "companion_device";
+
+ /**
* Use with {@link #getSystemService} to retrieve a
* {@link android.hardware.ConsumerIrManager} for transmitting infrared
* signals from the device.
diff --git a/core/java/android/content/SyncRequest.java b/core/java/android/content/SyncRequest.java
index dd53eac..74d2f11 100644
--- a/core/java/android/content/SyncRequest.java
+++ b/core/java/android/content/SyncRequest.java
@@ -351,7 +351,7 @@
* @param requiresCharging true if sync requires the phone to be plugged in. Default false.
*/
public Builder setRequiresCharging(boolean requiresCharging) {
- mRequiresCharging = true;
+ mRequiresCharging = requiresCharging;
return this;
}
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index ab641c9..b20b5e2 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1741,6 +1741,22 @@
/**
* Feature for {@link #getSystemAvailableFeatures} and
+ * {@link #hasSystemFeature(String, int)}: If this feature is supported, the Vulkan native API
+ * will enumerate at least one {@code VkPhysicalDevice}, and the feature version will indicate
+ * what level of optional compute features are supported beyond the Vulkan 1.0 requirements.
+ * <p>
+ * Compute level 0 indicates support for:
+ * <ul>
+ * <li>Ability to use pointers to buffer data from shaders</li>
+ * <li>Ability to load/store 16-bit values from buffers</li>
+ * <li>Ability to control shader floating point rounding mode</li>
+ * </ul>
+ */
+ @SdkConstant(SdkConstantType.FEATURE)
+ public static final String FEATURE_VULKAN_HARDWARE_COMPUTE = "android.hardware.vulkan.compute";
+
+ /**
+ * Feature for {@link #getSystemAvailableFeatures} and
* {@link #hasSystemFeature(String, int)}: The version of this feature indicates the highest
* {@code VkPhysicalDeviceProperties::apiVersion} supported by the physical devices that support
* the hardware level indicated by {@link #FEATURE_VULKAN_HARDWARE_LEVEL}. The feature version
diff --git a/core/java/android/hardware/camera2/params/OutputConfiguration.java b/core/java/android/hardware/camera2/params/OutputConfiguration.java
index 522575f..d951294 100644
--- a/core/java/android/hardware/camera2/params/OutputConfiguration.java
+++ b/core/java/android/hardware/camera2/params/OutputConfiguration.java
@@ -259,10 +259,6 @@
throw new IllegalArgumentException("Unknow surface source class type");
}
- if (surfaceSize.getWidth() == 0 || surfaceSize.getHeight() == 0) {
- throw new IllegalArgumentException("Surface size needs to be non-zero");
- }
-
mSurfaceGroupId = SURFACE_GROUP_ID_NONE;
mSurfaces = new ArrayList<Surface>();
mRotation = ROTATION_0;
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java
index 3eb5844..98a5749 100644
--- a/core/java/android/hardware/display/DisplayManagerInternal.java
+++ b/core/java/android/hardware/display/DisplayManagerInternal.java
@@ -230,9 +230,6 @@
public int dozeScreenBrightness;
public int dozeScreenState;
- // If true, use twilight to affect the brightness.
- public boolean useTwilight;
-
public DisplayPowerRequest() {
policy = POLICY_BRIGHT;
useProximitySensor = false;
@@ -268,7 +265,6 @@
boostScreenBrightness = other.boostScreenBrightness;
dozeScreenBrightness = other.dozeScreenBrightness;
dozeScreenState = other.dozeScreenState;
- useTwilight = other.useTwilight;
}
@Override
@@ -289,8 +285,7 @@
&& lowPowerMode == other.lowPowerMode
&& boostScreenBrightness == other.boostScreenBrightness
&& dozeScreenBrightness == other.dozeScreenBrightness
- && dozeScreenState == other.dozeScreenState
- && useTwilight == other.useTwilight;
+ && dozeScreenState == other.dozeScreenState;
}
@Override
@@ -310,8 +305,7 @@
+ ", lowPowerMode=" + lowPowerMode
+ ", boostScreenBrightness=" + boostScreenBrightness
+ ", dozeScreenBrightness=" + dozeScreenBrightness
- + ", dozeScreenState=" + Display.stateToString(dozeScreenState)
- + ", useTwilight=" + useTwilight;
+ + ", dozeScreenState=" + Display.stateToString(dozeScreenState);
}
public static String policyToString(int policy) {
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index 2c9e6c7..7947620 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -766,7 +766,7 @@
/**
* Retrieves the authenticator token for binding keys to the lifecycle
- * of the current set of fingerprints. Used only by internal clients.
+ * of the calling user's fingerprints. Used only by internal clients.
*
* @hide
*/
diff --git a/core/java/android/net/RecommendationRequest.java b/core/java/android/net/RecommendationRequest.java
index b89a245..9f97c5a 100644
--- a/core/java/android/net/RecommendationRequest.java
+++ b/core/java/android/net/RecommendationRequest.java
@@ -50,7 +50,7 @@
private WifiConfiguration mDefaultConfig;
private WifiConfiguration mConnectedConfig;
private WifiConfiguration[] mConnectableConfigs;
- private int mLastSelectedNetworkId;
+ private int mLastSelectedNetworkId = -1;
private long mLastSelectedTimestamp;
public Builder setScanResults(ScanResult[] scanResults) {
@@ -161,7 +161,7 @@
/**
* @return The {@link WifiConfiguration#networkId} of the last user selected network.
- * {@code 0} if not set.
+ * {@code -1} if not set.
*/
public int getLastSelectedNetworkId() {
return mLastSelectedNetworkId;
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index dff0a28..31b3bc9 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -508,15 +508,6 @@
}
/**
- * Returns true if the twilight service should be used to adjust screen brightness
- * policy. This setting is experimental and disabled by default.
- * @hide
- */
- public static boolean useTwilightAdjustmentFeature() {
- return SystemProperties.getBoolean("persist.power.usetwilightadj", false);
- }
-
- /**
* Creates a new wake lock with the specified level and flags.
* <p>
* The {@code levelAndFlags} parameter specifies a wake lock level and optional flags
diff --git a/core/java/android/preference/PreferenceActivity.java b/core/java/android/preference/PreferenceActivity.java
index 06666f4..5e7f68b 100644
--- a/core/java/android/preference/PreferenceActivity.java
+++ b/core/java/android/preference/PreferenceActivity.java
@@ -16,6 +16,7 @@
package android.preference;
+import android.animation.LayoutTransition;
import android.annotation.Nullable;
import android.annotation.StringRes;
import android.annotation.XmlRes;
@@ -87,7 +88,7 @@
* items. Doing this implicitly switches the class into its new "headers
* + fragments" mode rather than the old style of just showing a single
* preferences list.
- *
+ *
* <div class="special reference">
* <h3>Developer Guides</h3>
* <p>For information about using {@code PreferenceActivity},
@@ -199,6 +200,9 @@
private ViewGroup mPrefsContainer;
+ // Null if in legacy mode.
+ private ViewGroup mHeadersContainer;
+
private FragmentBreadCrumbs mFragmentBreadCrumbs;
private boolean mSinglePane;
@@ -292,7 +296,7 @@
holder = (HeaderViewHolder) view.getTag();
}
- // All view fields must be updated every time, because the view may be recycled
+ // All view fields must be updated every time, because the view may be recycled
Header header = getItem(position);
if (mRemoveIconIfEmpty) {
if (header.iconRes == 0) {
@@ -469,7 +473,7 @@
}
return breadCrumbShortTitle;
}
-
+
@Override
public int describeContents() {
return 0;
@@ -558,6 +562,7 @@
mListFooter = (FrameLayout)findViewById(com.android.internal.R.id.list_footer);
mPrefsContainer = (ViewGroup) findViewById(com.android.internal.R.id.prefs_frame);
+ mHeadersContainer = (ViewGroup) findViewById(com.android.internal.R.id.headers);
boolean hidingHeaders = onIsHidingHeaders();
mSinglePane = hidingHeaders || !onIsMultiPane();
String initialFragment = getIntent().getStringExtra(EXTRA_SHOW_FRAGMENT);
@@ -575,66 +580,39 @@
(int) HEADER_ID_UNDEFINED);
if (curHeader >= 0 && curHeader < mHeaders.size()) {
setSelectedHeader(mHeaders.get(curHeader));
+ } else if (!mSinglePane && initialFragment == null) {
+ switchToHeader(onGetInitialHeader());
}
+ } else {
+ // This will for instance hide breadcrumbs for single pane.
+ showBreadCrumbs(getTitle(), null);
+ }
+ } else {
+ if (!onIsHidingHeaders()) {
+ onBuildHeaders(mHeaders);
}
- } else {
- if (initialFragment != null && mSinglePane) {
- // If we are just showing a fragment, we want to run in
- // new fragment mode, but don't need to compute and show
- // the headers.
+ if (initialFragment != null) {
switchToHeader(initialFragment, initialArguments);
- if (initialTitle != 0) {
- CharSequence initialTitleStr = getText(initialTitle);
- CharSequence initialShortTitleStr = initialShortTitle != 0
- ? getText(initialShortTitle) : null;
- showBreadCrumbs(initialTitleStr, initialShortTitleStr);
- }
-
- } else {
- // We need to try to build the headers.
- onBuildHeaders(mHeaders);
-
- // If there are headers, then at this point we need to show
- // them and, depending on the screen, we may also show in-line
- // the currently selected preference fragment.
- if (mHeaders.size() > 0) {
- if (!mSinglePane) {
- if (initialFragment == null) {
- Header h = onGetInitialHeader();
- switchToHeader(h);
- } else {
- switchToHeader(initialFragment, initialArguments);
- }
- }
- }
+ } else if (!mSinglePane && mHeaders.size() > 0) {
+ switchToHeader(onGetInitialHeader());
}
}
- // The default configuration is to only show the list view. Adjust
- // visibility for other configurations.
- if (initialFragment != null && mSinglePane) {
- // Single pane, showing just a prefs fragment.
- findViewById(com.android.internal.R.id.headers).setVisibility(View.GONE);
- mPrefsContainer.setVisibility(View.VISIBLE);
- if (initialTitle != 0) {
- CharSequence initialTitleStr = getText(initialTitle);
- CharSequence initialShortTitleStr = initialShortTitle != 0
- ? getText(initialShortTitle) : null;
- showBreadCrumbs(initialTitleStr, initialShortTitleStr);
- }
- } else if (mHeaders.size() > 0) {
+ if (mHeaders.size() > 0) {
setListAdapter(new HeaderAdapter(this, mHeaders, mPreferenceHeaderItemResId,
mPreferenceHeaderRemoveEmptyIcon));
- if (!mSinglePane) {
- // Multi-pane.
- getListView().setChoiceMode(AbsListView.CHOICE_MODE_SINGLE);
- if (mCurHeader != null) {
- setSelectedHeader(mCurHeader);
- }
- mPrefsContainer.setVisibility(View.VISIBLE);
- }
- } else {
+ getListView().setChoiceMode(AbsListView.CHOICE_MODE_SINGLE);
+ }
+
+ if (mSinglePane && initialFragment != null && initialTitle != 0) {
+ CharSequence initialTitleStr = getText(initialTitle);
+ CharSequence initialShortTitleStr = initialShortTitle != 0
+ ? getText(initialShortTitle) : null;
+ showBreadCrumbs(initialTitleStr, initialShortTitleStr);
+ }
+
+ if (mHeaders.size() == 0 && initialFragment == null) {
// If there are no headers, we are in the old "just show a screen
// of preferences" mode.
setContentView(com.android.internal.R.layout.preference_list_content_single);
@@ -642,6 +620,25 @@
mPrefsContainer = (ViewGroup) findViewById(com.android.internal.R.id.prefs);
mPreferenceManager = new PreferenceManager(this, FIRST_REQUEST_CODE);
mPreferenceManager.setOnPreferenceTreeClickListener(this);
+ mHeadersContainer = null;
+ } else if (mSinglePane) {
+ // Single-pane so one of the header or prefs containers must be hidden.
+ if (initialFragment != null || mCurHeader != null) {
+ mHeadersContainer.setVisibility(View.GONE);
+ } else {
+ mPrefsContainer.setVisibility(View.GONE);
+ }
+
+ // This animates our manual transitions between headers and prefs panel in single-pane.
+ // It also comes last so we don't animate any initial layout changes done above.
+ ViewGroup container = (ViewGroup) findViewById(
+ com.android.internal.R.id.prefs_container);
+ container.setLayoutTransition(new LayoutTransition());
+ } else {
+ // Multi-pane
+ if (mHeaders.size() > 0 && mCurHeader != null) {
+ setSelectedHeader(mCurHeader);
+ }
}
// see if we should show Back/Next buttons
@@ -697,12 +694,25 @@
}
}
+ @Override
+ public void onBackPressed() {
+ if (mCurHeader != null && mSinglePane && getFragmentManager().getBackStackEntryCount() == 0
+ && getIntent().getStringExtra(EXTRA_SHOW_FRAGMENT) == null) {
+ mCurHeader = null;
+
+ mPrefsContainer.setVisibility(View.GONE);
+ mHeadersContainer.setVisibility(View.VISIBLE);
+ getListView().clearChoices();
+ } else {
+ super.onBackPressed();
+ }
+ }
+
/**
* Returns true if this activity is currently showing the header list.
*/
public boolean hasHeaders() {
- return getListView().getVisibility() == View.VISIBLE
- && mPreferenceManager == null;
+ return mHeadersContainer != null && mHeadersContainer.getVisibility() == View.VISIBLE;
}
/**
@@ -718,7 +728,7 @@
* and a preference fragment.
*/
public boolean isMultiPane() {
- return hasHeaders() && mPrefsContainer.getVisibility() == View.VISIBLE;
+ return !mSinglePane;
}
/**
@@ -820,14 +830,14 @@
if (!"preference-headers".equals(nodeName)) {
throw new RuntimeException(
"XML document must start with <preference-headers> tag; found"
- + nodeName + " at " + parser.getPositionDescription());
+ + nodeName + " at " + parser.getPositionDescription());
}
Bundle curBundle = null;
final int outerDepth = parser.getDepth();
while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
- && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+ && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
continue;
}
@@ -889,7 +899,7 @@
final int innerDepth = parser.getDepth();
while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
- && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
+ && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
continue;
}
@@ -939,8 +949,9 @@
if (getApplicationInfo().targetSdkVersion >= android.os.Build.VERSION_CODES.KITKAT) {
throw new RuntimeException(
"Subclasses of PreferenceActivity must override isValidFragment(String)"
- + " to verify that the Fragment class is valid! " + this.getClass().getName()
- + " has not checked if fragment " + fragmentName + " is valid.");
+ + " to verify that the Fragment class is valid! "
+ + this.getClass().getName()
+ + " has not checked if fragment " + fragmentName + " is valid.");
} else {
return true;
}
@@ -1017,6 +1028,13 @@
// Only call this if we didn't save the instance state for later.
// If we did save it, it will be restored when we bind the adapter.
super.onRestoreInstanceState(state);
+
+ if (!mSinglePane) {
+ // Multi-pane.
+ if (mCurHeader != null) {
+ setSelectedHeader(mCurHeader);
+ }
+ }
}
@Override
@@ -1061,18 +1079,7 @@
*/
public void onHeaderClick(Header header, int position) {
if (header.fragment != null) {
- if (mSinglePane) {
- int titleRes = header.breadCrumbTitleRes;
- int shortTitleRes = header.breadCrumbShortTitleRes;
- if (titleRes == 0) {
- titleRes = header.titleRes;
- shortTitleRes = 0;
- }
- startWithFragment(header.fragment, header.fragmentArguments, null, 0,
- titleRes, shortTitleRes);
- } else {
- switchToHeader(header);
- }
+ switchToHeader(header);
} else if (header.intent != null) {
startActivity(header.intent);
}
@@ -1084,7 +1091,7 @@
* the selected fragment. The default implementation constructs an Intent
* that re-launches the current activity with the appropriate arguments to
* display the fragment.
- *
+ *
* @param fragmentName The name of the fragment to display.
* @param args Optional arguments to supply to the fragment.
* @param titleRes Optional resource ID of title to show for this item.
@@ -1103,7 +1110,7 @@
intent.putExtra(EXTRA_NO_HEADERS, true);
return intent;
}
-
+
/**
* Like {@link #startWithFragment(String, Bundle, Fragment, int, int, int)}
* but uses a 0 titleRes.
@@ -1223,11 +1230,21 @@
throw new IllegalArgumentException("Invalid fragment for this activity: "
+ fragmentName);
}
+
Fragment f = Fragment.instantiate(this, fragmentName, args);
FragmentTransaction transaction = getFragmentManager().beginTransaction();
- transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
+ transaction.setTransition(mSinglePane
+ ? FragmentTransaction.TRANSIT_NONE
+ : FragmentTransaction.TRANSIT_FRAGMENT_FADE);
transaction.replace(com.android.internal.R.id.prefs, f);
transaction.commitAllowingStateLoss();
+
+ if (mSinglePane && mPrefsContainer.getVisibility() == View.GONE) {
+ // We are transitioning from headers to preferences panel in single-pane so we need
+ // to hide headers and show the prefs container.
+ mPrefsContainer.setVisibility(View.VISIBLE);
+ mHeadersContainer.setVisibility(View.GONE);
+ }
}
/**
@@ -1340,7 +1357,7 @@
* be instantiated and placed in the appropriate pane. If running in
* single-pane mode, a new activity will be launched in which to show the
* fragment.
- *
+ *
* @param fragmentClass Full name of the class implementing the fragment.
* @param args Any desired arguments to supply to the fragment.
* @param titleRes Optional resource identifier of the title of this
@@ -1355,29 +1372,25 @@
*/
public void startPreferencePanel(String fragmentClass, Bundle args, @StringRes int titleRes,
CharSequence titleText, Fragment resultTo, int resultRequestCode) {
- if (mSinglePane) {
- startWithFragment(fragmentClass, args, resultTo, resultRequestCode, titleRes, 0);
- } else {
- Fragment f = Fragment.instantiate(this, fragmentClass, args);
- if (resultTo != null) {
- f.setTargetFragment(resultTo, resultRequestCode);
- }
- FragmentTransaction transaction = getFragmentManager().beginTransaction();
- transaction.replace(com.android.internal.R.id.prefs, f);
- if (titleRes != 0) {
- transaction.setBreadCrumbTitle(titleRes);
- } else if (titleText != null) {
- transaction.setBreadCrumbTitle(titleText);
- }
- transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
- transaction.addToBackStack(BACK_STACK_PREFS);
- transaction.commitAllowingStateLoss();
+ Fragment f = Fragment.instantiate(this, fragmentClass, args);
+ if (resultTo != null) {
+ f.setTargetFragment(resultTo, resultRequestCode);
}
+ FragmentTransaction transaction = getFragmentManager().beginTransaction();
+ transaction.replace(com.android.internal.R.id.prefs, f);
+ if (titleRes != 0) {
+ transaction.setBreadCrumbTitle(titleRes);
+ } else if (titleText != null) {
+ transaction.setBreadCrumbTitle(titleText);
+ }
+ transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
+ transaction.addToBackStack(BACK_STACK_PREFS);
+ transaction.commitAllowingStateLoss();
}
/**
* Called by a preference panel fragment to finish itself.
- *
+ *
* @param caller The fragment that is asking to be finished.
* @param resultCode Optional result code to send back to the original
* launching fragment.
@@ -1385,21 +1398,16 @@
* launching fragment.
*/
public void finishPreferencePanel(Fragment caller, int resultCode, Intent resultData) {
- if (mSinglePane) {
- setResult(resultCode, resultData);
- finish();
- } else {
- // XXX be smarter about popping the stack.
- onBackPressed();
- if (caller != null) {
- if (caller.getTargetFragment() != null) {
- caller.getTargetFragment().onActivityResult(caller.getTargetRequestCode(),
- resultCode, resultData);
- }
+ // TODO: be smarter about popping the stack.
+ onBackPressed();
+ if (caller != null) {
+ if (caller.getTargetFragment() != null) {
+ caller.getTargetFragment().onActivityResult(caller.getTargetRequestCode(),
+ resultCode, resultData);
}
}
}
-
+
@Override
public boolean onPreferenceStartFragment(PreferenceFragment caller, Preference pref) {
startPreferencePanel(pref.getFragment(), pref.getExtras(), pref.getTitleRes(),
diff --git a/core/java/android/provider/OneTimeUseBuilder.java b/core/java/android/provider/OneTimeUseBuilder.java
new file mode 100644
index 0000000..682e9c7
--- /dev/null
+++ b/core/java/android/provider/OneTimeUseBuilder.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2017 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.provider;
+
+/**
+ * A builder that facilitates prohibiting its use after an instance was created with it.
+ *
+ * Suggested usage:
+ * call {@link #checkNotUsed} in each setter, and {@link #markUsed} in {@link #build}
+ *
+ * @param <T> Type of object being built
+ * @hide
+ */
+public abstract class OneTimeUseBuilder<T> {
+ private boolean used = false;
+
+ protected void markUsed() {
+ checkNotUsed();
+ used = true;
+ }
+
+ protected void checkNotUsed() {
+ if (used) {
+ throw new IllegalStateException(
+ "This Builder should not be reused. Use a new Builder instance instead");
+ }
+ }
+
+ /**
+ * Builds the instance
+ *
+ * Once this method is called, this builder should no longer be used. Any subsequent calls to a
+ * setter or {@code build()} will throw an exception
+ */
+ public abstract T build();
+}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index d83f2cb..2936dfb 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -6721,12 +6721,6 @@
public static final String NIGHT_DISPLAY_CUSTOM_END_TIME = "night_display_custom_end_time";
/**
- * Whether brightness should automatically adjust based on twilight state.
- * @hide
- */
- public static final String BRIGHTNESS_USE_TWILIGHT = "brightness_use_twilight";
-
- /**
* Names of the service components that the current user has explicitly allowed to
* be a VR mode listener, separated by ':'.
*
diff --git a/core/java/android/provider/SettingsStringUtil.java b/core/java/android/provider/SettingsStringUtil.java
new file mode 100644
index 0000000..f242d79
--- /dev/null
+++ b/core/java/android/provider/SettingsStringUtil.java
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2017 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.provider;
+
+import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.text.TextUtils;
+
+import com.android.internal.util.ArrayUtils;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.function.Function;
+
+/**
+ * Utilities for dealing with {@link String} values in {@link Settings}
+ *
+ * @hide
+ */
+public class SettingsStringUtil {
+ private SettingsStringUtil() {}
+
+ public static final String DELIMITER = ":";
+
+ /**
+ * A {@link HashSet} of items, that uses a common convention of setting string
+ * serialization/deserialization of separating multiple items with {@link #DELIMITER}
+ */
+ public static abstract class ColonDelimitedSet<T> extends HashSet<T> {
+
+ public ColonDelimitedSet(String colonSeparatedItems) {
+ for (String cn :
+ TextUtils.split(TextUtils.emptyIfNull(colonSeparatedItems), DELIMITER)) {
+ add(itemFromString(cn));
+ }
+ }
+
+ protected abstract T itemFromString(String s);
+ protected String itemToString(T item) {
+ return String.valueOf(item);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ Iterator<T> it = iterator();
+ if (it.hasNext()) {
+ sb.append(it.next());
+ while (it.hasNext()) {
+ sb.append(DELIMITER);
+ sb.append(itemToString(it.next()));
+ }
+ }
+ return sb.toString();
+ }
+
+
+ public static class OfStrings extends ColonDelimitedSet<String> {
+ public OfStrings(String colonSeparatedItems) {
+ super(colonSeparatedItems);
+ }
+
+ @Override
+ protected String itemFromString(String s) {
+ return s;
+ }
+
+ public static String add(String delimitedElements, String element) {
+ final ColonDelimitedSet<String> set
+ = new ColonDelimitedSet.OfStrings(delimitedElements);
+ if (set.contains(element)) {
+ return delimitedElements;
+ }
+ set.add(element);
+ return set.toString();
+ }
+
+ public static String remove(String delimitedElements, String element) {
+ final ColonDelimitedSet<String> set
+ = new ColonDelimitedSet.OfStrings(delimitedElements);
+ if (!set.contains(element)) {
+ return delimitedElements;
+ }
+ set.remove(element);
+ return set.toString();
+ }
+
+ public static boolean contains(String delimitedElements, String element) {
+ final String[] elements = TextUtils.split(delimitedElements, DELIMITER);
+ return ArrayUtils.indexOf(elements, element) != -1;
+ }
+ }
+ }
+
+ public static class ComponentNameSet extends ColonDelimitedSet<ComponentName> {
+ public ComponentNameSet(String colonSeparatedPackageNames) {
+ super(colonSeparatedPackageNames);
+ }
+
+ @Override
+ protected ComponentName itemFromString(String s) {
+ return ComponentName.unflattenFromString(s);
+ }
+
+ @Override
+ protected String itemToString(ComponentName item) {
+ return item.flattenToString();
+ }
+
+ public static String add(String delimitedElements, ComponentName element) {
+ final ComponentNameSet set = new ComponentNameSet(delimitedElements);
+ if (set.contains(element)) {
+ return delimitedElements;
+ }
+ set.add(element);
+ return set.toString();
+ }
+
+ public static String remove(String delimitedElements, ComponentName element) {
+ final ComponentNameSet set = new ComponentNameSet(delimitedElements);
+ if (!set.contains(element)) {
+ return delimitedElements;
+ }
+ set.remove(element);
+ return set.toString();
+ }
+
+ public static boolean contains(String delimitedElements, ComponentName element) {
+ return ColonDelimitedSet.OfStrings.contains(
+ delimitedElements, element.flattenToString());
+ }
+ }
+
+ public static class SettingStringHelper {
+ private final ContentResolver mContentResolver;
+ private final String mSettingName;
+ private final int mUserId;
+
+ public SettingStringHelper(ContentResolver contentResolver, String name, int userId) {
+ mContentResolver = contentResolver;
+ mUserId = userId;
+ mSettingName = name;
+ }
+
+ public String read() {
+ return Settings.Secure.getStringForUser(
+ mContentResolver, mSettingName, mUserId);
+ }
+
+ public boolean write(String value) {
+ return Settings.Secure.putStringForUser(
+ mContentResolver, mSettingName, value, mUserId);
+ }
+
+ public boolean modify(Function<String, String> change) {
+ return write(change.apply(read()));
+ }
+ }
+}
diff --git a/core/java/android/service/quicksettings/TileService.java b/core/java/android/service/quicksettings/TileService.java
index 887f4b6..1781c2a 100644
--- a/core/java/android/service/quicksettings/TileService.java
+++ b/core/java/android/service/quicksettings/TileService.java
@@ -130,6 +130,11 @@
*/
public static final String EXTRA_COMPONENT = "android.service.quicksettings.extra.COMPONENT";
+ /**
+ * @hide
+ */
+ public static final String EXTRA_STATE = "state";
+
private final H mHandler = new H(Looper.getMainLooper());
private boolean mListening = false;
diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java
index bb952ab..55aeb1e 100644
--- a/core/java/android/text/TextUtils.java
+++ b/core/java/android/text/TextUtils.java
@@ -62,6 +62,7 @@
import com.android.internal.R;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.Preconditions;
import java.lang.reflect.Array;
import java.util.Iterator;
@@ -466,6 +467,16 @@
return isEmpty(str) ? null : str;
}
+ /** {@hide} */
+ public static String emptyIfNull(@Nullable String str) {
+ return str == null ? "" : str;
+ }
+
+ /** {@hide} */
+ public static String firstNotEmpty(@Nullable String a, @NonNull String b) {
+ return !isEmpty(a) ? a : Preconditions.checkStringNotEmpty(b);
+ }
+
/**
* Returns the length that the specified CharSequence would have if
* spaces and ASCII control characters were trimmed from the start and end,
diff --git a/core/java/android/text/style/ClickableSpan.java b/core/java/android/text/style/ClickableSpan.java
index a183427..b098f16 100644
--- a/core/java/android/text/style/ClickableSpan.java
+++ b/core/java/android/text/style/ClickableSpan.java
@@ -22,7 +22,7 @@
/**
* If an object of this type is attached to the text of a TextView
* with a movement method of LinkMovementMethod, the affected spans of
- * text can be selected. If clicked, the {@link #onClick} method will
+ * text can be selected. If selected and clicked, the {@link #onClick} method will
* be called.
*/
public abstract class ClickableSpan extends CharacterStyle implements UpdateAppearance {
diff --git a/core/java/android/transition/ChangeTransform.java b/core/java/android/transition/ChangeTransform.java
index 584c114..5303855 100644
--- a/core/java/android/transition/ChangeTransform.java
+++ b/core/java/android/transition/ChangeTransform.java
@@ -141,9 +141,10 @@
* child view will be relative to its parent's final position, so it may appear to "jump"
* at the beginning.</p>
*
- * @return <code>true</code> when a changed parent should execute the transition
- * inside the scene root's overlay or <code>false</code> if a parent change only
- * affects the transform of the transitioning view.
+ * @param reparentWithOverlay <code>true</code> when a changed parent should execute the
+ * transition inside the scene root's overlay or <code>false</code>
+ * if a parent change only affects the transform of the transitioning
+ * view.
* @attr ref android.R.styleable#ChangeTransform_reparentWithOverlay
*/
public void setReparentWithOverlay(boolean reparentWithOverlay) {
diff --git a/core/java/android/view/NotificationHeaderView.java b/core/java/android/view/NotificationHeaderView.java
index 0da710a..c3d3f39 100644
--- a/core/java/android/view/NotificationHeaderView.java
+++ b/core/java/android/view/NotificationHeaderView.java
@@ -17,6 +17,7 @@
package android.view;
import android.annotation.Nullable;
+import android.app.Notification;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Outline;
@@ -39,7 +40,7 @@
*/
@RemoteViews.RemoteView
public class NotificationHeaderView extends ViewGroup {
- public static final int NO_COLOR = -1;
+ public static final int NO_COLOR = Notification.COLOR_INVALID;
private final int mChildMinWidth;
private final int mContentEndMargin;
private View mAppName;
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index e2eee95..a150529 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -19942,9 +19942,9 @@
* @return the view of the specified id, null if cannot be found
* @hide
*/
- protected <T extends View> T findViewTraversal(@IdRes int id) {
+ protected View findViewTraversal(@IdRes int id) {
if (id == mID) {
- return (T) this;
+ return this;
}
return null;
}
@@ -19954,9 +19954,9 @@
* @return the view of specified tag, null if cannot be found
* @hide
*/
- protected <T extends View> T findViewWithTagTraversal(Object tag) {
+ protected View findViewWithTagTraversal(Object tag) {
if (tag != null && tag.equals(mTag)) {
- return (T) this;
+ return this;
}
return null;
}
@@ -19967,10 +19967,9 @@
* @return The first view that matches the predicate or null.
* @hide
*/
- protected <T extends View> T findViewByPredicateTraversal(Predicate<View> predicate,
- View childToSkip) {
+ protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
if (predicate.apply(this)) {
- return (T) this;
+ return this;
}
return null;
}
@@ -19983,7 +19982,7 @@
* @return The view that has the given id in the hierarchy or null
*/
@Nullable
- public final <T extends View> T findViewById(@IdRes int id) {
+ public final View findViewById(@IdRes int id) {
if (id < 0) {
return null;
}
@@ -19996,11 +19995,11 @@
* @param accessibilityId The searched accessibility id.
* @return The found view.
*/
- final <T extends View> T findViewByAccessibilityId(int accessibilityId) {
+ final View findViewByAccessibilityId(int accessibilityId) {
if (accessibilityId < 0) {
return null;
}
- T view = findViewByAccessibilityIdTraversal(accessibilityId);
+ View view = findViewByAccessibilityIdTraversal(accessibilityId);
if (view != null) {
return view.includeForAccessibility() ? view : null;
}
@@ -20019,11 +20018,12 @@
*
* @param accessibilityId The accessibility id.
* @return The found view.
+ *
* @hide
*/
- public <T extends View> T findViewByAccessibilityIdTraversal(int accessibilityId) {
+ public View findViewByAccessibilityIdTraversal(int accessibilityId) {
if (getAccessibilityViewId() == accessibilityId) {
- return (T) this;
+ return this;
}
return null;
}
@@ -20035,7 +20035,7 @@
* @param tag The tag to search for, using "tag.equals(getTag())".
* @return The View that has the given tag in the hierarchy or null
*/
- public final <T extends View> T findViewWithTag(Object tag) {
+ public final View findViewWithTag(Object tag) {
if (tag == null) {
return null;
}
@@ -20050,7 +20050,7 @@
* @return The first view that matches the predicate or null.
* @hide
*/
- public final <T extends View> T findViewByPredicate(Predicate<View> predicate) {
+ public final View findViewByPredicate(Predicate<View> predicate) {
return findViewByPredicateTraversal(predicate, null);
}
@@ -20070,11 +20070,10 @@
* @return The first view that matches the predicate or null.
* @hide
*/
- public final <T extends View> T findViewByPredicateInsideOut(
- View start, Predicate<View> predicate) {
+ public final View findViewByPredicateInsideOut(View start, Predicate<View> predicate) {
View childToSkip = null;
for (;;) {
- T view = start.findViewByPredicateTraversal(predicate, childToSkip);
+ View view = start.findViewByPredicateTraversal(predicate, childToSkip);
if (view != null || start == this) {
return view;
}
@@ -24660,7 +24659,7 @@
* Determine if this view is rendered on a round wearable device and is the main view
* on the screen.
*/
- private boolean shouldDrawRoundScrollbar() {
+ boolean shouldDrawRoundScrollbar() {
if (!mResources.getConfiguration().isScreenRound() || mAttachInfo == null) {
return false;
}
@@ -24677,7 +24676,7 @@
return false;
}
- getLocationOnScreen(mAttachInfo.mTmpLocation);
+ getLocationInWindow(mAttachInfo.mTmpLocation);
return mAttachInfo.mTmpLocation[0] == insets.getStableInsetLeft()
&& mAttachInfo.mTmpLocation[1] == insets.getStableInsetTop();
}
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index b11b3d7..aa580fa 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -4208,9 +4208,9 @@
* {@hide}
*/
@Override
- protected <T extends View> T findViewTraversal(@IdRes int id) {
+ protected View findViewTraversal(@IdRes int id) {
if (id == mID) {
- return (T) this;
+ return this;
}
final View[] where = mChildren;
@@ -4223,7 +4223,7 @@
v = v.findViewById(id);
if (v != null) {
- return (T) v;
+ return v;
}
}
}
@@ -4235,9 +4235,9 @@
* {@hide}
*/
@Override
- protected <T extends View> T findViewWithTagTraversal(Object tag) {
+ protected View findViewWithTagTraversal(Object tag) {
if (tag != null && tag.equals(mTag)) {
- return (T) this;
+ return this;
}
final View[] where = mChildren;
@@ -4250,7 +4250,7 @@
v = v.findViewWithTag(tag);
if (v != null) {
- return (T) v;
+ return v;
}
}
}
@@ -4262,10 +4262,9 @@
* {@hide}
*/
@Override
- protected <T extends View> T findViewByPredicateTraversal(Predicate<View> predicate,
- View childToSkip) {
+ protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
if (predicate.apply(this)) {
- return (T) this;
+ return this;
}
final View[] where = mChildren;
@@ -4278,7 +4277,7 @@
v = v.findViewByPredicate(predicate);
if (v != null) {
- return (T) v;
+ return v;
}
}
}
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index 1ef0d17..45302b6 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -779,6 +779,49 @@
}
}
+ /**
+ * Notifies that the accessibility button in the system's navigation area has been clicked
+ *
+ * @hide
+ */
+ public void notifyAccessibilityButtonClicked() {
+ final IAccessibilityManager service;
+ synchronized (mLock) {
+ service = getServiceLocked();
+ if (service == null) {
+ return;
+ }
+ }
+ try {
+ service.notifyAccessibilityButtonClicked();
+ } catch (RemoteException re) {
+ Log.e(LOG_TAG, "Error while dispatching accessibility button click", re);
+ }
+ }
+
+ /**
+ * Notifies that the availability of the accessibility button in the system's navigation area
+ * has changed.
+ *
+ * @param available {@code true} if the accessibility button is available within the system
+ * navigation area, {@code false} otherwise
+ * @hide
+ */
+ public void notifyAccessibilityButtonAvailabilityChanged(boolean available) {
+ final IAccessibilityManager service;
+ synchronized (mLock) {
+ service = getServiceLocked();
+ if (service == null) {
+ return;
+ }
+ }
+ try {
+ service.notifyAccessibilityButtonAvailabilityChanged(available);
+ } catch (RemoteException re) {
+ Log.e(LOG_TAG, "Error while dispatching accessibility button availability change", re);
+ }
+ }
+
private IAccessibilityManager getServiceLocked() {
if (mService == null) {
tryConnectToServiceLocked(null);
diff --git a/core/java/android/view/accessibility/IAccessibilityManager.aidl b/core/java/android/view/accessibility/IAccessibilityManager.aidl
index 136bbbe..8fde47a 100644
--- a/core/java/android/view/accessibility/IAccessibilityManager.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityManager.aidl
@@ -59,6 +59,10 @@
IBinder getWindowToken(int windowId, int userId);
+ void notifyAccessibilityButtonClicked();
+
+ void notifyAccessibilityButtonAvailabilityChanged(boolean available);
+
// Requires WRITE_SECURE_SETTINGS
void performAccessibilityShortcut();
diff --git a/core/java/android/widget/ActivityChooserView.java b/core/java/android/widget/ActivityChooserView.java
index 9a39a17..51587a7 100644
--- a/core/java/android/widget/ActivityChooserView.java
+++ b/core/java/android/widget/ActivityChooserView.java
@@ -250,7 +250,7 @@
mDefaultActivityButton = (FrameLayout) findViewById(R.id.default_activity_button);
mDefaultActivityButton.setOnClickListener(mCallbacks);
mDefaultActivityButton.setOnLongClickListener(mCallbacks);
- mDefaultActivityButtonImage = mDefaultActivityButton.findViewById(R.id.image);
+ mDefaultActivityButtonImage = (ImageView) mDefaultActivityButton.findViewById(R.id.image);
final FrameLayout expandButton = (FrameLayout) findViewById(R.id.expand_activities_button);
expandButton.setOnClickListener(mCallbacks);
@@ -282,7 +282,7 @@
mExpandActivityOverflowButton = expandButton;
mExpandActivityOverflowButtonImage =
- expandButton.findViewById(R.id.image);
+ (ImageView) expandButton.findViewById(R.id.image);
mExpandActivityOverflowButtonImage.setImageDrawable(expandActivityOverflowButtonDrawable);
mAdapter = new ActivityChooserViewAdapter();
@@ -760,7 +760,7 @@
convertView = LayoutInflater.from(getContext()).inflate(
R.layout.activity_chooser_view_list_item, parent, false);
convertView.setId(ITEM_VIEW_TYPE_FOOTER);
- TextView titleView = convertView.findViewById(R.id.title);
+ TextView titleView = (TextView) convertView.findViewById(R.id.title);
titleView.setText(mContext.getString(
R.string.activity_chooser_view_see_all));
}
@@ -772,11 +772,11 @@
}
PackageManager packageManager = mContext.getPackageManager();
// Set the icon
- ImageView iconView = convertView.findViewById(R.id.icon);
+ ImageView iconView = (ImageView) convertView.findViewById(R.id.icon);
ResolveInfo activity = (ResolveInfo) getItem(position);
iconView.setImageDrawable(activity.loadIcon(packageManager));
// Set the title.
- TextView titleView = convertView.findViewById(R.id.title);
+ TextView titleView = (TextView) convertView.findViewById(R.id.title);
titleView.setText(activity.loadLabel(packageManager));
// Highlight the default.
if (mShowDefaultActivity && position == 0 && mHighlightDefaultActivity) {
diff --git a/core/java/android/widget/AppSecurityPermissions.java b/core/java/android/widget/AppSecurityPermissions.java
index 06d4868..68e6809 100644
--- a/core/java/android/widget/AppSecurityPermissions.java
+++ b/core/java/android/widget/AppSecurityPermissions.java
@@ -451,7 +451,7 @@
private View getPermissionsView(int which, boolean showRevokeUI) {
LinearLayout permsView = (LinearLayout) mInflater.inflate(R.layout.app_perms_summary, null);
- LinearLayout displayList = permsView.findViewById(R.id.perms_list);
+ LinearLayout displayList = (LinearLayout) permsView.findViewById(R.id.perms_list);
View noPermsView = permsView.findViewById(R.id.no_permissions);
displayPermissions(mPermGroupsList, displayList, which, showRevokeUI);
@@ -517,8 +517,8 @@
CharSequence grpName, CharSequence permList, boolean dangerous, Drawable icon) {
View permView = inflater.inflate(R.layout.app_permission_item_old, null);
- TextView permGrpView = permView.findViewById(R.id.permission_group);
- TextView permDescView = permView.findViewById(R.id.permission_list);
+ TextView permGrpView = (TextView) permView.findViewById(R.id.permission_group);
+ TextView permDescView = (TextView) permView.findViewById(R.id.permission_list);
ImageView imgView = (ImageView)permView.findViewById(R.id.perm_icon);
imgView.setImageDrawable(icon);
diff --git a/core/java/android/widget/ArrayAdapter.java b/core/java/android/widget/ArrayAdapter.java
index 81f0d3d..bbc50da 100644
--- a/core/java/android/widget/ArrayAdapter.java
+++ b/core/java/android/widget/ArrayAdapter.java
@@ -388,7 +388,7 @@
text = (TextView) view;
} else {
// Otherwise, find the TextView field within the layout
- text = view.findViewById(mFieldId);
+ text = (TextView) view.findViewById(mFieldId);
if (text == null) {
throw new RuntimeException("Failed to find view with ID "
diff --git a/core/java/android/widget/CalendarViewLegacyDelegate.java b/core/java/android/widget/CalendarViewLegacyDelegate.java
index 1b899db..557d411 100644
--- a/core/java/android/widget/CalendarViewLegacyDelegate.java
+++ b/core/java/android/widget/CalendarViewLegacyDelegate.java
@@ -316,9 +316,9 @@
View content = layoutInflater.inflate(R.layout.calendar_view, null, false);
mDelegator.addView(content);
- mListView = mDelegator.findViewById(R.id.list);
- mDayNamesHeader = content.findViewById(R.id.day_names);
- mMonthName = content.findViewById(R.id.month_name);
+ mListView = (ListView) mDelegator.findViewById(R.id.list);
+ mDayNamesHeader = (ViewGroup) content.findViewById(R.id.day_names);
+ mMonthName = (TextView) content.findViewById(R.id.month_name);
setUpHeader();
setUpListView();
diff --git a/core/java/android/widget/DatePickerCalendarDelegate.java b/core/java/android/widget/DatePickerCalendarDelegate.java
index 907250a..f712685 100755
--- a/core/java/android/widget/DatePickerCalendarDelegate.java
+++ b/core/java/android/widget/DatePickerCalendarDelegate.java
@@ -115,10 +115,10 @@
mDelegator.addView(mContainer);
// Set up header views.
- final ViewGroup header = mContainer.findViewById(R.id.date_picker_header);
- mHeaderYear = header.findViewById(R.id.date_picker_header_year);
+ final ViewGroup header = (ViewGroup) mContainer.findViewById(R.id.date_picker_header);
+ mHeaderYear = (TextView) header.findViewById(R.id.date_picker_header_year);
mHeaderYear.setOnClickListener(mOnHeaderClickListener);
- mHeaderMonthDay = header.findViewById(R.id.date_picker_header_date);
+ mHeaderMonthDay = (TextView) header.findViewById(R.id.date_picker_header_date);
mHeaderMonthDay.setOnClickListener(mOnHeaderClickListener);
// For the sake of backwards compatibility, attempt to extract the text
@@ -154,10 +154,10 @@
a.recycle();
// Set up picker container.
- mAnimator = mContainer.findViewById(R.id.animator);
+ mAnimator = (ViewAnimator) mContainer.findViewById(R.id.animator);
// Set up day picker view.
- mDayPickerView = mAnimator.findViewById(R.id.date_picker_day_picker);
+ mDayPickerView = (DayPickerView) mAnimator.findViewById(R.id.date_picker_day_picker);
mDayPickerView.setFirstDayOfWeek(mFirstDayOfWeek);
mDayPickerView.setMinDate(mMinDate.getTimeInMillis());
mDayPickerView.setMaxDate(mMaxDate.getTimeInMillis());
@@ -165,7 +165,7 @@
mDayPickerView.setOnDaySelectedListener(mOnDaySelectedListener);
// Set up year picker view.
- mYearPickerView = mAnimator.findViewById(R.id.date_picker_year_picker);
+ mYearPickerView = (YearPickerView) mAnimator.findViewById(R.id.date_picker_year_picker);
mYearPickerView.setRange(mMinDate, mMaxDate);
mYearPickerView.setYear(mCurrentDate.get(Calendar.YEAR));
mYearPickerView.setOnYearSelectedListener(mOnYearSelectedListener);
diff --git a/core/java/android/widget/DayPickerPagerAdapter.java b/core/java/android/widget/DayPickerPagerAdapter.java
index 63621e1..8d5bf8f 100644
--- a/core/java/android/widget/DayPickerPagerAdapter.java
+++ b/core/java/android/widget/DayPickerPagerAdapter.java
@@ -225,7 +225,7 @@
public Object instantiateItem(ViewGroup container, int position) {
final View itemView = mInflater.inflate(mLayoutResId, container, false);
- final SimpleMonthView v = itemView.findViewById(mCalendarViewId);
+ final SimpleMonthView v = (SimpleMonthView) itemView.findViewById(mCalendarViewId);
v.setOnDayClickListener(mOnDayClickListener);
v.setMonthTextAppearance(mMonthTextAppearance);
v.setDayOfWeekTextAppearance(mDayOfWeekTextAppearance);
diff --git a/core/java/android/widget/DayPickerViewPager.java b/core/java/android/widget/DayPickerViewPager.java
index 058baa6..94022ae 100644
--- a/core/java/android/widget/DayPickerViewPager.java
+++ b/core/java/android/widget/DayPickerViewPager.java
@@ -137,10 +137,9 @@
}
@Override
- protected <T extends View> T findViewByPredicateTraversal(Predicate<View> predicate,
- View childToSkip) {
+ protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
if (predicate.apply(this)) {
- return (T) this;
+ return this;
}
// Always try the selected view first.
@@ -149,7 +148,7 @@
if (current != childToSkip && current != null) {
final View v = current.findViewByPredicate(predicate);
if (v != null) {
- return (T) v;
+ return v;
}
}
@@ -161,7 +160,7 @@
final View v = child.findViewByPredicate(predicate);
if (v != null) {
- return (T) v;
+ return v;
}
}
}
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index b7da04e..80780a6 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -3740,21 +3740,20 @@
* @removed For internal use only. This should have been hidden.
*/
@Override
- protected <T extends View> T findViewTraversal(@IdRes int id) {
- // First look in our children, then in any header and footer views that
- // may be scrolled off.
- View v = super.findViewTraversal(id);
+ protected View findViewTraversal(@IdRes int id) {
+ View v;
+ v = super.findViewTraversal(id);
if (v == null) {
v = findViewInHeadersOrFooters(mHeaderViewInfos, id);
if (v != null) {
- return (T) v;
+ return v;
}
v = findViewInHeadersOrFooters(mFooterViewInfos, id);
if (v != null) {
- return (T) v;
+ return v;
}
}
- return (T) v;
+ return v;
}
View findViewInHeadersOrFooters(ArrayList<FixedViewInfo> where, int id) {
@@ -3783,22 +3782,21 @@
* @removed For internal use only. This should have been hidden.
*/
@Override
- protected <T extends View> T findViewWithTagTraversal(Object tag) {
- // First look in our children, then in any header and footer views that
- // may be scrolled off.
- View v = super.findViewWithTagTraversal(tag);
+ protected View findViewWithTagTraversal(Object tag) {
+ View v;
+ v = super.findViewWithTagTraversal(tag);
if (v == null) {
v = findViewWithTagInHeadersOrFooters(mHeaderViewInfos, tag);
if (v != null) {
- return (T) v;
+ return v;
}
v = findViewWithTagInHeadersOrFooters(mFooterViewInfos, tag);
if (v != null) {
- return (T) v;
+ return v;
}
}
- return (T) v;
+ return v;
}
View findViewWithTagInHeadersOrFooters(ArrayList<FixedViewInfo> where, Object tag) {
@@ -3831,21 +3829,21 @@
* @hide
*/
@Override
- protected <T extends View> T findViewByPredicateTraversal(
- Predicate<View> predicate, View childToSkip) {
- View v = super.findViewByPredicateTraversal(predicate, childToSkip);
+ protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
+ View v;
+ v = super.findViewByPredicateTraversal(predicate, childToSkip);
if (v == null) {
v = findViewByPredicateInHeadersOrFooters(mHeaderViewInfos, predicate, childToSkip);
if (v != null) {
- return (T) v;
+ return v;
}
v = findViewByPredicateInHeadersOrFooters(mFooterViewInfos, predicate, childToSkip);
if (v != null) {
- return (T) v;
+ return v;
}
}
- return (T) v;
+ return v;
}
/**
diff --git a/core/java/android/widget/MediaController.java b/core/java/android/widget/MediaController.java
index 8e04f1c..8008637 100644
--- a/core/java/android/widget/MediaController.java
+++ b/core/java/android/widget/MediaController.java
@@ -257,13 +257,13 @@
.getText(com.android.internal.R.string.lockscreen_transport_play_description);
mPauseDescription = res
.getText(com.android.internal.R.string.lockscreen_transport_pause_description);
- mPauseButton = v.findViewById(com.android.internal.R.id.pause);
+ mPauseButton = (ImageButton) v.findViewById(com.android.internal.R.id.pause);
if (mPauseButton != null) {
mPauseButton.requestFocus();
mPauseButton.setOnClickListener(mPauseListener);
}
- mFfwdButton = v.findViewById(com.android.internal.R.id.ffwd);
+ mFfwdButton = (ImageButton) v.findViewById(com.android.internal.R.id.ffwd);
if (mFfwdButton != null) {
mFfwdButton.setOnClickListener(mFfwdListener);
if (!mFromXml) {
@@ -271,7 +271,7 @@
}
}
- mRewButton = v.findViewById(com.android.internal.R.id.rew);
+ mRewButton = (ImageButton) v.findViewById(com.android.internal.R.id.rew);
if (mRewButton != null) {
mRewButton.setOnClickListener(mRewListener);
if (!mFromXml) {
@@ -280,16 +280,16 @@
}
// By default these are hidden. They will be enabled when setPrevNextListeners() is called
- mNextButton = v.findViewById(com.android.internal.R.id.next);
+ mNextButton = (ImageButton) v.findViewById(com.android.internal.R.id.next);
if (mNextButton != null && !mFromXml && !mListenersSet) {
mNextButton.setVisibility(View.GONE);
}
- mPrevButton = v.findViewById(com.android.internal.R.id.prev);
+ mPrevButton = (ImageButton) v.findViewById(com.android.internal.R.id.prev);
if (mPrevButton != null && !mFromXml && !mListenersSet) {
mPrevButton.setVisibility(View.GONE);
}
- mProgress = v.findViewById(com.android.internal.R.id.mediacontroller_progress);
+ mProgress = (ProgressBar) v.findViewById(com.android.internal.R.id.mediacontroller_progress);
if (mProgress != null) {
if (mProgress instanceof SeekBar) {
SeekBar seeker = (SeekBar) mProgress;
@@ -298,8 +298,8 @@
mProgress.setMax(1000);
}
- mEndTime = v.findViewById(com.android.internal.R.id.time);
- mCurrentTime = v.findViewById(com.android.internal.R.id.time_current);
+ mEndTime = (TextView) v.findViewById(com.android.internal.R.id.time);
+ mCurrentTime = (TextView) v.findViewById(com.android.internal.R.id.time_current);
mFormatBuilder = new StringBuilder();
mFormatter = new Formatter(mFormatBuilder, Locale.getDefault());
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 5505f2f..359d04e 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -1578,7 +1578,7 @@
@Override
public void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
final Context context = root.getContext();
- final ViewGroup target = root.findViewById(viewId);
+ final ViewGroup target = (ViewGroup) root.findViewById(viewId);
if (target == null) return;
if (nestedViews != null) {
// Inflate nested views and add as children
@@ -1757,7 +1757,7 @@
@Override
public void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
- final TextView target = root.findViewById(viewId);
+ final TextView target = (TextView) root.findViewById(viewId);
if (target == null) return;
if (drawablesLoaded) {
if (isRelative) {
@@ -1857,7 +1857,7 @@
@Override
public void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
- final TextView target = root.findViewById(viewId);
+ final TextView target = (TextView) root.findViewById(viewId);
if (target == null) return;
target.setTextSize(units, size);
}
@@ -2045,7 +2045,7 @@
@Override
public void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
- final TextView target = root.findViewById(viewId);
+ final TextView target = (TextView) root.findViewById(viewId);
if (target == null) return;
Drawable[] drawables = isRelative
? target.getCompoundDrawablesRelative()
diff --git a/core/java/android/widget/SuggestionsAdapter.java b/core/java/android/widget/SuggestionsAdapter.java
index fbb8993..f833d1b 100644
--- a/core/java/android/widget/SuggestionsAdapter.java
+++ b/core/java/android/widget/SuggestionsAdapter.java
@@ -286,7 +286,7 @@
v.setTag(new ChildViewCache(v));
// Set up icon.
- final ImageView iconRefine = v.findViewById(R.id.edit_query);
+ final ImageView iconRefine = (ImageView) v.findViewById(R.id.edit_query);
iconRefine.setImageResource(mCommitIconResId);
return v;
@@ -304,11 +304,11 @@
public final ImageView mIconRefine;
public ChildViewCache(View v) {
- mText1 = v.findViewById(com.android.internal.R.id.text1);
- mText2 = v.findViewById(com.android.internal.R.id.text2);
- mIcon1 = v.findViewById(com.android.internal.R.id.icon1);
- mIcon2 = v.findViewById(com.android.internal.R.id.icon2);
- mIconRefine = v.findViewById(com.android.internal.R.id.edit_query);
+ mText1 = (TextView) v.findViewById(com.android.internal.R.id.text1);
+ mText2 = (TextView) v.findViewById(com.android.internal.R.id.text2);
+ mIcon1 = (ImageView) v.findViewById(com.android.internal.R.id.icon1);
+ mIcon2 = (ImageView) v.findViewById(com.android.internal.R.id.icon2);
+ mIconRefine = (ImageView) v.findViewById(com.android.internal.R.id.edit_query);
}
}
diff --git a/core/java/android/widget/TabHost.java b/core/java/android/widget/TabHost.java
index 7e2cadf..32418cd 100644
--- a/core/java/android/widget/TabHost.java
+++ b/core/java/android/widget/TabHost.java
@@ -619,7 +619,7 @@
mTabWidget, // tab widget is the parent
false); // no inflate params
- final TextView tv = tabIndicator.findViewById(R.id.title);
+ final TextView tv = (TextView) tabIndicator.findViewById(R.id.title);
tv.setText(mLabel);
if (context.getApplicationInfo().targetSdkVersion <= Build.VERSION_CODES.DONUT) {
@@ -653,8 +653,8 @@
mTabWidget, // tab widget is the parent
false); // no inflate params
- final TextView tv = tabIndicator.findViewById(R.id.title);
- final ImageView iconView = tabIndicator.findViewById(R.id.icon);
+ final TextView tv = (TextView) tabIndicator.findViewById(R.id.title);
+ final ImageView iconView = (ImageView) tabIndicator.findViewById(R.id.icon);
// when icon is gone by default, we're in exclusive mode
final boolean exclusive = iconView.getVisibility() == View.GONE;
diff --git a/core/java/android/widget/TextInputTimePickerView.java b/core/java/android/widget/TextInputTimePickerView.java
new file mode 100644
index 0000000..ef91576
--- /dev/null
+++ b/core/java/android/widget/TextInputTimePickerView.java
@@ -0,0 +1,249 @@
+/*
+ * Copyright (C) 2017 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.widget;
+
+import android.content.Context;
+import android.text.Editable;
+import android.text.InputFilter;
+import android.text.TextWatcher;
+import android.util.AttributeSet;
+import android.util.MathUtils;
+import android.view.View;
+
+import com.android.internal.R;
+
+/**
+ * View to show text input based time picker with hour and minute fields and an optional AM/PM
+ * spinner.
+ *
+ * @hide
+ */
+public class TextInputTimePickerView extends RelativeLayout {
+ public static final int HOURS = 0;
+ public static final int MINUTES = 1;
+ public static final int AMPM = 2;
+
+ private static final int AM = 0;
+ private static final int PM = 1;
+
+ private final EditText mHourEditText;
+ private final EditText mMinuteEditText;
+ private final TextView mInputSeparatorView;
+ private final Spinner mAmPmSpinner;
+ private final TextView mErrorLabel;
+ private final TextView mHourLabel;
+ private final TextView mMinuteLabel;
+
+ private boolean mIs24Hour;
+ private boolean mHourFormatStartsAtZero;
+ private OnValueTypedListener mListener;
+
+ private boolean mErrorShowing;
+
+ interface OnValueTypedListener {
+ void onValueChanged(int inputType, int newValue);
+ }
+
+ public TextInputTimePickerView(Context context) {
+ this(context, null);
+ }
+
+ public TextInputTimePickerView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public TextInputTimePickerView(Context context, AttributeSet attrs, int defStyle) {
+ this(context, attrs, defStyle, 0);
+ }
+
+ public TextInputTimePickerView(Context context, AttributeSet attrs, int defStyle,
+ int defStyleRes) {
+ super(context, attrs, defStyle, defStyleRes);
+
+ inflate(context, R.layout.time_picker_text_input_material, this);
+
+ mHourEditText = (EditText) findViewById(R.id.input_hour);
+ mMinuteEditText = (EditText) findViewById(R.id.input_minute);
+ mInputSeparatorView = (TextView) findViewById(R.id.input_separator);
+ mErrorLabel = (TextView) findViewById(R.id.label_error);
+ mHourLabel = (TextView) findViewById(R.id.label_hour);
+ mMinuteLabel = (TextView) findViewById(R.id.label_minute);
+
+ mHourEditText.addTextChangedListener(new TextWatcher() {
+ @Override
+ public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
+
+ @Override
+ public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
+
+ @Override
+ public void afterTextChanged(Editable editable) {
+ parseAndSetHourInternal(editable.toString());
+ }
+ });
+
+ mMinuteEditText.addTextChangedListener(new TextWatcher() {
+ @Override
+ public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
+
+ @Override
+ public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
+
+ @Override
+ public void afterTextChanged(Editable editable) {
+ parseAndSetMinuteInternal(editable.toString());
+ }
+ });
+
+ mAmPmSpinner = (Spinner) findViewById(R.id.am_pm_spinner);
+ final String[] amPmStrings = TimePicker.getAmPmStrings(context);
+ ArrayAdapter<CharSequence> adapter =
+ new ArrayAdapter<CharSequence>(context, R.layout.simple_spinner_dropdown_item);
+ adapter.add(TimePickerClockDelegate.obtainVerbatim(amPmStrings[0]));
+ adapter.add(TimePickerClockDelegate.obtainVerbatim(amPmStrings[1]));
+ mAmPmSpinner.setAdapter(adapter);
+ mAmPmSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(AdapterView<?> adapterView, View view, int position,
+ long id) {
+ if (position == 0) {
+ mListener.onValueChanged(AMPM, AM);
+ } else {
+ mListener.onValueChanged(AMPM, PM);
+ }
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView<?> adapterView) {}
+ });
+ }
+
+ void setListener(OnValueTypedListener listener) {
+ mListener = listener;
+ }
+
+ void setHourFormat(int maxCharLength) {
+ mHourEditText.setFilters(new InputFilter[] {
+ new InputFilter.LengthFilter(maxCharLength)});
+ mMinuteEditText.setFilters(new InputFilter[] {
+ new InputFilter.LengthFilter(maxCharLength)});
+ }
+
+ boolean validateInput() {
+ final boolean inputValid = parseAndSetHourInternal(mHourEditText.getText().toString())
+ && parseAndSetMinuteInternal(mMinuteEditText.getText().toString());
+ setError(!inputValid);
+ return inputValid;
+ }
+
+ void updateSeparator(String separatorText) {
+ mInputSeparatorView.setText(separatorText);
+ }
+
+ private void setError(boolean enabled) {
+ mErrorShowing = enabled;
+
+ mErrorLabel.setVisibility(enabled ? View.VISIBLE : View.INVISIBLE);
+ mHourLabel.setVisibility(enabled ? View.INVISIBLE : View.VISIBLE);
+ mMinuteLabel.setVisibility(enabled ? View.INVISIBLE : View.VISIBLE);
+ }
+
+ /**
+ * Computes the display value and updates the text of the view.
+ * <p>
+ * This method should be called whenever the current value or display
+ * properties (leading zeroes, max digits) change.
+ */
+ void updateTextInputValues(int localizedHour, int minute, int amOrPm, boolean is24Hour,
+ boolean hourFormatStartsAtZero) {
+ final String format = "%d";
+
+ mIs24Hour = is24Hour;
+ mHourFormatStartsAtZero = hourFormatStartsAtZero;
+
+ mAmPmSpinner.setVisibility(is24Hour ? View.INVISIBLE : View.VISIBLE);
+
+ mHourEditText.setText(String.format(format, localizedHour));
+ mMinuteEditText.setText(String.format(format, minute));
+
+ if (amOrPm == AM) {
+ mAmPmSpinner.setSelection(0);
+ } else {
+ mAmPmSpinner.setSelection(1);
+ }
+
+ if (mErrorShowing) {
+ validateInput();
+ }
+ }
+
+ private boolean parseAndSetHourInternal(String input) {
+ try {
+ final int hour = Integer.parseInt(input);
+ if (!isValidLocalizedHour(hour)) {
+ final int minHour = mHourFormatStartsAtZero ? 0 : 1;
+ final int maxHour = mIs24Hour ? 23 : 11 + minHour;
+ mListener.onValueChanged(HOURS, getHourOfDayFromLocalizedHour(
+ MathUtils.constrain(hour, minHour, maxHour)));
+ return false;
+ }
+ mListener.onValueChanged(HOURS, getHourOfDayFromLocalizedHour(hour));
+ return true;
+ } catch (NumberFormatException e) {
+ // Do nothing since we cannot parse the input.
+ return false;
+ }
+ }
+
+ private boolean parseAndSetMinuteInternal(String input) {
+ try {
+ final int minutes = Integer.parseInt(input);
+ if (minutes < 0 || minutes > 59) {
+ mListener.onValueChanged(MINUTES, MathUtils.constrain(minutes, 0, 59));
+ return false;
+ }
+ mListener.onValueChanged(MINUTES, minutes);
+ return true;
+ } catch (NumberFormatException e) {
+ // Do nothing since we cannot parse the input.
+ return false;
+ }
+ }
+
+ private boolean isValidLocalizedHour(int localizedHour) {
+ final int minHour = mHourFormatStartsAtZero ? 0 : 1;
+ final int maxHour = (mIs24Hour ? 23 : 11) + minHour;
+ return localizedHour >= minHour && localizedHour <= maxHour;
+ }
+
+ private int getHourOfDayFromLocalizedHour(int localizedHour) {
+ int hourOfDay = localizedHour;
+ if (mIs24Hour) {
+ if (!mHourFormatStartsAtZero && localizedHour == 24) {
+ hourOfDay = 0;
+ }
+ } else {
+ if (!mHourFormatStartsAtZero && localizedHour == 12) {
+ hourOfDay = 0;
+ }
+ if (mAmPmSpinner.getSelectedItemPosition() == 1) {
+ hourOfDay += 12;
+ }
+ }
+ return hourOfDay;
+ }
+}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 4a8ec94..a5ff291 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -9639,7 +9639,7 @@
return new GestureDetector(mContext,
new GestureDetector.SimpleOnGestureListener() {
@Override
- public boolean onSingleTapConfirmed(MotionEvent e) {
+ public boolean onSingleTapUp(MotionEvent e) {
if (shouldUseClickableSpanOnClickGestureDetector()) {
ClickableSpan[] links = ((Spannable) mText).getSpans(
getSelectionStart(), getSelectionEnd(),
diff --git a/core/java/android/widget/TimePicker.java b/core/java/android/widget/TimePicker.java
index e6cd798..9f38b04 100644
--- a/core/java/android/widget/TimePicker.java
+++ b/core/java/android/widget/TimePicker.java
@@ -278,6 +278,16 @@
return mDelegate.getBaseline();
}
+ /**
+ * Validates whether current input by the user is a valid time based on the locale. TimePicker
+ * will show an error message to the user if the time is not valid.
+ *
+ * @return {@code true} if the input is valid, {@code false} otherwise
+ */
+ public boolean validateInput() {
+ return mDelegate.validateInput();
+ }
+
@Override
protected Parcelable onSaveInstanceState() {
Parcelable superState = super.onSaveInstanceState();
@@ -341,6 +351,8 @@
void setIs24Hour(boolean is24Hour);
boolean is24Hour();
+ boolean validateInput();
+
void setOnTimeChangedListener(OnTimeChangedListener onTimeChangedListener);
void setEnabled(boolean enabled);
diff --git a/core/java/android/widget/TimePickerClockDelegate.java b/core/java/android/widget/TimePickerClockDelegate.java
index 1d37a21..3a09063 100644
--- a/core/java/android/widget/TimePickerClockDelegate.java
+++ b/core/java/android/widget/TimePickerClockDelegate.java
@@ -16,12 +16,14 @@
package android.widget;
+import android.annotation.IntDef;
import android.annotation.Nullable;
import android.annotation.TestApi;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.content.res.TypedArray;
+import android.icu.text.DecimalFormatSymbols;
import android.os.Parcelable;
import android.text.SpannableStringBuilder;
import android.text.format.DateFormat;
@@ -40,11 +42,14 @@
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
import android.widget.RadialTimePickerView.OnValueSelectedListener;
+import android.widget.TextInputTimePickerView.OnValueTypedListener;
import com.android.internal.R;
import com.android.internal.widget.NumericTextView;
import com.android.internal.widget.NumericTextView.OnValueChangedListener;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.Calendar;
/**
@@ -58,6 +63,13 @@
*/
private static final long DELAY_COMMIT_MILLIS = 2000;
+ @IntDef({FROM_EXTERNAL_API, FROM_RADIAL_PICKER, FROM_INPUT_PICKER})
+ @Retention(RetentionPolicy.SOURCE)
+ private @interface ChangeSource {}
+ private static final int FROM_EXTERNAL_API = 0;
+ private static final int FROM_RADIAL_PICKER = 1;
+ private static final int FROM_INPUT_PICKER = 2;
+
// Index used by RadialPickerLayout
private static final int HOUR_INDEX = RadialTimePickerView.HOURS;
private static final int MINUTE_INDEX = RadialTimePickerView.MINUTES;
@@ -78,6 +90,15 @@
private final RadialTimePickerView mRadialTimePickerView;
private final TextView mSeparatorView;
+ private boolean mRadialPickerModeEnabled = true;
+ private final ImageButton mRadialTimePickerModeButton;
+ private final String mRadialTimePickerModeEnabledDescription;
+ private final String mTextInputPickerModeEnabledDescription;
+ private final View mRadialTimePickerHeader;
+ private final View mTextInputPickerHeader;
+
+ private final TextInputTimePickerView mTextInputPickerView;
+
private final Calendar mTempCalendar;
// Accessibility strings.
@@ -116,8 +137,8 @@
final int layoutResourceId = a.getResourceId(R.styleable.TimePicker_internalLayout,
R.layout.time_picker_material);
final View mainView = inflater.inflate(layoutResourceId, delegator);
- final View headerView = mainView.findViewById(R.id.time_header);
- headerView.setOnTouchListener(new NearestTouchDelegate());
+ mRadialTimePickerHeader = mainView.findViewById(R.id.time_header);
+ mRadialTimePickerHeader.setOnTouchListener(new NearestTouchDelegate());
// Set up hour/minute labels.
mHourView = (NumericTextView) mainView.findViewById(R.id.hours);
@@ -170,6 +191,8 @@
headerTextColor = a.getColorStateList(R.styleable.TimePicker_headerTextColor);
}
+ mTextInputPickerHeader = mainView.findViewById(R.id.input_header);
+
if (headerTextColor != null) {
mHourView.setTextColor(headerTextColor);
mSeparatorView.setTextColor(headerTextColor);
@@ -180,7 +203,10 @@
// Set up header background, if available.
if (a.hasValueOrEmpty(R.styleable.TimePicker_headerBackground)) {
- headerView.setBackground(a.getDrawable(R.styleable.TimePicker_headerBackground));
+ mRadialTimePickerHeader.setBackground(a.getDrawable(
+ R.styleable.TimePicker_headerBackground));
+ mTextInputPickerHeader.setBackground(a.getDrawable(
+ R.styleable.TimePicker_headerBackground));
}
a.recycle();
@@ -189,6 +215,22 @@
mRadialTimePickerView.applyAttributes(attrs, defStyleAttr, defStyleRes);
mRadialTimePickerView.setOnValueSelectedListener(mOnValueSelectedListener);
+ mTextInputPickerView = (TextInputTimePickerView) mainView.findViewById(R.id.input_mode);
+ mTextInputPickerView.setListener(mOnValueTypedListener);
+
+ mRadialTimePickerModeButton =
+ (ImageButton) mainView.findViewById(R.id.toggle_mode);
+ mRadialTimePickerModeButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ toggleRadialPickerMode();
+ }
+ });
+ mRadialTimePickerModeEnabledDescription = context.getResources().getString(
+ R.string.time_picker_radial_mode_description);
+ mTextInputPickerModeEnabledDescription = context.getResources().getString(
+ R.string.time_picker_text_input_mode_description);
+
mAllowAutoAdvance = true;
updateHourFormat();
@@ -200,6 +242,34 @@
initialize(currentHour, currentMinute, mIs24Hour, HOUR_INDEX);
}
+ private void toggleRadialPickerMode() {
+ if (mRadialPickerModeEnabled) {
+ mRadialTimePickerView.setVisibility(View.GONE);
+ mRadialTimePickerHeader.setVisibility(View.GONE);
+ mTextInputPickerHeader.setVisibility(View.VISIBLE);
+ mTextInputPickerView.setVisibility(View.VISIBLE);
+ mRadialTimePickerModeButton.setImageResource(R.drawable.btn_event_material);
+ mRadialTimePickerModeButton.setContentDescription(
+ mRadialTimePickerModeEnabledDescription);
+ mRadialPickerModeEnabled = false;
+ } else {
+ mRadialTimePickerView.setVisibility(View.VISIBLE);
+ mRadialTimePickerHeader.setVisibility(View.VISIBLE);
+ mTextInputPickerHeader.setVisibility(View.GONE);
+ mTextInputPickerView.setVisibility(View.GONE);
+ mRadialTimePickerModeButton.setImageResource(R.drawable.btn_keyboard_key_material);
+ mRadialTimePickerModeButton.setContentDescription(
+ mTextInputPickerModeEnabledDescription);
+ updateTextInputPicker();
+ mRadialPickerModeEnabled = true;
+ }
+ }
+
+ @Override
+ public boolean validateInput() {
+ return mTextInputPickerView.validateInput();
+ }
+
/**
* Ensures that a TextView is wide enough to contain its text without
* wrapping or clipping. Measures the specified view and sets the minimum
@@ -249,9 +319,16 @@
final int maxHour = (mIs24Hour ? 23 : 11) + minHour;
mHourView.setRange(minHour, maxHour);
mHourView.setShowLeadingZeroes(mHourFormatShowLeadingZero);
+
+ final String[] digits = DecimalFormatSymbols.getInstance(mLocale).getDigitStrings();
+ int maxCharLength = 0;
+ for (int i = 0; i < 10; i++) {
+ maxCharLength = Math.max(maxCharLength, digits[i].length());
+ }
+ mTextInputPickerView.setHourFormat(maxCharLength * 2);
}
- private static final CharSequence obtainVerbatim(String text) {
+ static final CharSequence obtainVerbatim(String text) {
return new SpannableStringBuilder().append(text,
new TtsSpan.VerbatimBuilder(text).build(), 0);
}
@@ -333,10 +410,16 @@
updateHeaderSeparator();
updateHeaderMinute(mCurrentMinute, false);
updateRadialPicker(index);
+ updateTextInputPicker();
mDelegator.invalidate();
}
+ private void updateTextInputPicker() {
+ mTextInputPickerView.updateTextInputValues(getLocalizedHour(mCurrentHour), mCurrentMinute,
+ mCurrentHour < 12 ? AM : PM, mIs24Hour, mHourFormatStartsAtZero);
+ }
+
private void updateRadialPicker(int index) {
mRadialTimePickerView.initialize(mCurrentHour, mCurrentMinute, mIs24Hour);
setCurrentItemShowing(index, false, true);
@@ -381,10 +464,10 @@
*/
@Override
public void setHour(int hour) {
- setHourInternal(hour, false, true);
+ setHourInternal(hour, FROM_EXTERNAL_API, true);
}
- private void setHourInternal(int hour, boolean isFromPicker, boolean announce) {
+ private void setHourInternal(int hour, @ChangeSource int source, boolean announce) {
if (mCurrentHour == hour) {
return;
}
@@ -393,10 +476,13 @@
updateHeaderHour(hour, announce);
updateHeaderAmPm();
- if (!isFromPicker) {
+ if (source != FROM_RADIAL_PICKER) {
mRadialTimePickerView.setCurrentHour(hour);
mRadialTimePickerView.setAmOrPm(hour < 12 ? AM : PM);
}
+ if (source != FROM_INPUT_PICKER) {
+ updateTextInputPicker();
+ }
mDelegator.invalidate();
onTimeChanged();
@@ -424,10 +510,10 @@
*/
@Override
public void setMinute(int minute) {
- setMinuteInternal(minute, false);
+ setMinuteInternal(minute, FROM_EXTERNAL_API);
}
- private void setMinuteInternal(int minute, boolean isFromPicker) {
+ private void setMinuteInternal(int minute, @ChangeSource int source) {
if (mCurrentMinute == minute) {
return;
}
@@ -435,9 +521,12 @@
mCurrentMinute = minute;
updateHeaderMinute(minute, true);
- if (!isFromPicker) {
+ if (source != FROM_RADIAL_PICKER) {
mRadialTimePickerView.setCurrentMinute(minute);
}
+ if (source != FROM_INPUT_PICKER) {
+ updateTextInputPicker();
+ }
mDelegator.invalidate();
onTimeChanged();
@@ -661,6 +750,7 @@
separatorText = Character.toString(bestDateTimePattern.charAt(hIndex + 1));
}
mSeparatorView.setText(separatorText);
+ mTextInputPickerView.updateSeparator(separatorText);
}
static private int lastIndexOfAny(String str, char[] any) {
@@ -712,7 +802,7 @@
if (mRadialTimePickerView.setAmOrPm(amOrPm)) {
mCurrentHour = getHour();
-
+ updateTextInputPicker();
if (mOnTimeChangedListener != null) {
mOnTimeChangedListener.onTimeChanged(mDelegator, getHour(), getMinute());
}
@@ -726,7 +816,7 @@
switch (pickerType) {
case RadialTimePickerView.HOURS:
final boolean isTransition = mAllowAutoAdvance && autoAdvance;
- setHourInternal(newValue, true, !isTransition);
+ setHourInternal(newValue, FROM_RADIAL_PICKER, !isTransition);
if (isTransition) {
setCurrentItemShowing(MINUTE_INDEX, true, false);
@@ -735,7 +825,7 @@
}
break;
case RadialTimePickerView.MINUTES:
- setMinuteInternal(newValue, true);
+ setMinuteInternal(newValue, FROM_RADIAL_PICKER);
break;
}
@@ -745,6 +835,23 @@
}
};
+ private final OnValueTypedListener mOnValueTypedListener = new OnValueTypedListener() {
+ @Override
+ public void onValueChanged(int pickerType, int newValue) {
+ switch (pickerType) {
+ case TextInputTimePickerView.HOURS:
+ setHourInternal(newValue, FROM_INPUT_PICKER, false);
+ break;
+ case TextInputTimePickerView.MINUTES:
+ setMinuteInternal(newValue, FROM_INPUT_PICKER);
+ break;
+ case TextInputTimePickerView.AMPM:
+ setAmOrPm(newValue);
+ break;
+ }
+ }
+ };
+
/** Listener for keyboard interaction. */
private final OnValueChangedListener mDigitEnteredListener = new OnValueChangedListener() {
@Override
diff --git a/core/java/android/widget/TimePickerSpinnerDelegate.java b/core/java/android/widget/TimePickerSpinnerDelegate.java
index 4634631..7ef54a5 100644
--- a/core/java/android/widget/TimePickerSpinnerDelegate.java
+++ b/core/java/android/widget/TimePickerSpinnerDelegate.java
@@ -86,7 +86,7 @@
inflater.inflate(layoutResourceId, mDelegator, true);
// hour
- mHourSpinner = delegator.findViewById(R.id.hour);
+ mHourSpinner = (NumberPicker) delegator.findViewById(R.id.hour);
mHourSpinner.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
public void onValueChange(NumberPicker spinner, int oldVal, int newVal) {
updateInputState();
@@ -100,17 +100,17 @@
onTimeChanged();
}
});
- mHourSpinnerInput = mHourSpinner.findViewById(R.id.numberpicker_input);
+ mHourSpinnerInput = (EditText) mHourSpinner.findViewById(R.id.numberpicker_input);
mHourSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_NEXT);
// divider (only for the new widget style)
- mDivider = mDelegator.findViewById(R.id.divider);
+ mDivider = (TextView) mDelegator.findViewById(R.id.divider);
if (mDivider != null) {
setDividerText();
}
// minute
- mMinuteSpinner = mDelegator.findViewById(R.id.minute);
+ mMinuteSpinner = (NumberPicker) mDelegator.findViewById(R.id.minute);
mMinuteSpinner.setMinValue(0);
mMinuteSpinner.setMaxValue(59);
mMinuteSpinner.setOnLongPressUpdateInterval(100);
@@ -138,7 +138,7 @@
onTimeChanged();
}
});
- mMinuteSpinnerInput = mMinuteSpinner.findViewById(R.id.numberpicker_input);
+ mMinuteSpinnerInput = (EditText) mMinuteSpinner.findViewById(R.id.numberpicker_input);
mMinuteSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_NEXT);
// Get the localized am/pm strings and use them in the spinner.
@@ -173,13 +173,13 @@
onTimeChanged();
}
});
- mAmPmSpinnerInput = mAmPmSpinner.findViewById(R.id.numberpicker_input);
+ mAmPmSpinnerInput = (EditText) mAmPmSpinner.findViewById(R.id.numberpicker_input);
mAmPmSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_DONE);
}
if (isAmPmAtStart()) {
// Move the am/pm view to the beginning
- ViewGroup amPmParent = delegator.findViewById(R.id.timePickerLayout);
+ ViewGroup amPmParent = (ViewGroup) delegator.findViewById(R.id.timePickerLayout);
amPmParent.removeView(amPmView);
amPmParent.addView(amPmView, 0);
// Swap layout margins if needed. They may be not symmetrical (Old Standard Theme
@@ -219,6 +219,11 @@
}
}
+ @Override
+ public boolean validateInput() {
+ return true;
+ }
+
private void getHourFormatData() {
final String bestDateTimePattern = DateFormat.getBestDateTimePattern(mLocale,
(mIs24HourView) ? "Hm" : "hm");
diff --git a/core/java/android/widget/Toast.java b/core/java/android/widget/Toast.java
index bf0601d..789e60b 100644
--- a/core/java/android/widget/Toast.java
+++ b/core/java/android/widget/Toast.java
@@ -299,7 +299,7 @@
if (mNextView == null) {
throw new RuntimeException("This Toast was not created with Toast.makeText()");
}
- TextView tv = mNextView.findViewById(com.android.internal.R.id.message);
+ TextView tv = (TextView) mNextView.findViewById(com.android.internal.R.id.message);
if (tv == null) {
throw new RuntimeException("This Toast was not created with Toast.makeText()");
}
diff --git a/core/java/android/widget/ZoomButtonsController.java b/core/java/android/widget/ZoomButtonsController.java
index 1a3ca86..69b79971 100644
--- a/core/java/android/widget/ZoomButtonsController.java
+++ b/core/java/android/widget/ZoomButtonsController.java
@@ -264,7 +264,7 @@
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(com.android.internal.R.layout.zoom_container, container);
- mControls = container.findViewById(com.android.internal.R.id.zoomControls);
+ mControls = (ZoomControls) container.findViewById(com.android.internal.R.id.zoomControls);
mControls.setOnZoomInClickListener(new OnClickListener() {
public void onClick(View v) {
dismissControlsDelayed(ZOOM_CONTROLS_TIMEOUT);
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index 20f10b3..9cbbc5a 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -53,9 +53,6 @@
void setImeWindowStatus(in IBinder token, int vis, int backDisposition,
boolean showImeSwitcher);
void setWindowState(int window, int state);
- void buzzBeepBlinked();
- void notificationLightOff();
- void notificationLightPulse(int argb, int millisOn, int millisOff);
void showRecentApps(boolean triggeredFromAltTab, boolean fromHome);
void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey);
diff --git a/core/java/com/android/internal/util/ArrayUtils.java b/core/java/com/android/internal/util/ArrayUtils.java
index a9a6364..cb3a250 100644
--- a/core/java/com/android/internal/util/ArrayUtils.java
+++ b/core/java/com/android/internal/util/ArrayUtils.java
@@ -435,10 +435,6 @@
}
}
- public static <T> boolean contains(@Nullable ArraySet<T> cur, T val) {
- return (cur != null) ? cur.contains(val) : false;
- }
-
public static @NonNull <T> ArrayList<T> add(@Nullable ArrayList<T> cur, T val) {
if (cur == null) {
cur = new ArrayList<>();
@@ -459,6 +455,16 @@
}
}
+ /**
+ * Returns the given list, or an immutable empty list if the provided list is null
+ *
+ * @see Collections#emptyList
+ */
+
+ public static @NonNull <T> List<T> emptyIfNull(@Nullable List<T> cur) {
+ return cur == null ? Collections.emptyList() : cur;
+ }
+
public static <T> boolean contains(@Nullable Collection<T> cur, T val) {
return (cur != null) ? cur.contains(val) : false;
}
diff --git a/core/java/com/android/internal/util/ObjectUtils.java b/core/java/com/android/internal/util/ObjectUtils.java
new file mode 100644
index 0000000..d109a5a
--- /dev/null
+++ b/core/java/com/android/internal/util/ObjectUtils.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2017 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.util;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+/** @hide */
+public class ObjectUtils {
+ private ObjectUtils() {}
+
+ @NonNull
+ public static <T> T firstNotNull(@Nullable T a, @NonNull T b) {
+ return a != null ? a : Preconditions.checkNotNull(b);
+ }
+}
diff --git a/core/java/com/android/internal/widget/DrawingSpace.java b/core/java/com/android/internal/widget/DrawingSpace.java
deleted file mode 100644
index b8222db..0000000
--- a/core/java/com/android/internal/widget/DrawingSpace.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2015 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.widget;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.View;
-
-/**
- * Implementation of {@link android.widget.Space} that uses normal View drawing
- * rather than a no-op. Useful for dialogs and other places where the base View
- * class is too greedy when measured with AT_MOST.
- */
-public final class DrawingSpace extends View {
- public DrawingSpace(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
- super(context, attrs, defStyleAttr, defStyleRes);
- }
-
- public DrawingSpace(Context context, AttributeSet attrs, int defStyleAttr) {
- this(context, attrs, defStyleAttr, 0);
- }
-
- public DrawingSpace(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public DrawingSpace(Context context) {
- this(context, null);
- }
-
- /**
- * Compare to: {@link View#getDefaultSize(int, int)}
- * <p>
- * If mode is AT_MOST, return the child size instead of the parent size
- * (unless it is too big).
- */
- private static int getDefaultSizeNonGreedy(int size, int measureSpec) {
- int result = size;
- int specMode = MeasureSpec.getMode(measureSpec);
- int specSize = MeasureSpec.getSize(measureSpec);
-
- switch (specMode) {
- case MeasureSpec.UNSPECIFIED:
- result = size;
- break;
- case MeasureSpec.AT_MOST:
- result = Math.min(size, specSize);
- break;
- case MeasureSpec.EXACTLY:
- result = specSize;
- break;
- }
- return result;
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- setMeasuredDimension(
- getDefaultSizeNonGreedy(getSuggestedMinimumWidth(), widthMeasureSpec),
- getDefaultSizeNonGreedy(getSuggestedMinimumHeight(), heightMeasureSpec));
- }
-}
diff --git a/core/java/com/android/internal/widget/WatchHeaderListView.java b/core/java/com/android/internal/widget/WatchHeaderListView.java
index 53fa7ab..4fd19c3 100644
--- a/core/java/com/android/internal/widget/WatchHeaderListView.java
+++ b/core/java/com/android/internal/widget/WatchHeaderListView.java
@@ -92,14 +92,13 @@
}
@Override
- protected <T extends View> T findViewByPredicateTraversal(
- Predicate<View> predicate, View childToSkip) {
+ protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
View v = super.findViewByPredicateTraversal(predicate, childToSkip);
if (v == null && mTopPanel != null && mTopPanel != childToSkip
&& !mTopPanel.isRootNamespace()) {
- return (T) mTopPanel.findViewByPredicate(predicate);
+ return mTopPanel.findViewByPredicate(predicate);
}
- return (T) v;
+ return v;
}
@Override
diff --git a/core/jni/android_os_HwBlob.cpp b/core/jni/android_os_HwBlob.cpp
index b2dee06..8590ecf 100644
--- a/core/jni/android_os_HwBlob.cpp
+++ b/core/jni/android_os_HwBlob.cpp
@@ -382,7 +382,7 @@
s = nullptr;
hidl_string tmp;
- tmp.setToExternal(static_cast<const char *>(subBlob->data()), size);
+ tmp.setToExternal(static_cast<const char *>(subBlob->data()), size - 1);
sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, thiz);
blob->write(offset, &tmp, sizeof(tmp));
diff --git a/core/jni/android_os_seccomp.cpp b/core/jni/android_os_seccomp.cpp
index 2fe5d39..3f7bab2 100644
--- a/core/jni/android_os_seccomp.cpp
+++ b/core/jni/android_os_seccomp.cpp
@@ -147,6 +147,9 @@
// Needed for kernel to restart syscalls
AllowSyscall(f, 128); // __NR_restart_syscall
+ // b/35034743
+ AllowSyscall(f, 267); // __NR_fstatfs64
+
Trap(f);
if (SetValidateArchitectureJumpTarget(offset_to_32bit_filter, f) != 0)
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 5c65241..e2fc444 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -247,24 +247,42 @@
static void DropCapabilitiesBoundingSet(JNIEnv* env) {
for (int i = 0; prctl(PR_CAPBSET_READ, i, 0, 0, 0) >= 0; i++) {
- // Keep CAP_SYS_PTRACE in our bounding set so crash_dump can gain it.
- if (i == CAP_SYS_PTRACE) {
- continue;
- }
-
int rc = prctl(PR_CAPBSET_DROP, i, 0, 0, 0);
if (rc == -1) {
if (errno == EINVAL) {
ALOGE("prctl(PR_CAPBSET_DROP) failed with EINVAL. Please verify "
"your kernel is compiled with file capabilities support");
} else {
+ ALOGE("prctl(PR_CAPBSET_DROP, %d) failed: %s", i, strerror(errno));
RuntimeAbort(env, __LINE__, "prctl(PR_CAPBSET_DROP) failed");
}
}
}
}
-static void SetCapabilities(JNIEnv* env, int64_t permitted, int64_t effective) {
+static void SetInheritable(JNIEnv* env, uint64_t inheritable) {
+ __user_cap_header_struct capheader;
+ memset(&capheader, 0, sizeof(capheader));
+ capheader.version = _LINUX_CAPABILITY_VERSION_3;
+ capheader.pid = 0;
+
+ __user_cap_data_struct capdata[2];
+ if (capget(&capheader, &capdata[0]) == -1) {
+ ALOGE("capget failed: %s", strerror(errno));
+ RuntimeAbort(env, __LINE__, "capget failed");
+ }
+
+ capdata[0].inheritable = inheritable;
+ capdata[1].inheritable = inheritable >> 32;
+
+ if (capset(&capheader, &capdata[0]) == -1) {
+ ALOGE("capset(inh=%" PRIx64 ") failed: %s", inheritable, strerror(errno));
+ RuntimeAbort(env, __LINE__, "capset failed");
+ }
+}
+
+static void SetCapabilities(JNIEnv* env, uint64_t permitted, uint64_t effective,
+ uint64_t inheritable) {
__user_cap_header_struct capheader;
memset(&capheader, 0, sizeof(capheader));
capheader.version = _LINUX_CAPABILITY_VERSION_3;
@@ -276,9 +294,12 @@
capdata[1].effective = effective >> 32;
capdata[0].permitted = permitted;
capdata[1].permitted = permitted >> 32;
+ capdata[0].inheritable = inheritable;
+ capdata[1].inheritable = inheritable >> 32;
if (capset(&capheader, &capdata[0]) == -1) {
- ALOGE("capset(%" PRId64 ", %" PRId64 ") failed", permitted, effective);
+ ALOGE("capset(perm=%" PRIx64 ", eff=%" PRIx64 ", inh=%" PRIx64 ") failed: %s", permitted,
+ effective, inheritable, strerror(errno));
RuntimeAbort(env, __LINE__, "capset failed");
}
}
@@ -532,6 +553,7 @@
EnableKeepCapabilities(env);
}
+ SetInheritable(env, permittedCapabilities);
DropCapabilitiesBoundingSet(env);
bool use_native_bridge = !is_system_server && (instructionSet != NULL)
@@ -604,7 +626,7 @@
}
}
- SetCapabilities(env, permittedCapabilities, effectiveCapabilities);
+ SetCapabilities(env, permittedCapabilities, effectiveCapabilities, permittedCapabilities);
SetSchedulerPolicy(env);
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 11eb47b..a6e43ff 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2365,6 +2365,11 @@
<permission android:name="android.permission.BIND_PRINT_SPOOLER_SERVICE"
android:protectionLevel="signature" />
+ <!-- Must be required by the CompanionDeviceManager to ensure that only the system can bind to it.
+ @hide -->
+ <permission android:name="android.permission.BIND_COMPANION_DEVICE_MANAGER_SERVICE"
+ android:protectionLevel="signature" />
+
<!-- @SystemApi Must be required by the RuntimePermissionPresenterService to ensure
that only the system can bind to it.
@hide -->
diff --git a/core/res/res/drawable/btn_event_material.xml b/core/res/res/drawable/btn_event_material.xml
new file mode 100644
index 0000000..47c49cf
--- /dev/null
+++ b/core/res/res/drawable/btn_event_material.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2017 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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
+ <path
+ android:fillColor="#90ffffff"
+ android:pathData="M17 12h-5v5h5v-5zM16 1v2H8V1H6v2H5c-1.11 0-1.99 .9 -1.99 2L3 19c0 1.1 .89 2 2
+2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2h-1V1h-2zm3 18H5V8h14v11z" />
+ <path android:pathData="M0 0h24v24H0z" />
+</vector>
\ No newline at end of file
diff --git a/core/res/res/drawable/btn_keyboard_key_material.xml b/core/res/res/drawable/btn_keyboard_key_material.xml
new file mode 100644
index 0000000..14a9492f
--- /dev/null
+++ b/core/res/res/drawable/btn_keyboard_key_material.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2017 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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
+ <path
+ android:fillColor="#90ffffff"
+ android:pathData="M20 5H4c-1.1 0-1.99 .9 -1.99 2L2 17c0 1.1 .9 2 2 2h16c1.1 0 2-.9
+2-2V7c0-1.1-.9-2-2-2zm-9 3h2v2h-2V8zm0 3h2v2h-2v-2zM8 8h2v2H8V8zm0
+3h2v2H8v-2zm-1 2H5v-2h2v2zm0-3H5V8h2v2zm9
+7H8v-2h8v2zm0-4h-2v-2h2v2zm0-3h-2V8h2v2zm3 3h-2v-2h2v2zm0-3h-2V8h2v2z" />
+ <path
+ android:pathData="M0 0h24v24H0zm0 0h24v24H0z" />
+</vector>
\ No newline at end of file
diff --git a/core/res/res/layout-land/time_picker_material.xml b/core/res/res/layout-land/time_picker_material.xml
index 70833d6..8b95f9f 100644
--- a/core/res/res/layout-land/time_picker_material.xml
+++ b/core/res/res/layout-land/time_picker_material.xml
@@ -15,28 +15,17 @@
limitations under the License.
-->
-<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layoutDirection="ltr">
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
- <!-- Provides a background for the time layout that extends into the button bar area. -->
- <com.android.internal.widget.DrawingSpace
+ <LinearLayout
android:id="@+id/time_header"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_column="@dimen/time_picker_column_start_material"
- android:layout_row="0"
- android:layout_rowSpan="3"
- android:layout_gravity="center|fill"
- android:layoutDirection="locale" />
-
- <RelativeLayout
android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_column="@dimen/time_picker_column_start_material"
- android:layout_row="1"
- android:layout_gravity="center|fill"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:gravity="center"
android:paddingStart="?attr/dialogPreferredPadding"
android:paddingEnd="?attr/dialogPreferredPadding">
@@ -44,10 +33,8 @@
android:id="@+id/time_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:layout_centerInParent="true"
android:paddingTop="@dimen/timepicker_radial_picker_top_margin"
- android:layout_marginBottom="-12dp">
+ android:orientation="horizontal">
<!-- The hour should always be to the left of the separator,
regardless of the current locale's layout direction. -->
@@ -125,38 +112,71 @@
android:includeFontPadding="false"
android:button="@null" />
</RadioGroup>
- </RelativeLayout>
+ </LinearLayout>
- <ViewStub
- android:id="@id/topPanel"
- android:layout="@layout/alert_dialog_title_material"
+ <TextView
+ android:visibility="gone"
+ android:id="@+id/input_header"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:gravity="center"
+ android:paddingStart="@dimen/dialog_padding_material"
+ android:paddingEnd="@dimen/dialog_padding_material"
+ android:paddingTop="20dp"
+ android:paddingBottom="20dp"
+ android:includeFontPadding="false"
+ android:textAppearance="@style/TextAppearance.Material.TimePicker.InputHeader"
+ android:text="@string/time_picker_header_text"/>
+
+ <LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_column="@dimen/time_picker_column_end_material"
- android:layout_row="0"
- android:layout_gravity="top|fill_horizontal"
- android:layoutDirection="locale" />
+ android:orientation="vertical">
- <android.widget.RadialTimePickerView
- android:id="@+id/radial_picker"
- android:layout_width="@dimen/timepicker_radial_picker_dimen"
- android:layout_height="@dimen/timepicker_radial_picker_dimen"
- android:layout_column="@dimen/time_picker_column_end_material"
- android:layout_row="1"
- android:layout_rowWeight="1"
- android:layout_gravity="center|fill"
- android:layout_marginTop="@dimen/timepicker_radial_picker_top_margin"
- android:layout_marginStart="@dimen/timepicker_radial_picker_horizontal_margin"
- android:layout_marginEnd="@dimen/timepicker_radial_picker_horizontal_margin"
- android:layoutDirection="locale" />
+ <android.widget.RadialTimePickerView
+ android:id="@+id/radial_picker"
+ android:layout_width="@dimen/timepicker_radial_picker_dimen"
+ android:layout_height="@dimen/timepicker_radial_picker_dimen"
+ android:layout_gravity="center|fill"
+ android:layout_marginTop="@dimen/timepicker_radial_picker_top_margin"
+ android:layout_marginStart="@dimen/timepicker_radial_picker_horizontal_margin"
+ android:layout_marginEnd="@dimen/timepicker_radial_picker_horizontal_margin"
+ android:layoutDirection="locale" />
- <ViewStub
- android:id="@id/buttonPanel"
- android:layout="@layout/alert_dialog_button_bar_material"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_column="@dimen/time_picker_column_end_material"
- android:layout_row="2"
- android:layout_gravity="bottom|fill_horizontal"
- android:layoutDirection="locale" />
-</GridLayout>
+ <android.widget.TextInputTimePickerView
+ android:id="@+id/input_mode"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingStart="?attr/dialogPreferredPadding"
+ android:paddingEnd="?attr/dialogPreferredPadding"
+ android:visibility="gone" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+ <ImageButton
+ android:id="@+id/toggle_mode"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:layout_marginStart="12dp"
+ android:layout_marginEnd="12dp"
+ android:padding="12dp"
+ android:background="?attr/selectableItemBackgroundBorderless"
+ android:tint="?attr/colorControlNormal"
+ android:src="@drawable/btn_keyboard_key_material"
+ android:contentDescription="@string/time_picker_text_input_mode_description" />
+ <Space
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1" />
+ <ViewStub
+ android:id="@id/buttonPanel"
+ android:layout="@layout/alert_dialog_button_bar_material"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layoutDirection="locale" />
+ </LinearLayout>
+ </LinearLayout>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/core/res/res/layout/preference_list_content.xml b/core/res/res/layout/preference_list_content.xml
index 02cd8cd..bed80ed 100644
--- a/core/res/res/layout/preference_list_content.xml
+++ b/core/res/res/layout/preference_list_content.xml
@@ -24,6 +24,7 @@
android:layout_width="match_parent">
<LinearLayout
+ android:id="@+id/prefs_container"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="0px"
@@ -61,8 +62,7 @@
android:layout_width="0px"
android:layout_height="match_parent"
android:layout_weight="@integer/preferences_right_pane_weight"
- android:orientation="vertical"
- android:visibility="gone" >
+ android:orientation="vertical">
<!-- Breadcrumb inserted here, in certain screen sizes. In others, it will be an
empty layout or just padding, and PreferenceActivity will put the breadcrumbs in
diff --git a/core/res/res/layout/preference_list_content_material.xml b/core/res/res/layout/preference_list_content_material.xml
index 1bc527e..37b4119 100644
--- a/core/res/res/layout/preference_list_content_material.xml
+++ b/core/res/res/layout/preference_list_content_material.xml
@@ -24,6 +24,7 @@
android:layout_width="match_parent">
<LinearLayout
+ android:id="@+id/prefs_container"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="0px"
@@ -64,8 +65,7 @@
android:layout_width="0px"
android:layout_height="match_parent"
android:layout_weight="@integer/preferences_right_pane_weight"
- android:orientation="vertical"
- android:visibility="gone" >
+ android:orientation="vertical">
<!-- Breadcrumb inserted here, in certain screen sizes. In others, it will be an
empty layout or just padding, and PreferenceActivity will put the breadcrumbs in
diff --git a/core/res/res/layout/time_picker_material.xml b/core/res/res/layout/time_picker_material.xml
index 37a7384..7597379 100644
--- a/core/res/res/layout/time_picker_material.xml
+++ b/core/res/res/layout/time_picker_material.xml
@@ -34,4 +34,53 @@
android:layout_marginTop="@dimen/timepicker_radial_picker_top_margin"
android:layout_marginStart="@dimen/timepicker_radial_picker_horizontal_margin"
android:layout_marginEnd="@dimen/timepicker_radial_picker_horizontal_margin" />
+ <TextView
+ android:visibility="gone"
+ android:id="@+id/input_header"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingStart="@dimen/dialog_padding_material"
+ android:paddingEnd="@dimen/dialog_padding_material"
+ android:paddingTop="20dp"
+ android:paddingBottom="20dp"
+ android:includeFontPadding="false"
+ android:fontFamily="sans-serif-medium"
+ android:textSize="34sp"
+ android:textColor="@color/white"
+ android:text="@string/time_picker_header_text"/>
+ <android.widget.TextInputTimePickerView
+ android:id="@+id/input_mode"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingStart="?attr/dialogPreferredPadding"
+ android:paddingEnd="?attr/dialogPreferredPadding"
+ android:visibility="gone" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+ <ImageButton
+ android:id="@+id/toggle_mode"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:layout_marginStart="12dp"
+ android:layout_marginEnd="12dp"
+ android:padding="12dp"
+ android:background="?attr/selectableItemBackgroundBorderless"
+ android:tint="?attr/colorControlNormal"
+ android:src="@drawable/btn_keyboard_key_material"
+ android:contentDescription="@string/time_picker_text_input_mode_description" />
+ <Space
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1" />
+ <ViewStub
+ android:id="@id/buttonPanel"
+ android:layout="@layout/alert_dialog_button_bar_material"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layoutDirection="locale" />
+ </LinearLayout>
+
</LinearLayout>
diff --git a/core/res/res/layout/time_picker_text_input_material.xml b/core/res/res/layout/time_picker_text_input_material.xml
new file mode 100644
index 0000000..f17b80e
--- /dev/null
+++ b/core/res/res/layout/time_picker_text_input_material.xml
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2017 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.
+-->
+
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <TextView
+ android:id="@+id/top_label"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="26dp"
+ android:layout_marginBottom="8dp"
+ android:text="@string/time_picker_prompt_label"
+ android:textAppearance="@style/TextAppearance.Material.TimePicker.PromptLabel" />
+
+ <RelativeLayout
+ android:id="@+id/input_block"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/top_label"
+ android:layoutDirection="ltr">
+ <EditText
+ android:id="@+id/input_hour"
+ android:layout_width="50dp"
+ android:layout_height="wrap_content"
+ android:inputType="number"
+ android:textAppearance="@style/TextAppearance.Material.TimePicker.InputField" />
+ <TextView
+ android:id="@+id/label_hour"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/input_hour"
+ android:layout_alignStart="@id/input_hour"
+ android:text="@string/time_picker_hour_label"/>
+
+ <TextView
+ android:id="@+id/input_separator"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignEnd="@id/input_hour"
+ android:layout_alignBaseline="@id/input_hour"
+ android:textAppearance="@style/TextAppearance.Material.TimePicker.InputField" />
+
+ <EditText
+ android:id="@+id/input_minute"
+ android:layout_width="50dp"
+ android:layout_height="wrap_content"
+ android:layout_alignBaseline="@id/input_hour"
+ android:layout_toEndOf="@id/input_separator"
+ android:inputType="number"
+ android:textAppearance="@style/TextAppearance.Material.TimePicker.InputField" />
+ <TextView
+ android:id="@+id/label_minute"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/input_minute"
+ android:layout_alignStart="@id/input_minute"
+ android:text="@string/time_picker_minute_label"/>
+
+ <TextView
+ android:visibility="invisible"
+ android:id="@+id/label_error"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/input_hour"
+ android:layout_alignStart="@id/input_hour"
+ android:textColor="?attr/textColorError"
+ android:text="@string/time_picker_input_error" />
+ </RelativeLayout>
+ <Spinner
+ android:id="@+id/am_pm_spinner"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignBaseline="@id/input_block"
+ android:layout_alignParentEnd="true"/>
+
+</merge>
\ No newline at end of file
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 9be3635..46d0745 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Beheer die vertoonskerm se zoemvlak en posisionering."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Voer gebare uit"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Kan tik, swiep, knyp en ander gebare uitvoer."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Vingerafdrukgebare"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Kan gebare wat op die toestel se vingerafdruksensor uitgevoer word, vasvang"</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"deaktiveer of verander statusbalk"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Laat die program toe om die statusbalk te deaktiveer en stelselikone by te voeg of te verwyder."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"wees die statusbalk"</string>
@@ -1146,6 +1148,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"Tik vir meer opsies."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB-ontfouter gekoppel"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"Tik om USB-ontfouting te deaktiveer."</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Kies om USB-ontfouting te deaktiveer."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Neem tans foutverslag …"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Deel foutverslag?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Deel tans foutverslag …"</string>
@@ -1689,4 +1692,7 @@
<string name="app_category_news" msgid="7496506240743986873">"Nuus en tydskrifte"</string>
<string name="app_category_maps" msgid="5878491404538024367">"Kaarte en navigasie"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"Produktiwiteit"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Toestelberging"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 41dff04..45206873 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"የማሳያውን የማጉያ ደረጃ እና አቀማመጥ ይቆጣጠሩ።"</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"የጣት ምልክቶችን ያከናውኑ"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"መታ ማድረግ፣ ማንሸራተት፣ መቆንጠጥ እና ሌሎች የጣት ምልክቶችን ማከናወን ይችላል።"</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"የጣት አሻራ ምልክቶች"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"በመሣሪያዎቹ የጣት አሻራ ዳሳሽ ላይ የተከናወኑ የጣት ምልክቶችን መያዝ ይችላል።"</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"የሁኔቴ አሞሌ አቦዝን ወይም ቀይር"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"የስርዓት አዶዎችን ወደ ሁኔታ አሞሌ ላለማስቻል ወይም ለማከል እና ለማስወገድ ለመተግበሪያው ይፈቅዳሉ፡፡"</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"የሁኔታ አሞሌ መሆን"</string>
@@ -1146,6 +1148,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"ለተጨማሪ አማራጮች መታ ያድርጉ።"</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB አድስ ተያይዟል"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"የዩኤስቢ ማረሚያን ለማሰናከል መታ ያድርጉ።"</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"USB ማረሚያ ላለማንቃት ምረጥ።"</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"የሳንካ ሪፖርትን በመውሰድ ላይ…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"የሳንካ ሪፖርት ይጋራ?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"የሳንካ ሪፖርትን በማጋራት ላይ…"</string>
@@ -1689,4 +1692,7 @@
<string name="app_category_news" msgid="7496506240743986873">"ዜና እና መጽሔቶች"</string>
<string name="app_category_maps" msgid="5878491404538024367">"ካርታዎች እና ዳሰሳ"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"ውጤታማነት"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"የመሣሪያ ማከማቻ"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 07e1699..95118c2 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -290,6 +290,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"يمكنك التحكم في مستوى التكبير/التصغير للشاشة وتحديد الموضع."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"تنفيذ إيماءات"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"يمكن النقر والتمرير بسرعة والتصغير وتنفيذ إيماءات أخرى."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"إيماءات بصمات الإصبع"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"يمكن أن تلتقط الإيماءات التي تم تنفيذها على مستشعر بصمات الإصبع في الأجهزة."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"تعطيل شريط الحالة أو تعديله"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"للسماح للتطبيق بتعطيل شريط الحالة أو إضافة رموز نظام وإزالتها."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"العمل كشريط للحالة"</string>
@@ -1226,6 +1228,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"انقر للحصول على المزيد من الخيارات."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"تم توصيل تصحيح أخطاء USB"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"انقر لتعطيل تصحيح أخطاء USB."</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"اختيار تعطيل تصحيح أخطاء USB."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"جارٍ الحصول على تقرير الخطأ…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"هل تريد مشاركة تقرير الخطأ؟"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"جارٍ مشاركة تقرير الخطأ…"</string>
@@ -1813,4 +1816,7 @@
<string name="app_category_news" msgid="7496506240743986873">"الأخبار والمجلات"</string>
<string name="app_category_maps" msgid="5878491404538024367">"الخرائط والتنقل"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"الإنتاجية"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"السعة التخزينية للجهاز"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index ebc4eed..cf377b2 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Ekran yaxınlaşdırma səviyyəsi və yerləşdirməsinə nəzarət edin."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Jestlər ilə əməliyyat aparın"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Digər jestlərə tıklaya, sürüşdürə və əməliyyat apara bilərsiniz."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Barmaq izi işarələri"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Cihazların barmaq izi sensorunda olan işarələri əldə edə bilər"</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"status panelini deaktivləşdir və ya dəyişdir"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Tətbiqə status panelini deaktiv etməyə və ya sistem ikonalarını əlavə etmək və ya silmək imkanı verir."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"status paneli edin"</string>
@@ -1146,6 +1148,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"Əlavə seçimlər üçün tıklayın."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB sazlama qoşuludur"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"USB debaqı deaktivasiya etmək üçün tıklayın."</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"USb debaqı deaktivasiya etməyi seçin."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Baq hesabatı verilir..."</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Baq hesabatı paylaşılsın?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Baq hesabatı paylaşılır..."</string>
@@ -1689,4 +1692,7 @@
<string name="app_category_news" msgid="7496506240743986873">"Xəbər və Jurnallar"</string>
<string name="app_category_maps" msgid="5878491404538024367">"Xəritə və Naviqasiya"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"Məhsuldarlıq"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Cihaz yaddaşı"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index 810ed0f..e56d938 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -281,6 +281,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Upravlja nivoom zumiranja prikaza i određivanjem položaja."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Obavljanje pokreta"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Može da dodiruje, lista, skuplja prikaz i obavlja druge pokrete."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Pokreti za otisak prsta"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Može da registruje pokrete na senzoru za otisak prsta na uređaju."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"onemogućavanje ili izmena statusne trake"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Dozvoljava aplikaciji da onemogući statusnu traku ili da dodaje i uklanja sistemske ikone."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"funkcionisanje kao statusna traka"</string>
@@ -1166,6 +1168,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"Dodirnite za još opcija."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Otklanjanje grešaka sa USB-a je uspostavljeno"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"Dodirnite da biste onemogućili otklanjanje grešaka sa USB-a."</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Izaberite da biste onemogućili otklanjanja grešaka sa USB-a."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Izveštaj o grešci se generiše…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Želite li da podelite izveštaj o grešci?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Deli se izveštaj o grešci…"</string>
@@ -1720,4 +1723,7 @@
<string name="app_category_news" msgid="7496506240743986873">"Novosti i časopisi"</string>
<string name="app_category_maps" msgid="5878491404538024367">"Mape i navigacija"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"Produktivnost"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Memorijski prostor uređaja"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 7ad40c4..6383c39 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -284,6 +284,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Кіраваць маштабам дысплэя і пазіцыянаваннем."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Выконваць жэсты"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Можна кранаць, праводзіць пальцам, маштабаваць шчыпком, а таксама выконваць іншыя жэсты."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Жэсты адбіткаў пальцаў"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Можа распазнаваць жэсты на сканеры адбіткаў пальцаў прылады."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"адключаць ці змяняць радок стану"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Дазваляе прыкладанням адключаць радок стану або дадаваць і выдаляць сістэмныя значкі."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"быць панэллю стану"</string>
@@ -1186,6 +1188,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"Дакраніцеся, каб атрымаць іншыя параметры."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Адладка па USB падключана"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"Дакраніцеся, каб адключыць адладку па USB."</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Выберыце, каб адключыць адладку USB."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Стварэнне справаздачы пра памылку…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Падзяліцца справаздачай пра памылку?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Перадача справаздачы пра памылку..."</string>
@@ -1751,4 +1754,7 @@
<string name="app_category_news" msgid="7496506240743986873">"Навіны і часопісы"</string>
<string name="app_category_maps" msgid="5878491404538024367">"Карты і навігацыя"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"Прадукцыйнасць"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Сховішча на прыладзе"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 9afed47..1238e2c 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Управление на нивото на мащаба и позиционирането на дисплея."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Извършване на жестове"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Можете да докосвате, да прекарвате пръст, да събирате пръсти и да извършвате други жестове."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Жестове за отпечатък"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Може да улавя жестовете, извършени върху сензора за отпечатъци на устройството."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"деактивиране или промяна на лентата на състоянието"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Разрешава на приложението да деактивира лентата на състоянието или да добавя и премахва системни икони."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"изпълняване на ролята на лента на състоянието"</string>
@@ -1146,6 +1148,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"Докоснете за още опции."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Отстраняване на грешки през USB"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"Докоснете, за да деактивирате отстраняването на грешки през USB."</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Изберете, за да деактивирате отстраняването на грешки през USB."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Сигналът за програмна грешка се извлича…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Да се сподели ли сигналът за програмна грешка?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Сигналът за програмна грешка се споделя…"</string>
@@ -1689,4 +1692,7 @@
<string name="app_category_news" msgid="7496506240743986873">"Новини и списания"</string>
<string name="app_category_maps" msgid="5878491404538024367">"Карти и навигация"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"Производителност"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Хранилище на устройството"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index 6522537..9bedf58 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -63,8 +63,8 @@
<string name="needPuk2" msgid="4526033371987193070">"সিম কার্ড অবরোধ মুক্ত করতে PUK2 লিখুন৷"</string>
<string name="enablePin" msgid="209412020907207950">"অসফল, সিম/RUIM লক সক্ষম করুন৷"</string>
<plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
- <item quantity="one">আপনার কাছে আর <xliff:g id="NUMBER_1">%d</xliff:g>টি প্রচেষ্টা বাকি রয়েছে এটির পরেই আপনার SIM লক হয়ে যাবে৷</item>
- <item quantity="other">আপনার কাছে আর <xliff:g id="NUMBER_1">%d</xliff:g>টি প্রচেষ্টা বাকি রয়েছে এটির পরেই আপনার SIM লক হয়ে যাবে৷</item>
+ <item quantity="one">আপনার কাছে আর <xliff:g id="NUMBER_1">%d</xliff:g>টি প্রচেষ্টা বাকি রয়েছে এটির পরেই আপনার সিম লক হয়ে যাবে৷</item>
+ <item quantity="other">আপনার কাছে আর <xliff:g id="NUMBER_1">%d</xliff:g>টি প্রচেষ্টা বাকি রয়েছে এটির পরেই আপনার সিম লক হয়ে যাবে৷</item>
</plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
@@ -255,7 +255,7 @@
<string name="permgrouplab_calendar" msgid="5863508437783683902">"ক্যালেন্ডার"</string>
<string name="permgroupdesc_calendar" msgid="3889615280211184106">"আপনার ক্যালেন্ডারে অ্যাক্সেস"</string>
<string name="permgrouplab_sms" msgid="228308803364967808">"SMS"</string>
- <string name="permgroupdesc_sms" msgid="4656988620100940350">"SMS বার্তাগুলি পাঠাতে এবং দেখতে"</string>
+ <string name="permgroupdesc_sms" msgid="4656988620100940350">"এসএমএসগুলি পাঠাতে এবং দেখতে"</string>
<string name="permgrouplab_storage" msgid="1971118770546336966">"সঞ্চয়স্থান"</string>
<string name="permgroupdesc_storage" msgid="637758554581589203">"আপনার ডিভাইসে ফটো, মিডিয়া এবং ফাইলগুলিতে অ্যাক্সেস"</string>
<string name="permgrouplab_microphone" msgid="171539900250043464">"মাইক্রোফোন"</string>
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"প্রদর্শনের জুমের স্তর এবং অবস্থান নির্ধারন নিয়ন্ত্রণ করুন৷"</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"অঙ্গভঙ্গির কাজগুলি সম্পাদন করুন"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"আলতো চাপ দেওয়া, সোয়াইপ, পিঞ্চ করা এবং অন্যান্য অঙ্গভঙ্গির কাজগুলি সম্পাদন করতে পারবেন৷"</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"ফিঙ্গারপ্রিন্ট সেন্সরের উপর করা অঙ্গভঙ্গিগুলি"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"ডিভাইসের ফিঙ্গারপ্রিন্ট সেন্সরের উপর আঙ্গুলের অঙ্গভঙ্গি ক্যাপচার করতে পারে।"</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"স্থিতি দন্ড নিষ্ক্রিয় অথবা সংশোধন করে"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"অ্যাপ্লিকেশানকে স্থিতি দন্ড অক্ষম করতে এবং সিস্টেম আইকনগুলি সরাতে দেয়৷"</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"স্থিতি দন্ডে থাকুন"</string>
@@ -291,7 +293,7 @@
<string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"আউটগোয়িং কলগুলি পুনঃচালিত করুন"</string>
<string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"অ্যাপ্লিকেশানকে কল চলাকালীন অন্য একটি নম্বরে কল পুনঃনির্দেশ বা কলটি একসথে বন্ধ করার সাথে ডায়াল করা নম্বরটি দেখতে দেয়৷"</string>
<string name="permlab_receiveSms" msgid="8673471768947895082">"পাঠ্য বার্তা পান (SMS)"</string>
- <string name="permdesc_receiveSms" msgid="6424387754228766939">"অ্যাপ্লিকেশানটিকে SMS বার্তা প্রাপ্ত করার এবং প্রক্রিয়া করার অনুমতি দেয়৷ এর মানে হল অ্যাপ্লিকেশানটি আপনার ডিভাইস থেকে পাঠানো বার্তাগুলিকে পর্যবেক্ষণ করতে পারে এবং মুছতে পারে সেগুলিকে আপনাকে না দেখিয়ে৷"</string>
+ <string name="permdesc_receiveSms" msgid="6424387754228766939">"অ্যাপ্লিকেশানটিকে এসএমএস প্রাপ্ত করার এবং প্রক্রিয়া করার অনুমতি দেয়৷ এর মানে হল অ্যাপ্লিকেশানটি আপনার ডিভাইস থেকে পাঠানো বার্তাগুলিকে পর্যবেক্ষণ করতে পারে এবং মুছতে পারে সেগুলিকে আপনাকে না দেখিয়ে৷"</string>
<string name="permlab_receiveMms" msgid="1821317344668257098">"পাঠ্য বার্তা পান (MMS)"</string>
<string name="permdesc_receiveMms" msgid="533019437263212260">"অ্যাপ্লিকেশানটিকে MMS বার্তা প্রাপ্ত করার এবং প্রক্রিয়া করার অনুমতি দেয়৷ এর মানে হল অ্যাপ্লিকেশানটি আপনার ডিভাইস থেকে পাঠানো বার্তাগুলিকে পর্যবেক্ষণ করতে পারে এবং মুছতে পারে সেগুলিকে আপনাকে না দেখিয়ে৷"</string>
<string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"সেল সম্প্রচার বার্তা পড়ুন"</string>
@@ -299,7 +301,7 @@
<string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"গ্রাহক হিসাবে নেওয়া ফিডগুলি পড়ে"</string>
<string name="permdesc_subscribedFeedsRead" msgid="5557058907906144505">"অ্যাপ্লিকেশানকে বর্তমানে সিঙ্ক করা ফিডগুলির সম্পর্কে বিবরণ পেতে দেয়৷"</string>
<string name="permlab_sendSms" msgid="7544599214260982981">"SMS পাঠানো ও দেখা,আপনি কি পরিচিতি কে এগুলি করার অনুমতি দেবেন?"</string>
- <string name="permdesc_sendSms" msgid="7094729298204937667">"অ্যাপ্লিকেশানটিকে SMS বার্তাগুলি পাঠাতে অনুমতি দেয়৷ এর জন্য অপ্রত্যাশিত চার্জ কাটা হতে পারে৷ ক্ষতিকারক অ্যাপ্লিকেশানগুলি আপনার নিশ্চিতকরণ ছাড়া বার্তা পাঠানোর মাধ্যমে আপনাকে অর্থ চার্জ করতে পারে৷"</string>
+ <string name="permdesc_sendSms" msgid="7094729298204937667">"অ্যাপ্লিকেশানটিকে এসএমএসগুলি পাঠাতে অনুমতি দেয়৷ এর জন্য অপ্রত্যাশিত চার্জ কাটা হতে পারে৷ ক্ষতিকারক অ্যাপ্লিকেশানগুলি আপনার নিশ্চিতকরণ ছাড়া বার্তা পাঠানোর মাধ্যমে আপনাকে অর্থ চার্জ করতে পারে৷"</string>
<string name="permlab_readSms" msgid="8745086572213270480">"আপনার পাঠ্য বার্তা পড়ুন (SMS বা MMS)"</string>
<string name="permdesc_readSms" product="tablet" msgid="4741697454888074891">"এই অ্যাপটি আপনার ট্যাবলেটে সংরক্ষিত সমস্ত SMS (পাঠ্য) বার্তা পড়তে পারে৷"</string>
<string name="permdesc_readSms" product="tv" msgid="5796670395641116592">"এই অ্যাপটি আপনার টিভিতে সংরক্ষিত সমস্ত SMS (পাঠ্য) বার্তা পড়তে পারে৷"</string>
@@ -370,7 +372,7 @@
<string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"ভলিউম এবং যেখানে স্পিকার আউটপুট সামগ্রী হিসাবে ব্যবহৃত হয় সেই সব ক্ষেত্রে গ্লোবাল অডিও সেটিংসের সংশোধন করতে অ্যাপ্লিকেশানটিকে মঞ্জুর করে৷"</string>
<string name="permlab_recordAudio" msgid="3876049771427466323">"অডিও রেকর্ড"</string>
<string name="permdesc_recordAudio" msgid="4245930455135321433">"এই অ্যাপটি মাইক্রোফোন ব্যবহার করে যে কোনো সময় অডিও রেকর্ড করতে পারে৷"</string>
- <string name="permlab_sim_communication" msgid="2935852302216852065">"SIM এ আদেশগুলি পাঠান"</string>
+ <string name="permlab_sim_communication" msgid="2935852302216852065">"সিম এ আদেশগুলি পাঠান"</string>
<string name="permdesc_sim_communication" msgid="5725159654279639498">"অ্যাপ্লিকেশানটিকে সিম কার্ডে কমান্ডগুলি পাঠানোর অনুমতি দেয়৷ এটি খুবই বিপজ্জনক৷"</string>
<string name="permlab_camera" msgid="3616391919559751192">"ছবি এবং ভিডিও তোলে"</string>
<string name="permdesc_camera" msgid="5392231870049240670">"এই অ্যাপটি যে কোনো সময় ক্যামেরা ব্যবহার করে ছবি তুলতে বা ভিডিও রেকর্ড করতে পারে৷"</string>
@@ -479,8 +481,8 @@
<string name="permdesc_sdcardWrite" product="default" msgid="4337417790936632090">"অ্যাপ্লিকেশানকে SD কার্ডে লেখার অনুমতি দেয়৷"</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"SIP কল করুন/গ্রহণ করুন"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"অ্যাপ্লিকেশানকে SIP কল করতে ও গ্রহণ করতে অনুমতি দেয়।"</string>
- <string name="permlab_register_sim_subscription" msgid="3166535485877549177">"নতুন টেলিকম SIM সংযোগগুলির নিবন্ধন"</string>
- <string name="permdesc_register_sim_subscription" msgid="2138909035926222911">"অ্যাপ্লিকেশানটিকে নতুন টেলিকম SIM সংযোগগুলি নিবন্ধিত করতে অনুমোদিত করে৷"</string>
+ <string name="permlab_register_sim_subscription" msgid="3166535485877549177">"নতুন টেলিকম সিম সংযোগগুলির নিবন্ধন"</string>
+ <string name="permdesc_register_sim_subscription" msgid="2138909035926222911">"অ্যাপ্লিকেশানটিকে নতুন টেলিকম সিম সংযোগগুলি নিবন্ধিত করতে অনুমোদিত করে৷"</string>
<string name="permlab_register_call_provider" msgid="108102120289029841">"নতুন টেলিকম সংযোগগুলির নিবন্ধন"</string>
<string name="permdesc_register_call_provider" msgid="7034310263521081388">"নতুন টেলিকম সংযোগ নিবন্ধিত করতে অ্যাপ্লিকেশানটিকে অনুমোদিত করে৷"</string>
<string name="permlab_connection_manager" msgid="1116193254522105375">"টেলিকম সংযোগগুলি পরিচালনা করুন"</string>
@@ -692,7 +694,7 @@
<string name="faceunlock_multiple_failures" msgid="754137583022792429">"মুখের সাহায্যে আনলক করার প্রচেষ্টা যতবার করা যায় তার সীমা পেরিয়ে গেছে"</string>
<string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"কোনো সিম কার্ড নেই"</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"ট্যাবলেটের মধ্যে কোনো সিম কার্ড নেই৷"</string>
- <string name="lockscreen_missing_sim_message" product="tv" msgid="1943633865476989599">"টিভির মধ্যে কোনো SIM কার্ড নেই৷"</string>
+ <string name="lockscreen_missing_sim_message" product="tv" msgid="1943633865476989599">"টিভির মধ্যে কোনো সিম কার্ড নেই৷"</string>
<string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"ফোনের মধ্যে কোনো সিম কার্ড নেই৷"</string>
<string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"একটি সিম কার্ড ঢোকান৷"</string>
<string name="lockscreen_missing_sim_instructions_long" msgid="3526573099019319472">"সিম কার্ডটি অনুপস্থিত বা পাঠযোগ্য নয়৷ একটি সিম কার্ড ঢোকান৷"</string>
@@ -1104,8 +1106,8 @@
<string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="3087858235069421128">"আপনার টিভি <xliff:g id="DEVICE_NAME">%1$s</xliff:g> এ সংযুক্ত থাকার সময় ওয়াই-ফাই থেকে সাময়িকভাবে সংযোগ বিচ্ছিন্ন হবে৷"</string>
<string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"ফোনটি যখন <xliff:g id="DEVICE_NAME">%1$s</xliff:g> এ সংযুক্ত হবে তখন এটি ওয়াই-ফাই থেকে সাময়িকভাবে সংযোগ বিচ্ছিন্ন হবে"</string>
<string name="select_character" msgid="3365550120617701745">"অক্ষর ঢোকান"</string>
- <string name="sms_control_title" msgid="7296612781128917719">"SMS বার্তা পাঠানো হচ্ছে"</string>
- <string name="sms_control_message" msgid="3867899169651496433">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> অনেকগুলি SMS বার্তা পাঠাচ্ছে৷ আপনি কি এই অ্যাপ্লিকেশানটিকে বার্তা পাঠানো চালিয়ে যাওয়ার অনুমতি দিতে চান?"</string>
+ <string name="sms_control_title" msgid="7296612781128917719">"এসএমএস পাঠানো হচ্ছে"</string>
+ <string name="sms_control_message" msgid="3867899169651496433">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> অনেকগুলি এসএমএস পাঠাচ্ছে৷ আপনি কি এই অ্যাপ্লিকেশানটিকে বার্তা পাঠানো চালিয়ে যাওয়ার অনুমতি দিতে চান?"</string>
<string name="sms_control_yes" msgid="3663725993855816807">"অনুমতি দিন"</string>
<string name="sms_control_no" msgid="625438561395534982">"আস্বীকার করুন"</string>
<string name="sms_short_code_confirm_message" msgid="1645436466285310855">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> <b><xliff:g id="DEST_ADDRESS">%2$s</xliff:g></b> এ একটি বার্তা পাঠাতে চায়৷"</string>
@@ -1123,10 +1125,10 @@
<string name="sim_added_title" msgid="3719670512889674693">"সিম কার্ড যোগ করা হয়েছে"</string>
<string name="sim_added_message" msgid="7797975656153714319">"সেলুলার নেটওয়ার্ক অ্যাক্সেস করতে আপনার ডিভাইস পুনর্সূচনা করুন"</string>
<string name="sim_restart_button" msgid="4722407842815232347">"পুনর্সূচনা"</string>
- <string name="carrier_app_dialog_message" msgid="7066156088266319533">"যাতে আপনার নতুন SIM সঠিকভাবে কাজ করে, তার জন্য আপনাকে আপনার পরিষেবা প্রদানকারীর থেকে একটি অ্যাপ্লিকেশান ইনস্টল করতে এবং খুলতে হবে৷"</string>
+ <string name="carrier_app_dialog_message" msgid="7066156088266319533">"যাতে আপনার নতুন সিম সঠিকভাবে কাজ করে, তার জন্য আপনাকে আপনার পরিষেবা প্রদানকারীর থেকে একটি অ্যাপ্লিকেশান ইনস্টল করতে এবং খুলতে হবে৷"</string>
<string name="carrier_app_dialog_button" msgid="7900235513678617329">"অ্যাপ্লিকেশানটি পান"</string>
<string name="carrier_app_dialog_not_now" msgid="6361378684292268027">"এখনই নয়"</string>
- <string name="carrier_app_notification_title" msgid="8921767385872554621">"নতুন SIM ঢোকানো হয়েছে"</string>
+ <string name="carrier_app_notification_title" msgid="8921767385872554621">"নতুন সিম ঢোকানো হয়েছে"</string>
<string name="carrier_app_notification_text" msgid="1132487343346050225">"এটিকে সেট আপ করতে আলতো চাপুন"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"সময় সেট করুন"</string>
<string name="date_picker_dialog_title" msgid="5879450659453782278">"তারিখ সেট করুন"</string>
@@ -1146,6 +1148,8 @@
<string name="usb_notification_message" msgid="3370903770828407960">"আরো বিকল্পের জন্য আলতো চাপুন৷"</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB ডিবাগিং সংযুক্ত হয়েছে"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"USB ডিবাগিং অক্ষম করতে আলতো চাপুন৷"</string>
+ <!-- no translation found for adb_active_notification_message (8470296818270110396) -->
+ <skip />
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"ত্রুটির প্রতিবেদন নেওয়া হচ্ছে..."</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"ত্রুটির প্রতিবেদন শেয়ার করবেন?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"ত্রুটির প্রতিবেদন শেয়ার করা হচ্ছে..."</string>
@@ -1689,4 +1693,7 @@
<string name="app_category_news" msgid="7496506240743986873">"খবর ও পত্রিকাগুলি"</string>
<string name="app_category_maps" msgid="5878491404538024367">"মানচিত্র ও নেভিগেশান"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"উৎপাদনশীলতা"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"ডিভাইসের সঞ্চয়স্থান"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index c6d70f3..66ef19a 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -281,6 +281,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Kontrolira stepen uvećanja prikaza na ekranu i podešavanje položaja."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Praviti pokrete"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Može dodirivati, prevlačiti, hvatati prstima i praviti druge pokrete."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Pokreti otiska prsta"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Moguće je zabilježiti pokrete na senzoru za otisak prsta uređaja."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"onemogućavanje ili mijenjanje statusne trake"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Dozvoljava aplikaciji onemogućavanje statusne trake ili dodavanje i uklanjanje sistemskih ikona."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"funkcioniranje u vidu statusne trake"</string>
@@ -1168,6 +1170,8 @@
<string name="usb_notification_message" msgid="3370903770828407960">"Dodirnite za više opcija."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Otklanjanje grešaka putem uređaja spojenog na USB je uspostavljeno"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"Dodirnite da onemogućite otklanjanje grešaka putem uređaja spojenog na USB."</string>
+ <!-- no translation found for adb_active_notification_message (8470296818270110396) -->
+ <skip />
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Prijem izvještaja o grešci..."</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Podijeliti izvještaj o grešci?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Dijeljenje izvještaja o grešci..."</string>
@@ -1722,4 +1726,7 @@
<string name="app_category_news" msgid="7496506240743986873">"Vijesti i časopisi"</string>
<string name="app_category_maps" msgid="5878491404538024367">"Mape i navigacija"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"Produktivnost"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Memorija uređaja"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index eebe75f..b01f382 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Controla el nivell i el posicionament del zoom de la pantalla."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Utilitza gestos"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Pot tocar, lliscar, pessigar i utilitzar altres gestos."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Gestos amb les empremtes digitals"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Captura gestos realitzats en el sensor d\'empremtes digitals del dispositiu."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"desactivar o modificar la barra d\'estat"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Permet que l\'aplicació desactivi la barra d\'estat o afegeixi i elimini icones del sistema."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"aparèixer a la barra d\'estat"</string>
@@ -950,7 +952,7 @@
<string name="inputMethod" msgid="1653630062304567879">"Mètode d\'introducció de text"</string>
<string name="editTextMenuTitle" msgid="4909135564941815494">"Accions de text"</string>
<string name="email" msgid="4560673117055050403">"Correu electrònic"</string>
- <string name="dial" msgid="2275093056198652749">"Marcatge"</string>
+ <string name="dial" msgid="2275093056198652749">"Telèfon"</string>
<string name="map" msgid="5441053548030107189">"Mapa"</string>
<string name="low_internal_storage_view_title" msgid="5576272496365684834">"L\'espai d\'emmagatzematge s\'està esgotant"</string>
<string name="low_internal_storage_view_text" msgid="6640505817617414371">"És possible que algunes funcions del sistema no funcionin"</string>
@@ -1146,6 +1148,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"Toca per veure més opcions."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Depuració USB activada"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"Toca per desactivar la depuració USB."</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Selecciona per desactivar la depuració USB"</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"S\'està creant l\'informe d\'errors…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Vols compartir l\'informe d\'errors?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"S\'està compartint l\'informe d\'errors…"</string>
@@ -1689,4 +1692,7 @@
<string name="app_category_news" msgid="7496506240743986873">"Notícies i revistes"</string>
<string name="app_category_maps" msgid="5878491404538024367">"Mapes i navegació"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"Productivitat"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Emmagatzematge del dispositiu"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 68cc583..b8717d5 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -284,6 +284,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Určuje umístění a úroveň přiblížení displeje."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Provádění gest"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Může provádět gesta klepnutí, přejetí, stažení prstů a další."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Gesta otiskem prstu"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Dokáže rozpoznat gesta zadaná na snímači otisků prstů."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"zakázání či změny stavového řádku"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Umožňuje aplikaci zakázat stavový řádek nebo přidat či odebrat systémové ikony."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"vydávání se za stavový řádek"</string>
@@ -1186,6 +1188,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"Klepnutím zobrazíte další možnosti."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Ladění přes USB připojeno"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"Klepnutím zakážete ladění USB."</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Vyberte, chcete-li zakázat ladění USB."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Vytváření zprávy o chybě…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Sdílet zprávu o chybě?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Sdílení zprávy o chybě…"</string>
@@ -1751,4 +1754,7 @@
<string name="app_category_news" msgid="7496506240743986873">"Zprávy a časopisy"</string>
<string name="app_category_maps" msgid="5878491404538024367">"Mapy a navigace"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"Produktivita"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Úložiště zařízení"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index f2b6be9..ebcd48e 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Kontrollér skærmens zoomniveau og position."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Udfør bevægelser"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Kan trykke, stryge, knibe sammen og udføre andre bevægelser."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Fingeraftryksbevægelser"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Kan registrere bevægelser, der foretages på enhedernes fingeraftrykslæser."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"deaktiver eller rediger statuslinje"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Tillader, at appen kan deaktivere statusbjælken eller tilføje og fjerne systemikoner."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"vær statusbjælken"</string>
@@ -1146,6 +1148,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"Tryk for at se flere muligheder."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB-fejlretning er tilsluttet"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"Tryk for at deaktivere fejlretning via USB."</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Vælg for at deaktivere USB-fejlretning."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Opretter fejlrapport…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Vil du dele fejlrapporten?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Deler fejlrapport…"</string>
@@ -1395,7 +1398,7 @@
<string name="kg_wrong_pin" msgid="1131306510833563801">"Forkert pinkode"</string>
<string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"Prøv igen om <xliff:g id="NUMBER">%1$d</xliff:g> sekunder."</string>
<string name="kg_pattern_instructions" msgid="398978611683075868">"Tegn dit mønster"</string>
- <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"Indtast pinkode til SIM"</string>
+ <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"Indtast pinkode til SIM-kort"</string>
<string name="kg_pin_instructions" msgid="2377242233495111557">"Indtast pinkode"</string>
<string name="kg_password_instructions" msgid="5753646556186936819">"Angiv adgangskode"</string>
<string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"SIM-kortet er nu deaktiveret. Indtast PUK-koden for at fortsætte. Kontakt mobiloperatøren for at få flere oplysninger."</string>
@@ -1689,4 +1692,7 @@
<string name="app_category_news" msgid="7496506240743986873">"Aviser og blade"</string>
<string name="app_category_maps" msgid="5878491404538024367">"Kort og navigation"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"Produktivitet"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Lagerplads på enheden"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 5ba5464..7e31748 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Legt die Zoom-Stufe des Displays und die Zoom-Position auf dem Display fest."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Bewegungen möglich"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Tippen, Wischen, Zusammenziehen und andere Bewegungen möglich."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Bewegungen auf dem Fingerabdrucksensor"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Erfasst Bewegungen auf dem Fingerabdrucksensor des Geräts."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"Statusleiste deaktivieren oder ändern"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Ermöglicht der App, die Statusleiste zu deaktivieren oder Systemsymbole hinzuzufügen oder zu entfernen"</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"Statusleiste darstellen"</string>
@@ -1146,6 +1148,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"Für weitere Optionen tippen."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB-Debugging aktiviert"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"Zum Deaktivieren von USB-Debugging tippen."</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"USB-Debugging deaktivieren: auswählen"</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Fehlerbericht wird abgerufen…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Fehlerbericht teilen?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Fehlerbericht wird geteilt…"</string>
@@ -1689,4 +1692,7 @@
<string name="app_category_news" msgid="7496506240743986873">"Nachrichten & Zeitschriften"</string>
<string name="app_category_maps" msgid="5878491404538024367">"Karten & Navigation"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"Effizienz"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Gerätespeicher"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 409b573..7458e04 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Ελέγξτε το επίπεδο ζουμ και τη θέση της οθόνης."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Εκτέλεση κινήσεων"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Επιτρέπει το πάτημα, την ολίσθηση, το πλησίασμα και άλλες κινήσεις."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Κινήσεις δακτυλικών αποτυπωμάτων"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Μπορεί να αναγνωρίσει κινήσεις που εκτελούνται στον αισθητήρα δακτυλικών αποτυπωμάτων των συσκευών."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"απενεργοποιεί ή να τροποποιεί την γραμμή κατάστασης"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Επιτρέπει στην εφαρμογή να απενεργοποιεί τη γραμμή κατάστασης ή να προσθέτει και να αφαιρεί εικονίδια συστήματος."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"ορίζεται ως γραμμή κατάστασης"</string>
@@ -1146,6 +1148,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"Πατήστε για περισσότερες επιλογές."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Συνδέθηκε ο εντοπισμός σφαλμάτων USB"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"Πατήστε για απενεργοποίηση του εντοπισμού σφαλμάτων USB."</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Επιλογή για απενεργοποίηση του εντοπισμού σφαλμάτων USB."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Λήψη αναφοράς σφάλματος…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Κοινή χρήση αναφοράς σφάλματος;"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Κοινή χρήση αναφοράς σφάλματος…"</string>
@@ -1689,4 +1692,7 @@
<string name="app_category_news" msgid="7496506240743986873">"Ειδήσεις και περιοδικά"</string>
<string name="app_category_maps" msgid="5878491404538024367">"Χάρτες και πλοήγηση"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"Παραγωγικότητα"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Αποθηκευτικός χώρος συσκευής"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 02860cf..107f247 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Control the display\'s zoom level and positioning."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Perform gestures"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Can tap, swipe, pinch and perform other gestures."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Fingerprint gestures"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Can capture gestures performed on the devices fingerprint sensor."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"disable or modify status bar"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Allows the app to disable the status bar or add and remove system icons."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"be the status bar"</string>
@@ -1146,6 +1148,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"Tap for more options."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB debugging connected"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"Tap to disable USB debugging."</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Select to disable USB debugging."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Taking bug report…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Share bug report?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Sharing bug report…"</string>
@@ -1689,4 +1692,7 @@
<string name="app_category_news" msgid="7496506240743986873">"News & Magazines"</string>
<string name="app_category_maps" msgid="5878491404538024367">"Maps & Navigation"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"Productivity"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Device storage"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 02860cf..107f247 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Control the display\'s zoom level and positioning."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Perform gestures"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Can tap, swipe, pinch and perform other gestures."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Fingerprint gestures"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Can capture gestures performed on the devices fingerprint sensor."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"disable or modify status bar"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Allows the app to disable the status bar or add and remove system icons."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"be the status bar"</string>
@@ -1146,6 +1148,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"Tap for more options."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB debugging connected"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"Tap to disable USB debugging."</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Select to disable USB debugging."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Taking bug report…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Share bug report?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Sharing bug report…"</string>
@@ -1689,4 +1692,7 @@
<string name="app_category_news" msgid="7496506240743986873">"News & Magazines"</string>
<string name="app_category_maps" msgid="5878491404538024367">"Maps & Navigation"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"Productivity"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Device storage"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 02860cf..107f247 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Control the display\'s zoom level and positioning."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Perform gestures"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Can tap, swipe, pinch and perform other gestures."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Fingerprint gestures"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Can capture gestures performed on the devices fingerprint sensor."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"disable or modify status bar"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Allows the app to disable the status bar or add and remove system icons."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"be the status bar"</string>
@@ -1146,6 +1148,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"Tap for more options."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB debugging connected"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"Tap to disable USB debugging."</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Select to disable USB debugging."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Taking bug report…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Share bug report?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Sharing bug report…"</string>
@@ -1689,4 +1692,7 @@
<string name="app_category_news" msgid="7496506240743986873">"News & Magazines"</string>
<string name="app_category_maps" msgid="5878491404538024367">"Maps & Navigation"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"Productivity"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Device storage"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index bd3ac31..2749b35 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Controla el posicionamiento y el nivel de zoom de la pantalla."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Usar gestos"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Permite presionar, deslizar, pellizcar y usar otros gestos."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Gestos del sensor de huellas digitales"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Captura los gestos que se hacen en el sensor de huellas digitales de los dispositivos."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"desactivar o modificar la barra de estado"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Permite que la aplicación inhabilite la barra de estado o que agregue y elimine íconos del sistema."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"aparecer en la barra de estado"</string>
@@ -1146,6 +1148,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"Presiona para ver más opciones."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Depuración por USB conectada"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"Presiona para inhabilitar la depuración por USB."</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Seleccionar para desactivar la depuración por USB"</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Realizando un informe de errores…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"¿Compartir informe de errores?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Compartiendo informe de errores…"</string>
@@ -1689,4 +1692,7 @@
<string name="app_category_news" msgid="7496506240743986873">"Noticias y revistas"</string>
<string name="app_category_maps" msgid="5878491404538024367">"Mapas y navegación"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"Productividad"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Almacenamiento del dispositivo"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 26f6005..bdb1381 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Controla el posicionamiento y el nivel de zoom de la pantalla."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Realizar gestos"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Puedes tocar y pellizcar la pantalla, deslizar el dedo y hacer otros gestos."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Gestos de huellas digitales"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Puede capturar los gestos realizados en el sensor de huellas digitales del dispositivo."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"inhabilitar o modificar la barra de estado"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Permite que la aplicación inhabilite la barra de estado o añada y elimine iconos del sistema."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"aparecer en la barra de estado"</string>
@@ -949,12 +951,9 @@
<string name="deleteText" msgid="6979668428458199034">"Eliminar"</string>
<string name="inputMethod" msgid="1653630062304567879">"Método de introducción de texto"</string>
<string name="editTextMenuTitle" msgid="4909135564941815494">"Acciones de texto"</string>
- <!-- no translation found for email (4560673117055050403) -->
- <skip />
- <!-- no translation found for dial (2275093056198652749) -->
- <skip />
- <!-- no translation found for map (5441053548030107189) -->
- <skip />
+ <string name="email" msgid="4560673117055050403">"Correo electrónico"</string>
+ <string name="dial" msgid="2275093056198652749">"Marcar"</string>
+ <string name="map" msgid="5441053548030107189">"Mapa"</string>
<string name="low_internal_storage_view_title" msgid="5576272496365684834">"Queda poco espacio"</string>
<string name="low_internal_storage_view_text" msgid="6640505817617414371">"Es posible que algunas funciones del sistema no funcionen."</string>
<string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"No hay espacio suficiente para el sistema. Comprueba que haya 250 MB libres y reinicia el dispositivo."</string>
@@ -1149,6 +1148,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"Toca para ver más opciones."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Depuración USB habilitada"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"Toca para inhabilitar la depuración USB."</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Seleccionar para inhabilitar la depuración USB"</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Creando informe de errores…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"¿Compartir informe de errores?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Compartiendo informe de errores…"</string>
@@ -1205,10 +1205,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Permite que una aplicación consulte sesiones de instalación para ver detalles sobre instalaciones de paquetes activos."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"solicitar instalación de paquetes"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Permite a una aplicación solicitar la instalación de paquetes."</string>
- <!-- no translation found for permlab_requestDeletePackages (1703686454657781242) -->
- <skip />
- <!-- no translation found for permdesc_requestDeletePackages (3406172963097595270) -->
- <skip />
+ <string name="permlab_requestDeletePackages" msgid="1703686454657781242">"solicitar eliminación de paquetes"</string>
+ <string name="permdesc_requestDeletePackages" msgid="3406172963097595270">"Permite a una aplicación solicitar la eliminación de paquetes."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"solicitar permiso para ignorar las optimizaciones de la batería"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"Permite que una aplicación solicite permiso para ignorar las optimizaciones de la batería."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Da dos toques para acceder al control de zoom."</string>
@@ -1694,4 +1692,7 @@
<string name="app_category_news" msgid="7496506240743986873">"Noticias y revistas"</string>
<string name="app_category_maps" msgid="5878491404538024367">"Mapas y navegación"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"Productividad"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Almacenamiento del dispositivo"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 30e73d8..5b532b4 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Saate juhtida ekraani suumitaset ja asendit."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Liigutuste tegemine"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Saate puudutada, pühkida, sõrmi kokku-lahku liigutada ja teisi liigutusi teha."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Sõrmejälje liigutused"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Teil on võimalik jäädvustada liigutused, mis on tehtud seadmete sõrmejäljeanduri abil."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"keela või muuda olekuriba"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Võimaldab rakendusel keelata olekuriba või lisada ja eemaldada süsteemiikoone."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"olekuribana kuvamine"</string>
@@ -1146,6 +1148,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"Puudutage lisavalikute nägemiseks."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB-silumine ühendatud"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"Puudutage USB-silumise keelamiseks."</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Valige USB silumise keelamiseks"</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Veaaruande võtmine …"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Kas jagada veaaruannet?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Veaaruande jagamine …"</string>
@@ -1689,4 +1692,7 @@
<string name="app_category_news" msgid="7496506240743986873">"Uudised ja ajakirjad"</string>
<string name="app_category_maps" msgid="5878491404538024367">"Kaardid ja navigeerimine"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"Produktiivsus"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Seadme salvestusruum"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index a49f94f..afb0a9c 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Kontrolatu pantailaren zoom-maila eta kokapena."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Keinuak egin"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Sakatu, lerratu, atximurkatu eta beste hainbat keinu egin ditzake."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Hatz-marken keinuak"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Gailuaren hatz-marken sentsorean egindako keinuak antzeman ditzake."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"Desgaitu edo aldatu egoera-barra"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Egoera-barra desgaitzea edo sistema-ikonoak gehitzea edo kentzea baimentzen die aplikazioei."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"Bihurtu egoera-barra"</string>
@@ -1146,6 +1148,8 @@
<string name="usb_notification_message" msgid="3370903770828407960">"Sakatu aukera gehiago ikusteko."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB arazketa konektatuta"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"Sakatu USB arazketa desgaitzeko."</string>
+ <!-- no translation found for adb_active_notification_message (8470296818270110396) -->
+ <skip />
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Akatsen txostena sortzen…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Akatsen txostena partekatu nahi duzu?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Akatsen txostena partekatzen…"</string>
@@ -1232,7 +1236,7 @@
<string name="wallpaper_binding_label" msgid="1240087844304687662">"Horma-papera"</string>
<string name="chooser_wallpaper" msgid="7873476199295190279">"Aldatu horma-papera"</string>
<string name="notification_listener_binding_label" msgid="2014162835481906429">"Jakinarazpenak hautemateko zerbitzua"</string>
- <string name="vr_listener_binding_label" msgid="4316591939343607306">"Errealitate birtualeko hautemailea"</string>
+ <string name="vr_listener_binding_label" msgid="4316591939343607306">"EB hautemailea"</string>
<string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Baldintza-hornitzailea"</string>
<string name="notification_ranker_binding_label" msgid="774540592299064747">"Jakinarazpenen sailkapen-zerbitzua"</string>
<string name="vpn_title" msgid="19615213552042827">"VPN eginbidea aktibatuta"</string>
@@ -1689,4 +1693,7 @@
<string name="app_category_news" msgid="7496506240743986873">"Albisteak eta aldizkariak"</string>
<string name="app_category_maps" msgid="5878491404538024367">"Mapak eta nabigazioa"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"Produktibitatea"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Gailuaren memoria"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 3880caa..1e1c8fa 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"سطح و موقعیت بزرگنمایی نمایشگر را کنترل کنید."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"اجرای اشارهها"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"میتوانید ضربه بزنید، انگشتتان را تند بکشید، انگشتانتان را به هم نزدیک یا از هم دور کنید و اشارههای دیگری اجرا کنید."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"اشارههای اثر انگشت"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"میتواند اشارههای انجامشده روی حسگر اثرانگشت دستگاهها را ثبت کند."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"غیرفعال کردن یا تغییر نوار وضعیت"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"به برنامه اجازه میدهد تا نوار وضعیت را غیرفعال کند یا نمادهای سیستم را اضافه یا حذف کند."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"نوار وضعیت باشد"</string>
@@ -1146,6 +1148,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"برای گزینههای بیشتر ضربه بزنید."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"اشکالزدایی USB متصل شد"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"برای غیرفعال کردن اشکالزدایی USB ضربه بزنید."</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"انتخاب کنید تا رفع عیب USB غیرفعال شود."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"درحال گرفتن گزارش اشکال…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"گزارش اشکال به اشتراک گذاشته شود؟"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"درحال اشتراکگذاری گزارش اشکال…"</string>
@@ -1689,4 +1692,7 @@
<string name="app_category_news" msgid="7496506240743986873">"اخبار و مجله"</string>
<string name="app_category_maps" msgid="5878491404538024367">"نقشه و پیمایش"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"بهرهوری"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"حافظه دستگاه"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index f0afbc8..c3c2c65 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Hallinnoi näytön zoomaustasoa ja asettelua."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Eleiden käyttäminen"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Lupa napauttaa, pyyhkäistä, nipistää ja käyttää muita eleitä."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Sormenjälkieleet"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Voi tallentaa laitteen sormenjälkitunnistimella tehtyjä eleitä."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"poista tilapalkki käytöstä tai muokkaa tilapalkkia"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Antaa sovelluksen poistaa tilapalkin käytöstä ja lisätä tai poistaa järjestelmäkuvakkeita."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"sijaita tilapalkissa"</string>
@@ -1146,6 +1148,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"Näet lisää vaihtoehtoja napauttamalla."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB-vianetsintä yhdistetty"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"Poista USB-vianetsintä käytöstä napauttamalla."</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Poista USB-vianetsintä käytöstä valitsemalla tämä."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Luodaan virheraporttia…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Jaetaanko virheraportti?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Jaetaan virheraporttia…"</string>
@@ -1689,4 +1692,7 @@
<string name="app_category_news" msgid="7496506240743986873">"Uutiset ja lehdet"</string>
<string name="app_category_maps" msgid="5878491404538024367">"Kartat ja navigointi"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"Tuottavuus"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Laitteen tallennustila"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 65609f4..7e051c9 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Contrôler le niveau de zoom et le positionnement de l\'écran."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Effectuer des gestes"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Peut toucher, balayer, pincer et effectuer d\'autres gestes."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Gestes sur le capteur d\'empreintes digitales"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Peut capturer des gestes effectués sur le capteur d\'empreintes digitales des appareils."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"désactiver ou modifier la barre d\'état"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Permet à l\'application de désactiver la barre d\'état, ou d\'ajouter et de supprimer des icônes système."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"servir de barre d\'état"</string>
@@ -1146,6 +1148,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"Touchez pour afficher plus d\'options."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Débogage USB connecté"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"Touchez pour désactiver le débogage USB."</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Sélectionnez cette option pour désactiver le débogage USB."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Création d\'un rapport de bogue en cours..."</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Partager le rapport de bogue?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Partage du rapport de bogue en cours..."</string>
@@ -1689,4 +1692,7 @@
<string name="app_category_news" msgid="7496506240743986873">"Actualités et magazines"</string>
<string name="app_category_maps" msgid="5878491404538024367">"Cartes et navigation"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"Productivité"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Mémoire de l\'appareil"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 66fb5b4..b8fcf28 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Contrôler le niveau de zoom et le positionnement de l\'écran"</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Effectuer des gestes"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Permet d\'appuyer sur l\'écran, de le balayer, de le pincer et d\'effectuer d\'autres gestes."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Gestes avec l\'empreinte digitale"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Peut enregistrer des gestes effectués sur le lecteur d\'empreinte digitale de l\'appareil."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"Désactivation ou modification de la barre d\'état"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Permet à l\'application de désactiver la barre d\'état, ou d\'ajouter et de supprimer des icônes système."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"remplacer la barre d\'état"</string>
@@ -1146,6 +1148,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"Appuyez ici pour plus d\'options."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Débogage USB activé"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"Appuyez ici pour désactiver le débogage USB."</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Sélectionnez cette option pour désactiver le débogage USB."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Création du rapport de bug…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Partager le rapport de bug ?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Partage du rapport de bug…"</string>
@@ -1689,4 +1692,7 @@
<string name="app_category_news" msgid="7496506240743986873">"Actualités et magazines"</string>
<string name="app_category_maps" msgid="5878491404538024367">"Plans et navigation"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"Productivité"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Mémoire de l\'appareil"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index 9b335a1..5d316f6 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Controlar o nivel do zoom e o posicionamento da pantalla"</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Realizar xestos"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Podes tocar, pasar o dedo, beliscar e realizar outros xestos."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Xestos de impresión dixital"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Pode rexistrar os xestos realizados no sensor de impresión dixital dos dispositivos."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"desactivar ou modificar a barra de estado"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Permite á aplicación desactivar a barra de estado ou engadir e eliminar as iconas do sistema."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"actuar como a barra de estado"</string>
@@ -1146,6 +1148,8 @@
<string name="usb_notification_message" msgid="3370903770828407960">"Toca para ver máis opcións."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Depuración USB conectada"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"Toca para desactivar a depuración de erros de USB."</string>
+ <!-- no translation found for adb_active_notification_message (8470296818270110396) -->
+ <skip />
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Creando informe de erros…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Queres compartir o informe de erros?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Compartindo informe de erros..."</string>
@@ -1689,4 +1693,7 @@
<string name="app_category_news" msgid="7496506240743986873">"Noticias e revistas"</string>
<string name="app_category_maps" msgid="5878491404538024367">"Mapas e navegación"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"Produtividade"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Almacenamento do dispositivo"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index 2bd3e41..b5c243b 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"પ્રદર્શનનું ઝૂમ સ્તર અને સ્થિતિનિર્ધારણ નિયંત્રિત કરો."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"હાવભાવ કરો"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"ટૅપ, સ્વાઇપ, પિંચ કરી અને અન્ય હાવભાવ કરી શકે છે."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"ફિંગરપ્રિન્ટ હાવભાવો"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"ઉપકરણોનાં ફિંગરપ્રિન્ટ સેન્સર પર ભજવેલા હાવભાવ કૅપ્ચર કરી શકે છે."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"સ્થિતિ બાર અક્ષમ કરો અથવા સંશોધિત કરો"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"એપ્લિકેશનને સ્થિતિ બાર અક્ષમ કરવાની અથવા સિસ્ટમ આયકન્સ ઉમેરવા અને દૂર કરવાની મંજૂરી આપે છે."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"સ્થિતિ બાર થાઓ"</string>
@@ -1146,6 +1148,8 @@
<string name="usb_notification_message" msgid="3370903770828407960">"વધુ વિકલ્પો માટે ટૅપ કરો."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB ડીબગિંગ કનેક્ટ થયું."</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"USB ડીબગિંગ અક્ષમ કરવા માટે ટૅપ કરો."</string>
+ <!-- no translation found for adb_active_notification_message (8470296818270110396) -->
+ <skip />
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"બગ રિપોર્ટ લઈ રહ્યાં છે…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"બગ રિપોર્ટ શેર કરીએ?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"બગ રિપોર્ટ શેર કરી રહ્યાં છે…"</string>
@@ -1689,4 +1693,7 @@
<string name="app_category_news" msgid="7496506240743986873">"સમાચાર અને સામાયિકો"</string>
<string name="app_category_maps" msgid="5878491404538024367">"નકશા અને નેવિગેશન"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"ઉત્પાદકતા"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"ઉપકરણ સ્ટૉરેજ"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 6300703..f2c3d43 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"प्रदर्शन का ज़ूम स्तर और स्थिति निर्धारण नियंत्रित करें."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"हावभाव निष्पादित करें"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"इस सेवा के द्वारा टैप किया जा सकता है, स्वाइप किया जा सकता है, पिंच किया जा सकता है और अन्य हावभाव निष्पादित किए जा सकते हैं."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"फ़िंगरप्रिंट हावभाव"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"डिवाइस फ़िंगरप्रिंट सेंसर पर किए गए हावभाव कैप्चर किए जा सकते हैं."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"स्थिति बार अक्षम या बदलें"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"ऐप्स को स्थिति बार अक्षम करने या सिस्टम आइकन को जोड़ने या निकालने देता है."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"स्थिति बार होने दें"</string>
@@ -951,7 +953,7 @@
<string name="editTextMenuTitle" msgid="4909135564941815494">"लेख क्रियाएं"</string>
<string name="email" msgid="4560673117055050403">"ईमेल करें"</string>
<string name="dial" msgid="2275093056198652749">"डायल करें"</string>
- <string name="map" msgid="5441053548030107189">"नक्शा"</string>
+ <string name="map" msgid="5441053548030107189">"मानचित्र"</string>
<string name="low_internal_storage_view_title" msgid="5576272496365684834">"मेमोरी स्थान समाप्त हो रहा है"</string>
<string name="low_internal_storage_view_text" msgid="6640505817617414371">"हो सकता है कुछ सिस्टम फ़ंक्शन कार्य न करें"</string>
<string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"सिस्टम के लिए पर्याप्त मेमोरी नहीं है. सुनिश्चित करें कि आपके पास 250MB का खाली स्थान है और फिर से प्रारंभ करें."</string>
@@ -1146,6 +1148,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"अधिक विकल्पों के लिए टैप करें."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB डीबग कनेक्ट किया गया"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"USB डीबग करना अक्षम करने के लिए टैप करें."</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"USB डीबग करना अक्षम करने के लिए चुनें."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"बग रिपोर्ट प्राप्त की जा रही है…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"बग रिपोर्ट साझा करें?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"बग रिपोर्ट साझा की जा रही है…"</string>
@@ -1689,4 +1692,7 @@
<string name="app_category_news" msgid="7496506240743986873">"समाचार और पत्रिकाएं"</string>
<string name="app_category_maps" msgid="5878491404538024367">"मानचित्र और मार्गदर्शक"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"उत्पादकता"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"डिवाइस में जगह"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index ee3ab30..11864c6 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -281,6 +281,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Kontrolira razinu zumiranja i položaj zaslona."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Izvođenje pokreta"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Može dodirnuti, prijeći prstom, spojiti prste i izvoditi druge pokrete."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Pokreti za otisak prsta"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Može snimati pokrete izvršene na senzoru otiska prsta na uređaju."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"onemogućavanje ili izmjena trake statusa"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Aplikaciji omogućuje onemogućavanje trake statusa ili dodavanje i uklanjanje sistemskih ikona."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"biti traka statusa"</string>
@@ -1166,6 +1168,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"Dodirnite za više opcija."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Priključen je alat za otklanjanje pogrešaka USB-om"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"Dodirnite da biste onemogućili otklanjanje pogrešaka putem USB-a."</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Odaberite da biste onemogućili rješavanje programske pogreške na USB-u."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Izrada izvješća o programskoj pogrešci…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Želite li podijeliti izvješće o programskoj pogrešci?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Dijeljenje izvješća o programskoj pogrešci…"</string>
@@ -1720,4 +1723,7 @@
<string name="app_category_news" msgid="7496506240743986873">"Vijesti i časopisi"</string>
<string name="app_category_maps" msgid="5878491404538024367">"Karte i navigacija"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"Produktivnost"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Pohrana na uređaju"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 943dbc0..4c6d440 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"A kijelző nagyítási/kicsinyítési szintjének és pozíciójának vezérlése"</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Kézmozdulatok végrehajtása"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Koppintás, ujjak gyors csúsztatása és összehúzása, illetve egyéb kézmozdulatok végrehajtása."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Kézmozdulatok az ujjlenyomat-érzékelőn"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Érzékeli az ujjlenyomat-érzékelőn végzett kézmozdulatokat."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"állapotsor kikapcsolása vagy módosítása"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Lehetővé teszi az alkalmazás számára az állapotsor kikapcsolását, illetve rendszerikonok hozzáadását és eltávolítását."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"az állapotsor szerepének átvétele"</string>
@@ -1146,6 +1148,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"Koppintson a további beállítások megjelenítéséhez."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB hibakereső csatlakoztatva"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"Koppintson az USB fejlesztő mód kikapcsolásához."</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Válassza ezt az USB hibakeresés kikapcsolásához."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Hibajelentés készítése…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Megosztja a hibajelentést?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Hibajelentés megosztása…"</string>
@@ -1689,4 +1692,7 @@
<string name="app_category_news" msgid="7496506240743986873">"Hírlapok és folyóiratok"</string>
<string name="app_category_maps" msgid="5878491404538024367">"Térképek és navigáció"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"Irodai alkalmazások"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Eszköztárhely"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index 7c579d1..276a326 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Ցուցասարքի մասշտաբավորման և դիրքավորման կառավարում:"</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Կատարել ժեստեր"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Կարող է հպել, թերթել, պտղունցել և կատարել այլ ժեստեր:"</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Մատնահետքերի սկաների ժեստեր"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Կարող է նկարահանել մատնահետքերի սկաների վրա կատարվող ժեստերը"</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"անջատել կամ փոփոխել կարգավիճակի գոտին"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Թույլ է տալիս հավելվածին անջատել կարգավիճակի գոտին կամ ավելացնել ու հեռացնել համակարգի պատկերակները:"</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"լինել կարգավիճակի գոտի"</string>
@@ -1146,6 +1148,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"Հպեք՝ լրացուցիչ ընտրանքների համար:"</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB վրիպազերծումը միացված է"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"Հպեք՝ USB վրիպազերծումն անջատելու համար:"</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Ընտրել` USB կարգաբերումը կասեցնելու համար:"</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Վրիպակի զեկույցի ստեղծում…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Տրամադրե՞լ վրիպակի զեկույցը:"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Վրիպակի զեկույցի տրամադրում…"</string>
@@ -1689,4 +1692,7 @@
<string name="app_category_news" msgid="7496506240743986873">"Նորություններ և ամսագրեր"</string>
<string name="app_category_maps" msgid="5878491404538024367">"Քարտեզներ և նավարկում"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"Աշխատանք"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Սարքի հիշողություն"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index b9771d6..839fc04 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Mengontrol tingkat zoom dan pemosisian layar."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Melakukan isyarat"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Dapat mengetuk, menggesek, mencubit, dan melakukan isyarat lainnya."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Gestur sidik jari"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Dapat merekam gestur yang dilakukan di sensor sidik jari perangkat."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"nonaktifkan atau ubah bilah status"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Mengizinkan apl menonaktifkan bilah status atau menambah dan menghapus ikon sistem."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"jadikan bilah status"</string>
@@ -1146,6 +1148,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"Ketuk untuk opsi lainnya."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Debugging USB terhubung"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"Ketuk untuk menonaktifkan debug USB."</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Pilih untuk menonaktifkan debugging USB."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Mengambil laporan bug…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Bagikan laporan bug?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Membagikan laporan bug..."</string>
@@ -1689,4 +1692,7 @@
<string name="app_category_news" msgid="7496506240743986873">"Berita & Majalah"</string>
<string name="app_category_maps" msgid="5878491404538024367">"Peta & Navigasi"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"Produktivitas"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Penyimpanan perangkat"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index 775c50e..1e2beb0 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Stjórnaðu aðdrætti og afstöðu skjásins."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Nota bendingar"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Getur ýtt, strokið, fært fingur saman og gert ýmsar aðrar bendingar."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Fingrafarabendingar"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Getur fangað bendingar sem eru gerðar á fingrafaraskynjara tækisins."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"slökkva á eða breyta stöðustiku"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Leyfir forriti að slökkva á stöðustikunni eða bæta við og fjarlægja kerfistákn."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"vera stöðustikan"</string>
@@ -1146,6 +1148,8 @@
<string name="usb_notification_message" msgid="3370903770828407960">"Ýttu til að sjá fleiri valkosti."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB-villuleit tengd"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"Ýttu til að slökkva á USB-villuleit."</string>
+ <!-- no translation found for adb_active_notification_message (8470296818270110396) -->
+ <skip />
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Tekur við villutilkynningu…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Deila villutilkynningu?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Deilir villutilkynningu..."</string>
@@ -1689,4 +1693,7 @@
<string name="app_category_news" msgid="7496506240743986873">"Fréttir og tímarit"</string>
<string name="app_category_maps" msgid="5878491404538024367">"Kort og leiðsögn"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"Aðstoð"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Geymslurými tækis"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index cb4769c..0b7820e 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Controlla il livello di zoom e la posizione del display."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Esegui gesti"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Consente di toccare, far scorrere, pizzicare ed eseguire altri gesti."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Gesti con sensore di impronte digitali"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"È in grado di rilevare i gesti compiuti con il sensore di impronte digitali dei dispositivi."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"disattivare o modificare la barra di stato"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Consente all\'applicazione di disattivare la barra di stato o di aggiungere e rimuovere icone di sistema."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"ruolo di barra di stato"</string>
@@ -1146,6 +1148,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"Tocca per altre opzioni."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Debug USB collegato"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"Tocca per disattivare il debug USB."</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Seleziona per disattivare il debug USB."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Recupero della segnalazione di bug…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Condividere la segnalazione di bug?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Condivisione della segnalazione di bug…"</string>
@@ -1689,4 +1692,7 @@
<string name="app_category_news" msgid="7496506240743986873">"Notizie e riviste"</string>
<string name="app_category_maps" msgid="5878491404538024367">"Maps e Navigatore"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"Produttività"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Memoria dispositivo"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index d33cd08..4361ff2 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -284,6 +284,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"קבע את המרחק מהתצוגה ואת מיקום התצוגה."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"ביצוע תנועות"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"יכול להקיש, להחליק, לעשות תנועת צביטה ולבצע תנועות אחרות."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"תנועות"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"אפשרות לזהות תנועות בזמן נגיעה בחיישן טביעות האצבע של המכשיר"</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"השבת או שנה את שורת המצב"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"מאפשר לאפליקציה להשבית את שורת המצב או להוסיף ולהסיר סמלי מערכת."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"להיות שורת הסטטוס"</string>
@@ -1186,6 +1188,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"הקש לקבלת אפשרויות נוספות."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"ניפוי באגים של USB מחובר"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"הקש כדי להשבית ניפוי באגים של USB."</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"בחר להשבית ניפוי באגים ב-USB."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"עיבוד דוח על באג..."</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"האם לשתף דוח על באג?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"שיתוף דוח על באג…"</string>
@@ -1751,4 +1754,7 @@
<string name="app_category_news" msgid="7496506240743986873">"חדשות וכתבי עת"</string>
<string name="app_category_maps" msgid="5878491404538024367">"מפות וניווט"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"פרודוקטיביות"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"שטח האחסון במכשיר"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 3992e6e..f3a22ce 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"画面のズームレベルと位置を制御します。"</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"操作の実行"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"タップ、スワイプ、ピンチ、その他の操作を行えます。"</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"指紋認証センサーでの操作"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"端末の指紋認証センサーで行われた操作をキャプチャできます。"</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"ステータスバーの無効化や変更"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"ステータスバーの無効化、システムアイコンの追加や削除をアプリに許可します。"</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"ステータスバーへの表示"</string>
@@ -1146,6 +1148,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"タップしてその他のオプションを表示します。"</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USBデバッグが接続されました"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"タップして USB デバッグを無効にします。"</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"USBデバッグを無効にする場合に選択します。"</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"バグレポートを取得しています…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"バグレポートを共有しますか?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"バグレポートの共有中…"</string>
@@ -1689,4 +1692,7 @@
<string name="app_category_news" msgid="7496506240743986873">"ニュース&雑誌"</string>
<string name="app_category_maps" msgid="5878491404538024367">"地図&ナビ"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"仕事効率化"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"端末のストレージ"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index 1fb7d13..9d3b288 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"ეკრანის მასშტაბირების დონისა და პოზიციის მართვა."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"ჟესტების შესრულება"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"შეუძლია შეხება, გადაფურცვლა, მასშტაბირება და სხვა ჟესტების შესრულება."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"თითის ანაბეჭდის ჟესტები"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"შეუძლია აღბეჭდოს მოწყობილობის თითის ანაბეჭდის სენსორზე განხორციელებული ჟესტები."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"სტატუსის ზოლის გათიშვა ან ცვლილება"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"აპს შეეძლება სტატუსების ზოლის გათიშვა და სისტემის ხატულების დამატება/წაშლა."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"სტატუსის ზოლის ჩანაცვლება"</string>
@@ -1146,6 +1148,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"შეეხეთ დამატებითი ვარიანტების სანახავად."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB გამართვა შეერთებულია"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"შეეხეთ USB-გამართვის გასათიშად."</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"მონიშნეთ რათა შეწყვიტოთ USB-ის გამართვა"</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"მიმდინარეობს ხარვეზის შესახებ ანგარიშის შექმნა…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"გსურთ ხარვეზის შესახებ ანგარიშის გაზიარება?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"მიმდინარეობს ხარვეზის შესახებ ანგარიშის გაზიარება…"</string>
@@ -1689,4 +1692,7 @@
<string name="app_category_news" msgid="7496506240743986873">"ახალი ამბები და ჟურნალები"</string>
<string name="app_category_maps" msgid="5878491404538024367">"რუკები და ნავიგაცია"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"პროდუქტიულობა"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"მოწყობილობის მეხსიერება"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index 87958c7..b168b6f 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Дисплейдің масштабтау деңгейін және орналастыруды басқару."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Қимылдарды орындау"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Түртуге, сырғытуға, қысуға және басқа қимылдарды орындауға болады."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Саусақ ізі датчигіндегі қимылдар"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Құрылғының саусақ ізі датчигінде орындалған қимылдарды сақтайды"</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"күйін көрсету тақтасын өшіру немесе өзгерту"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Қолданбаға күй жолағын өшіруге немесе жүйелік белгішелерді қосуға және жоюға рұқсат береді."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"күй жолағы болу"</string>
@@ -1146,6 +1148,8 @@
<string name="usb_notification_message" msgid="3370903770828407960">"Қосымша опциялар үшін түртіңіз."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB жөндеу қосылған"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"USB түзетуін өшіру үшін түртіңіз."</string>
+ <!-- no translation found for adb_active_notification_message (8470296818270110396) -->
+ <skip />
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Қате туралы есеп алынуда…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Қате туралы есепті бөлісу керек пе?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Қате туралы есеп бөлісілуде…"</string>
@@ -1689,4 +1693,7 @@
<string name="app_category_news" msgid="7496506240743986873">"Газеттер және журналдар"</string>
<string name="app_category_maps" msgid="5878491404538024367">"Карта және навигация"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"Өнімділік"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Құрылғы жады"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index f92eff5..0a57834 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"គ្រប់គ្រងការកំណត់ទីតាំង និងកម្រិតពង្រីករបស់អេក្រង់"</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"ធ្វើកាយវិការ"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"អាចប៉ះ អូស ច្បិច និងធ្វើកាយវិការផ្សេងទៀត"</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"ចលនាស្នាមម្រាមដៃ"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"អាចថតចលនាដែលមានសកម្មភាពនៅលើឧបករណ៍ចាប់ស្នាមម្រាមដៃរបស់ឧបករណ៍។"</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"បិទ ឬកែរបារស្ថានភាព"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"ឲ្យកម្មវិធីបិទរបារស្ថានភាព ឬបន្ថែម និងលុបរូបតំណាងប្រព័ន្ធ។"</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"ធ្វើជារបារស្ថានភាព"</string>
@@ -1148,6 +1150,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"ប៉ះសម្រាប់ជម្រើសជាច្រើនទៀត"</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"បានភ្ជាប់ការកែកំហុសយូអេសប៊ី"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"ប៉ះដើម្បីបិទដំណើរការកែកំហុសយូអេសប៊ី"</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"ជ្រើស ដើម្បីបិទការកែកំហុសយូអេសប៊ី។"</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"កំពុងទទួលយករបាយការណ៍កំហុស…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"ចែករំលែករបាយការណ៍កំហុសឬ?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"កំពុងចែករំលែករបាយកំហុស…"</string>
@@ -1691,4 +1694,7 @@
<string name="app_category_news" msgid="7496506240743986873">"ព័ត៌មាន និងទស្សនាវដ្ដី"</string>
<string name="app_category_maps" msgid="5878491404538024367">"ផែនទី និងការរុករក"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"ផលិតភាព"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"ទំហំផ្ទុកឧបករណ៍"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index 5c53b1c..07400f5 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"ಪ್ರದರ್ಶನದ ಝೂಮ್ ಮಟ್ಟ ಮತ್ತು ಸ್ಥಾನ ನಿರ್ಧಾರವನ್ನು ನಿಯಂತ್ರಿಸಿ."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"ಗೆಸ್ಚರ್ಗಳನ್ನು ಮಾಡಿ"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"ಟ್ಯಾಪ್ ಮಾಡಬಹುದು, ಸ್ವೈಪ್ ಮಾಡಬಹುದು, ಪಿಂಚ್ ಮಾಡಬಹುದು ಮತ್ತು ಇತರ ಗೆಸ್ಚರ್ಗಳನ್ನು ಮಾಡಬಹುದು."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಸೂಚಕಗಳು"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"ಸಾಧನದ ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಸೆನ್ಸರ್ನಲ್ಲಿ ನಡೆಸಿದ ಸೂಚಕಗಳನ್ನು ಕ್ಯಾಪ್ಚರ್ ಮಾಡಿ."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"ಸ್ಥಿತಿ ಪಟ್ಟಿಯನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ ಇಲ್ಲವೇ ಮಾರ್ಪಡಿಸಿ"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"ಸ್ಥಿತಿ ಪಟ್ಟಿಯನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲು ಅಥವಾ ಸೇರಿಸಲು ಮತ್ತು ಸಿಸ್ಟಂ ಐಕಾನ್ಗಳನ್ನು ತೆಗೆದುಹಾಕಲು ಅಪ್ಲಿಕೇಶನ್ಗೆ ಅವಕಾಶ ನೀಡುತ್ತದೆ."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"ಸ್ಥಿತಿ ಪಟ್ಟಿಯಾಗಿರಲು"</string>
@@ -1146,6 +1148,8 @@
<string name="usb_notification_message" msgid="3370903770828407960">"ಹೆಚ್ಚಿನ ಆಯ್ಕೆಗಳಿಗೆ ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB ಡೀಬಗಿಂಗ್ ಸಂಪರ್ಕ"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"USB ಡೀಬಗ್ ಮಾಡುವಿಕೆಯನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
+ <!-- no translation found for adb_active_notification_message (8470296818270110396) -->
+ <skip />
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"ದೋಷದ ವರದಿಯನ್ನು ತೆಗೆದುಕೊಳ್ಳಲಾಗುತ್ತಿದೆ…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"ಬಗ್ ವರದಿಯನ್ನು ಹಂಚುವುದೇ?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"ಬಗ್ ವರದಿಯನ್ನು ಹಂಚಿಕೊಳ್ಳಲಾಗುತ್ತಿದೆ…"</string>
@@ -1689,4 +1693,7 @@
<string name="app_category_news" msgid="7496506240743986873">"ಸುದ್ದಿ ಮತ್ತು ನಿಯತಕಾಲಿಕೆಗಳು"</string>
<string name="app_category_maps" msgid="5878491404538024367">"ನಕ್ಷೆಗಳು ಮತ್ತು ನ್ಯಾವಿಗೇಶನ್"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"ಉತ್ಪಾದಕತೆ"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"ಸಾಧನ ಸಂಗ್ರಹಣೆ"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index ca70e45..b74094e 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"디스플레이의 확대/축소 수준 및 위치를 제어합니다."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"동작 실행"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"탭, 스와이프, 확대/축소 및 기타 동작을 실행할 수 있습니다."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"지문 동작"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"기기 지문 센서에서 동작을 캡처합니다."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"상태 표시줄 사용 중지 또는 수정"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"앱이 상태 표시줄을 사용중지하거나 시스템 아이콘을 추가 및 제거할 수 있도록 허용합니다."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"상태 표시줄에 위치"</string>
@@ -1146,6 +1148,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"옵션을 더 보려면 탭하세요."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB 디버깅 연결됨"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"USB 디버깅을 사용하지 않으려면 탭하세요."</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"USB 디버깅을 사용하지 않으려면 선택합니다."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"버그 보고서 가져오는 중..."</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"버그 보고서를 공유하시겠습니까?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"버그 신고서 공유 중..."</string>
@@ -1689,4 +1692,7 @@
<string name="app_category_news" msgid="7496506240743986873">"뉴스/잡지"</string>
<string name="app_category_maps" msgid="5878491404538024367">"지도/내비게이션"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"생산성"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"기기 저장용량"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index 94b84f2..7b1d126 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Экрандагы сүрөттүн өлчөмүн өзгөртүү жана жайгаштыруу."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Жаңсоолорду аткаруу"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Таптап, серпип, чымчып жана башка жаңсоолорду аткара алат."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Манжа изинин жаңсоолору"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Түзмөктөрдөгү манжа изинин сенсорунда жасалган жаңсоолорду жаздырып алат."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"абал тилкесин өчүрүү же өзгөртүү"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Колдонмого абал тилкесин өчүрүү же тутум сүрөтчөлөрүн кошуу же алып салуу мүмкүнчүлүгүн берет."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"абал тилкесинин милдетин аткаруу"</string>
@@ -1146,6 +1148,8 @@
<string name="usb_notification_message" msgid="3370903770828407960">"Кошумча параметрлерди ачуу үчүн таптап коюңуз."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB аркылуу мүчүлүштүктөрдү оңдоо туташтырылган"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"USB арклуу мүчүлштктрдү жоюну өчр үчн тийп коюңуз."</string>
+ <!-- no translation found for adb_active_notification_message (8470296818270110396) -->
+ <skip />
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Мүчүлүштүк тууралуу кабар алынууда…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Мүчүлүштүк тууралуу баяндама бөлүшүлсүнбү?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Мүчүлүштүк тууралуу баяндама бөлүшүлүүдө…"</string>
@@ -1689,4 +1693,7 @@
<string name="app_category_news" msgid="7496506240743986873">"Жаңылыктар жана журналдар"</string>
<string name="app_category_maps" msgid="5878491404538024367">"Карталар жана чабыттоо"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"Өндүрүш категориясы"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Түзмөктүн сактагычы"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index 816eea2..5d7b4c3 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"ຄວບຄຸມລະດັບການຊູມ ແລະການວາງຕຳແໜ່ງຂອງຈໍສະແດງຜົນ."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"ດຳເນີນທ່າທາງຕ່າງໆ"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"ສາມາດແຕະ, ປັດນີ້ວມື, ຢິບນິ້ວມື ແລະ ດຳເນີນທ່າທາງອື່ນ."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"ທ່າທາງລາຍນິ້ວມື"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"ສາມາດບັນທຶກທ່າທາງທີ່ເກີດຂຶ້ນໃນອຸປະກອນເຊັນເຊີລາຍນິ້ວມືໄດ້."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"ປິດການນນຳໃຊ້ ຫຼື ແກ້ໄຂແຖບສະຖານະ"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"ອະນຸຍາດໃຫ້ແອັບຯປິດການເຮັດວຽກຂອງແຖບສະຖານະ ຫຼືເພີ່ມ ແລະລຶບໄອຄອນລະບົບອອກໄດ້."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"ເປັນແຖບສະຖານະ"</string>
@@ -1146,6 +1148,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"ແຕະເພື່ອເບິ່ງຕົວເລືອກເພີ່ມເຕີມ."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"ເຊື່ອມຕໍ່ການດີບັ໊ກຜ່ານ USB ແລ້ວ"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"ແຕະເພື່ອປິດການດີບັກຜ່ານ USB."</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"ເລືອກເພື່ອປິດການດີບັ໊ກຜ່ານ USB."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"ກຳລັງຂໍລາຍງານຂໍ້ຜິດພາດ…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"ແບ່ງປັນລາຍງານບັນຫາບໍ?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"ກຳລັງແບ່ງປັນລາຍງານບັນຫາ…"</string>
@@ -1202,8 +1205,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"ອະນຸຍາດໃຫ້ແອັບພລິເຄຊັນອ່ານເຊດຊັນການຕິດຕັ້ງໄດ້. ນີ້ຈະອະນຸຍາດໃຫ້ມັນເບິ່ງເຫັນລາຍລະອຽດກ່ຽວກັບການຕິດຕັ້ງແພັກເກດທີ່ເຮັດວຽກຢູ່ໄດ້."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"ຂໍຕິດຕັ້ງແພັກເກດ"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"ອະນຸຍາດໃຫ້ແອັບພລິເຄຊັນຂອງການຕິດຕັ້ງແພັກເກດ."</string>
- <string name="permlab_requestDeletePackages" msgid="1703686454657781242">"request delete packages"</string>
- <string name="permdesc_requestDeletePackages" msgid="3406172963097595270">"ອະນຸຍາດໃຫ້ແອັບພລິເຄຊັນຂອງການຕິດຕັ້ງແພັກເກດ."</string>
+ <string name="permlab_requestDeletePackages" msgid="1703686454657781242">"ຮ້ອງຂໍການລຶບແພັກເກດ"</string>
+ <string name="permdesc_requestDeletePackages" msgid="3406172963097595270">"ອະນຸຍາດໃຫ້ແອັບພລິເຄຊັນຮ້ອງຂໍການລຶບແພັກເກດ."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"ຖາມເພື່ອໃຫ້ເພີກເສີຍການປັບແຕ່ງແບັດເຕີຣີ"</string>
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"ອະນຸຍາດໃຫ້ແອັບຖາມສິດອະນຸຍາດເພື່ອເພີກເສີຍຕໍ່ການປັບແຕ່ງແບັດເຕີຣີສຳລັບແອັບນັ້ນ."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"ແຕະສອງເທື່ອເພື່ອຄວບຄຸມການຊູມ"</string>
@@ -1689,4 +1692,7 @@
<string name="app_category_news" msgid="7496506240743986873">"News & Magazines"</string>
<string name="app_category_maps" msgid="5878491404538024367">"Maps & Navigation"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"ຜະລິດຕະພາບ"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"ບ່ອນຈັດເກັບຂໍ້ມູນອຸປະກອນ"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 837134c..89ac3f2 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -284,6 +284,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Valdykite ekrano mastelio keitimo lygį ir pozicijos nustatymą."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Veiksmai gestais"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Galima paliesti, perbraukti, suimti ir atlikti kitus veiksmus gestais."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Kontrolinio kodo gestai"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Gali užfiksuoti gestus, atliktus naudojant įrenginio kontrolinio kodo jutiklį."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"išjungti ar keisti būsenos juostą"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Leidžiama programai neleisti būsenos juostos arba pridėti ir pašalinti sistemos piktogramas."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"būti būsenos juosta"</string>
@@ -1186,6 +1188,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"Palieskite, kad būtų rodoma daugiau parinkčių."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB derinimas prijungtas"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"Palieskite, kad išjungtumėte USB derinimą."</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Pasirinkite, kas išjungtumėte USB derinimą."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Pateikiamas pranešimas apie riktą…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Bendrinti pranešimą apie riktą?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Bendrinamas pranešimas apie riktą..."</string>
@@ -1751,4 +1754,7 @@
<string name="app_category_news" msgid="7496506240743986873">"Naujienos ir žurnalai"</string>
<string name="app_category_maps" msgid="5878491404538024367">"Žemėlapiai ir navigacija"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"Produktyvumas"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Įrenginio saugykla"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 7510e77..5163334 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -281,6 +281,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Kontrolējiet displeja tālummaiņas līmeni un pozicionēšanu."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Žestu izpilde"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Atbalsta pieskaršanos, vilkšanu, savilkšanu un citus žestus."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Pirksta nospieduma žesti"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Var uztvert žestus ierīces pirksta nospieduma sensorā."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"atspējot vai pārveidot statusa joslu"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Ļauj lietotnei atspējot statusa joslu vai pievienot un noņemt sistēmas ikonas."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"Būt par statusa joslu"</string>
@@ -1166,6 +1168,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"Pieskarieties, lai skatītu citas iespējas."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB atkļūdošana ir pievienota."</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"Pieskarieties, lai atspējotu USB atkļūdošanu."</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Atlasiet, lai atspējotu USB atkļūdošanu."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Notiek kļūdas pārskata izveide…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Vai kopīgot kļūdas pārskatu?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Notiek kļūdas pārskata kopīgošana…"</string>
@@ -1720,4 +1723,7 @@
<string name="app_category_news" msgid="7496506240743986873">"Ziņas un žurnāli"</string>
<string name="app_category_maps" msgid="5878491404538024367">"Kartes un navigācija"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"Produktivitāte"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Ierīces krātuve"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index 0e3862f..66d5387 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Контролирајте го нивото на зумирање и позиционирање на екранот."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Користете движења"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Може да допрете, повлечете, штипнете и да користите други движења."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Движења за отпечатоци"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Може да сними движења што се направени на сензорот за отпечатоци на уредите."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"оневозможи или измени статусна лента"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Дозволува апликацијата да ја оневозможи статусната лента или да додава или отстранува системски икони."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"да стане статусна лента"</string>
@@ -1146,6 +1148,8 @@
<string name="usb_notification_message" msgid="3370903770828407960">"Допрете за повеќе опции."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Поврзано е отстранување грешки преку УСБ"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"Допрете за да се оневозможи отстранувањето грешки преку USB."</string>
+ <!-- no translation found for adb_active_notification_message (8470296818270110396) -->
+ <skip />
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Се зема извештајот за грешки…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Да се сподели извештајот за грешки?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Се споделува извештај за грешки…"</string>
@@ -1691,4 +1695,7 @@
<string name="app_category_news" msgid="7496506240743986873">"Вести и списанија"</string>
<string name="app_category_maps" msgid="5878491404538024367">"Карти и навигација"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"Продуктивност"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Простор на уредот"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index da97cf5..bb5455d 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"ഡിസ്പ്ലേയുടെ സൂം നിലയും പൊസിഷനിംഗും നിയന്ത്രിക്കുക."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"ജെസ്റ്ററുകൾ നിർവഹിക്കുക"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"ടാപ്പുചെയ്യാനോ സ്വൈപ്പുചെയ്യാനോ പിഞ്ചുചെയ്യാനോ മറ്റ് ജെസ്റ്ററുകൾ നിർവഹിക്കാനോ കഴിയും."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"ഫിംഗർപ്രിന്റ് ജെസ്റ്ററുകൾ"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"ഉപകരണത്തിന്റെ ഫിംഗർപ്രിന്റ് സെൻസറിൽ ചെയ്ത ജെസ്റ്ററുകൾ ക്യാപ്ചർ ചെയ്യാനാകും."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"സ്റ്റാറ്റസ് ബാർ പ്രവർത്തനരഹിതമാക്കുക അല്ലെങ്കിൽ പരിഷ്ക്കരിക്കുക"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"നില ബാർ പ്രവർത്തരഹിതമാക്കുന്നതിന് അല്ലെങ്കിൽ സിസ്റ്റം ഐക്കണുകൾ ചേർക്കുന്നതിനും നീക്കംചെയ്യുന്നതിനും അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"സ്റ്റാറ്റസ് ബാർ ആയിരിക്കുക"</string>
@@ -1146,6 +1148,8 @@
<string name="usb_notification_message" msgid="3370903770828407960">"കൂടുതൽ ഓപ്ഷനുകൾക്ക് ടാപ്പുചെയ്യുക."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB ഡീബഗ്ഗിംഗ് കണക്റ്റുചെയ്തു"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"USB ഡീബഗ്ഗിംഗ് പ്രവർത്തനരഹിതമാക്കാൻ ടാപ്പുചെയ്യുക."</string>
+ <!-- no translation found for adb_active_notification_message (8470296818270110396) -->
+ <skip />
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"ബഗ് റിപ്പോർട്ട് എടുക്കുന്നു…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"ബഗ് റിപ്പോർട്ട് പങ്കിടണോ?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"ബഗ് റിപ്പോർട്ട് പങ്കിടുന്നു…"</string>
@@ -1689,4 +1693,7 @@
<string name="app_category_news" msgid="7496506240743986873">"വാർത്തകളും മാസികകളും"</string>
<string name="app_category_maps" msgid="5878491404538024367">"മാപ്സും നാവിഗേഷനും"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"ഉല്പ്പാദനക്ഷമത"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"ഉപകരണ സ്റ്റോറേജ്"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 2af81c4..0f7d43a 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Дэлгэцийн томруулах түвшин болон байршлыг хянах."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Зангах"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Товших, шудрах, жижигрүүлэх болон бусад зангааг хийх боломжтой."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Хурууны хээний зангаа"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Төхөөрөмжийн хурууны хээ мэдрэгчид зангасан зангааг танина."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"статус самбарыг идэвхгүй болгох болон өөрчлөх"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Апп нь статус самбарыг идэвхгүй болгох эсвэл систем дүрсийг нэмэх, хасах боломжтой."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"статусын хэсэг болох"</string>
@@ -1146,6 +1148,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"Бусад сонголтыг харахын тулд товшино уу."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB дебаг холбогдсон"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"USB-н алдаа засварлахыг идэвхгүй болгохын тулд товшино уу."</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"USB дебаг хийхийг идэвхгүй болгох бол сонгоно уу."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Алдааны тайланг авч байна..."</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Алдааны тайланг хуваалцах уу?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Алдааны тайланг хуваалцаж байна..."</string>
@@ -1687,4 +1690,7 @@
<string name="app_category_news" msgid="7496506240743986873">"Мэдээ & сэтгүүл"</string>
<string name="app_category_maps" msgid="5878491404538024367">"Газрын зураг & зүг чиг"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"Бүтээмж"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Төхөөрөмжийн сан"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index 1be89c2..69cf831 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"प्रदर्शनाचा झूम स्तर आणि स्थिती निर्धारण नियंत्रित करा."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"जेश्चर करा"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"टॅप, स्वाइप, पिंच आणि इतर जेश्चर करू शकते."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"फिंगरप्रिंट जेश्चर"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"डिव्हाइसच्या फिंगरप्रिंट सेंसरवर केलेले जेश्चर कॅप्चर करू शकते."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"स्टेटस बार अक्षम करा किंवा सुधारित करा"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"स्टेटस बार अक्षम करण्यासाठी किंवा सिस्टीम चिन्हे जोडण्यासाठी आणि काढण्यासाठी अॅप ला अनुमती देते."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"स्टेटस बार होऊ द्या"</string>
@@ -1146,6 +1148,8 @@
<string name="usb_notification_message" msgid="3370903770828407960">"अधिक पर्यायांसाठी टॅप करा."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB डीबग करणे कनेक्ट केले"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"USB डीबग करणे अक्षम करण्यासाठी टॅप करा."</string>
+ <!-- no translation found for adb_active_notification_message (8470296818270110396) -->
+ <skip />
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"दोष अहवाल घेत आहे..."</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"बग अहवाल सामायिक करायचा?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"दोष अहवाल सामायिक करीत आहे..."</string>
@@ -1689,4 +1693,7 @@
<string name="app_category_news" msgid="7496506240743986873">"बातम्या आणि मासिके"</string>
<string name="app_category_maps" msgid="5878491404538024367">"नकाशे आणि नेव्हिगेशन"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"उत्पादनक्षमता"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"डिव्हाइस संचय"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index ad1f4cb..ad053b9 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Kawal tahap zum dan kedudukan paparan."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Lakukan gerak isyarat"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Boleh ketik, leret, cubit dan laksanakan gerak isyarat lain."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Gerak isyarat cap jari"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Boleh menangkap gerak isyarat yang dilakukan pada penderia cap jari peranti."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"lumpuhkan atau ubah suai bar status"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Membenarkan apl melumpuhkan bar status atau menambah dan mengalih keluar ikon sistem."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"jadi bar status"</string>
@@ -1146,6 +1148,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"Ketik untuk mendapatkan lagi pilihan."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Penyahpepijatan USB disambungkan"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"Ketik untuk melumpuhkan penyahpepijatan USB."</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Pilih untuk melumpuhkan penyahpepijatan USB."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Mengambil laporan pepijat…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Kongsi laporan pepijat?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Berkongsi laporan pepijat…"</string>
@@ -1689,4 +1692,7 @@
<string name="app_category_news" msgid="7496506240743986873">"Berita & Majalah"</string>
<string name="app_category_maps" msgid="5878491404538024367">"Peta & Navigasi"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"Produktiviti"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Storan peranti"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index 129eefd..4454c2b5 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"မျက်နှာပြင် ဇူးမ်အရွယ်နှင့် နေရာချထားခြင်းကို ထိန်းချုပ်ပါ။"</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"လက်ဟန်များ အသုံးပြုပါ"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"တို့ခြင်း၊ ပွတ်ဆွဲခြင်း၊ နှင့် အခြား လက်ဟန်များကို အသုံးပြုနိုင်ပါသည်။"</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"လက်ဗွေရာများ"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"ကိရိယာ၏ လက်ဗွေအာရုံခံကိရိယာတွင် နှိပ်ထားသည်များကို မှတ်သားထားနိုင်သည်။"</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"အခြေအနေပြဘားအား အလုပ်မလုပ်ခိုင်းရန်သို့မဟုတ် မွမ်းမံရန်"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"အက်ပ်အား အခြေအနေပြ ဘားကို ပိတ်ခွင့် သို့မဟတ် စနစ် အိုင်ကွန်များကို ထည့်ခြင်း ဖယ်ရှားခြင်း ပြုလုပ်ခွင့် ပြုသည်။"</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"အခြေအနေပြ ဘားဖြစ်ပါစေ"</string>
@@ -1146,6 +1148,8 @@
<string name="usb_notification_message" msgid="3370903770828407960">"နောက်ထပ်ရွေးချယ်စရာများအတွက် တို့ပါ။"</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB အမှားစစ်ခြင်းအား ချိတ်ဆက်ထားသည်"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"USB ဆက်သွယ်ရေးစနစ်ကို ပိတ်ရန် တို့ပါ။"</string>
+ <!-- no translation found for adb_active_notification_message (8470296818270110396) -->
+ <skip />
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"ချွတ်ယွင်းချက် အစီရင်ခံစာပြုစုနေသည်..."</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"ချွတ်ယွင်းချက် အစီရင်ခံစာကို မျှဝေမလား။"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"ချွတ်ယွင်းမှုအစီရင်ခံစာ မျှဝေနေသည်…"</string>
@@ -1689,4 +1693,7 @@
<string name="app_category_news" msgid="7496506240743986873">"သတင်းနှင့် မဂ္ဂဇင်းများ"</string>
<string name="app_category_maps" msgid="5878491404538024367">"မြေပုံနှင့် ခရီးလမ်းညွှန်ချက်"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"ထုတ်လုပ်နိုင်မှု"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"စက်ပစ္စည်း သိုလှောင်ခန်း"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 9ef1bb3..d23441f 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Kontrollér zoomenivået og plasseringen for skjermen."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Gjøre bevegelser"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Kan trykke, sveipe, klype og gjøre andre bevegelser."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Bevegelser på fingeravtrykkssensor"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Kan fange inn bevegelser som utføres på enhetens fingeravtrykkssensor."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"deaktivere eller endre statusfeltet"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Lar appen deaktivere statusfeltet eller legge til og fjerne systemikoner."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"vise appen i statusfeltet"</string>
@@ -1146,6 +1148,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"Trykk for å få flere alternativ."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB-feilsøking tilkoblet"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"Trykk for å slå av feilsøking via USB."</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Velg for å deaktivere USB-debugging."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Kjører feilrapport …"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Vil du dele feilrapporten?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Deler feilrapporten …"</string>
@@ -1689,4 +1692,7 @@
<string name="app_category_news" msgid="7496506240743986873">"Nyheter og tidsskrifter"</string>
<string name="app_category_maps" msgid="5878491404538024367">"Kart og navigering"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"Produktivitet"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Lagring på enheten"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index 6ebbc93..d513ff3 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"प्रदर्शनको जुम स्तर र स्थिति नियन्त्रण गर्नुहोस्।"</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"इसाराहरू सम्बन्धी कार्य गर्नुहोस्"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"ट्याप, स्वाइप गर्न, थिच्न र अन्य इसाराहरू सम्बन्धी कार्य गर्न सक्छ"</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"फिंगरप्रिन्टका इसाराहरू"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"यन्त्रहरूको फिंगरप्रिन्ट सेन्सरमा गरिएका इसाराहरू कैद गर्न सक्छ।"</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"स्थिति पट्टिलाई अक्षम वा संशोधित गर्नुहोस्"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"स्थिति पट्टि असक्षम पार्न वा प्रणाली आइकनहरू थप्न र हटाउन अनुप्रयोगलाई अनुमति दिन्छ।"</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"वस्तुस्थिति पट्टी हुन दिनुहोस्"</string>
@@ -1152,6 +1154,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"थप विकल्पहरूका लागि ट्याप गर्नुहोस्।"</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB डिबग गर्ने जडित छ"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"USB डिबगिङलाई असक्षम गर्न ट्याप गर्नुहोस्।"</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"USB डिबगिङ असक्षम पार्न चयन गर्नुहोस्।"</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"बग रिपोर्ट लिँदै..."</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"बग रिपोर्टलाई साझेदारी गर्ने हो?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"बग रिपोर्टलाई साझेदारी गर्दै ..."</string>
@@ -1695,4 +1698,7 @@
<string name="app_category_news" msgid="7496506240743986873">"समाचार तथा पत्रिकाहरू"</string>
<string name="app_category_maps" msgid="5878491404538024367">"नक्सा तथा नेभिगेसन"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"उत्पादकत्व"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"यन्त्रको भण्डारण"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 8ece49e..f3e0274 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Bedien het zoomniveau en de positionering van het scherm."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Gebaren uitvoeren"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Kan tikken, vegen, samenknijpen en andere gebaren uitvoeren."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Vingerafdrukgebaren"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Kan gebaren registreren die op de vingerafdruksensor van het apparaat worden getekend."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"statusbalk uitschakelen of wijzigen"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Hiermee kan de app de statusbalk uitschakelen of systeempictogrammen toevoegen en verwijderen."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"de statusbalk zijn"</string>
@@ -1146,6 +1148,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"Tik voor meer opties."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB-foutopsporing verbonden"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"Tik om USB-foutopsporing uit te schakelen."</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Selecteer deze optie om USB-foutopsporing uit te schakelen."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Bugrapport genereren…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Bugrapport delen?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Bugrapport delen…"</string>
@@ -1689,4 +1692,7 @@
<string name="app_category_news" msgid="7496506240743986873">"Nieuws en tijdschriften"</string>
<string name="app_category_maps" msgid="5878491404538024367">"Maps en navigatie"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"Productiviteit"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Apparaatopslag"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index 8438fb9..788efb8 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"ਡਿਸਪਲੇ ਦੇ ਜ਼ੂਮ ਪੱਧਰ ਅਤੇ ਸਥਿਤੀ ਨੂੰ ਨਿਯੰਤ੍ਰਿਤ ਕਰੋ।"</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"ਸੰਕੇਤ ਕਰਦੀ ਹੈ"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"ਟੈਪ ਕਰ ਸਕਦੀ ਹੈ, ਸਵਾਈਪ ਕਰ ਸਕਦੀ ਹੈ, ਪਿੰਚ ਕਰ ਸਕਦੀ ਹੈ, ਅਤੇ ਹੋਰ ਸੰਕੇਤ ਕਰ ਸਕਦੀ ਹੈ।"</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਸੰਕੇਤ"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"ਡੀਵਾਈਸਾਂ ਦੇ ਫਿੰਗਰਪ੍ਰਿੰਟ ਸੈਂਸਰ \'ਤੇ ਕੀਤੇ ਗਏ ਸੰਕੇਤਾਂ ਨੂੰ ਕੈਪਚਰ ਕਰ ਸਕਦੀ ਹੈ।"</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"ਸਥਿਤੀ ਬਾਰ ਅਸਮਰੱਥ ਬਣਾਓ ਜਾਂ ਸੰਸ਼ੋਧਿਤ ਕਰੋ"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"ਐਪ ਨੂੰ ਸਥਿਤੀ ਬਾਰ ਨੂੰ ਅਸਮਰੱਥ ਬਣਾਉਣ ਜਾਂ ਸਿਸਟਮ ਆਈਕਨਾਂ ਨੂੰ ਜੋੜਨ ਅਤੇ ਹਟਾਉਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"ਸਥਿਤੀ ਪੱਟੀ ਬਣਨ ਦਿਓ"</string>
@@ -1146,6 +1148,8 @@
<string name="usb_notification_message" msgid="3370903770828407960">"ਹੋਰ ਵਿਕਲਪਾਂ ਲਈ ਟੈਪ ਕਰੋ।"</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB ਡੀਬਗਿੰਗ ਕਨੈਕਟ ਕੀਤੀ"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"USB ਡੀਬੱਗਿੰਗ ਨੂੰ ਅਯੋਗ ਬਣਾਉਣ ਲਈ ਟੈਪ ਕਰੋ।"</string>
+ <!-- no translation found for adb_active_notification_message (8470296818270110396) -->
+ <skip />
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"ਬੱਗ ਰਿਪਰੋਟ ਪ੍ਰਾਪਤ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ..."</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"ਕੀ ਬੱਗ ਰਿਪੋਰਟ ਸਾਂਝੀ ਕਰਨੀ ਹੈ?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"ਬੱਗ ਰਿਪੋਰਟ ਸਾਂਝੀ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ…"</string>
@@ -1689,4 +1693,7 @@
<string name="app_category_news" msgid="7496506240743986873">"ਖਬਰਾਂ ਅਤੇ ਰਸਾਲੇ"</string>
<string name="app_category_maps" msgid="5878491404538024367">"ਨਕਸ਼ੇ ਅਤੇ ਆਵਾਗੌਣ"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"ਉਤਪਾਦਕਤਾ"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"ਡੀਵਾਈਸ ਸਟੋਰੇਜ"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 125f3f2..3814f80 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -284,6 +284,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Regulowanie poziomu i obszaru powiększenia ekranu."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Obsługa gestów"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Obsługuje kliknięcia, przesunięcia, ściągnięcia palców i inne gesty."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Gesty związane z odciskiem palca"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Może przechwytywać gesty wykonywane na czytniku linii papilarnych w urządzeniu."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"wyłączanie lub zmienianie paska stanu"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Pozwala aplikacji na wyłączanie paska stanu oraz dodawanie i usuwanie ikon systemowych."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"działanie jako pasek stanu"</string>
@@ -1186,6 +1188,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"Kliknij, by wyświetlić więcej opcji."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Podłączono moduł debugowania USB"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"Kliknij, by wyłączyć debugowanie USB."</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Wybierz, aby wyłączyć debugowanie USB."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Zgłaszam błąd…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Udostępnić raport o błędzie?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Udostępniam raport o błędzie…"</string>
@@ -1751,4 +1754,7 @@
<string name="app_category_news" msgid="7496506240743986873">"Wiadomości i czasopisma"</string>
<string name="app_category_maps" msgid="5878491404538024367">"Mapy i nawigacja"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"Produktywność"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Pamięć urządzenia"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index c6d217a..a7a763f 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Controlar o posicionamento e nível de zoom da tela."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Fazer gestos"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Toque, deslize, faça gestos de pinça e faça outros gestos."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Gestos de impressão digital"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Pode captar gestos realizados no sensor de impressão digital do dispositivo."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"desativar ou modificar a barra de status"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Permite que o app desative a barra de status ou adicione e remova ícones do sistema."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"ser a barra de status"</string>
@@ -1146,6 +1148,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"Toque para ver mais opções."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Depuração USB conectada"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"Toque para desativar a depuração do USB."</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Selecione para desativar a depuração USB."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Gerando relatório do bug..."</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Compartilhar relatório do bug?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Compartilhando relatório do bug…"</string>
@@ -1689,4 +1692,7 @@
<string name="app_category_news" msgid="7496506240743986873">"Notícias e revistas"</string>
<string name="app_category_maps" msgid="5878491404538024367">"Mapas e navegação"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"Produtividade"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Armazenamento do dispositivo"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index eabc2f4..b87fe9e 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Controlar o nível de zoom e o posicionamento do ecrã."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Realizar gestos"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"É possível tocar, deslizar rapidamente, juntar os dedos e realizar outros gestos"</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Gestos de impressão digital"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Pode capturar gestos realizados no sensor de impressões digitais do dispositivo."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"desativar ou modificar barra de estado"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Permite à aplicação desativar a barra de estado ou adicionar e remover ícones do sistema."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"ser apresentada na barra de estado"</string>
@@ -1146,6 +1148,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"Toque para obter mais opções."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Depuração USB ligada"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"Toque para desativar a depuração USB."</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Seleccione para desativar depuração USB."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"A criar relatório de erro…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Pretende partilhar o relatório de erro?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"A partilhar relatório de erro…"</string>
@@ -1689,4 +1692,7 @@
<string name="app_category_news" msgid="7496506240743986873">"Notícias e revistas"</string>
<string name="app_category_maps" msgid="5878491404538024367">"Mapas e navegação"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"Produtividade"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Armazenamento do dispositivo"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index c6d217a..a7a763f 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Controlar o posicionamento e nível de zoom da tela."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Fazer gestos"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Toque, deslize, faça gestos de pinça e faça outros gestos."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Gestos de impressão digital"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Pode captar gestos realizados no sensor de impressão digital do dispositivo."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"desativar ou modificar a barra de status"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Permite que o app desative a barra de status ou adicione e remova ícones do sistema."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"ser a barra de status"</string>
@@ -1146,6 +1148,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"Toque para ver mais opções."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Depuração USB conectada"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"Toque para desativar a depuração do USB."</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Selecione para desativar a depuração USB."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Gerando relatório do bug..."</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Compartilhar relatório do bug?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Compartilhando relatório do bug…"</string>
@@ -1689,4 +1692,7 @@
<string name="app_category_news" msgid="7496506240743986873">"Notícias e revistas"</string>
<string name="app_category_maps" msgid="5878491404538024367">"Mapas e navegação"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"Produtividade"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Armazenamento do dispositivo"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 5e7df4b..b407ae0 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -281,6 +281,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Controlați nivelul de zoom și poziționarea afișajului."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Folosiți gesturi"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Se poate atinge, glisa, ciupi și se pot folosi alte gesturi."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Gesturi ce implică amprente"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Poate reda gesturile făcute pe senzorul de amprentă al dispozitivelor."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"dezactivare sau modificare bare de stare"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Permite aplicației să dezactiveze bara de stare sau să adauge și să elimine pictograme de sistem."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"să fie bara de stare"</string>
@@ -1166,6 +1168,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"Atingeți pentru mai multe opțiuni."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Depanarea USB este conectată"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"Atingeți ca să dezactivați remedierea erorilor prin USB."</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Selectați pentru a dezactiva depanarea USB."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Se creează un raport de eroare…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Trimiteți raportul de eroare?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Se trimite raportul de eroare…"</string>
@@ -1720,4 +1723,7 @@
<string name="app_category_news" msgid="7496506240743986873">"Știri și reviste"</string>
<string name="app_category_maps" msgid="5878491404538024367">"Hărți și navigare"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"Productivitate"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Stocare pe dispozitiv"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 5aabe4d..2e2bd0b 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -284,6 +284,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Управлять позиционированием и размером изображения на экране."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Жесты"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Может выполнять жесты нажатия, пролистывания, масштабирования и т. д."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Жесты для отпечатков пальцев"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Сохраняет жесты, выполненные на сканере отпечатков пальцев."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"Отключение/изменение строки состояния"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Приложение сможет отключать строку состояния, а также добавлять и удалять системные значки."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"Замена строки состояния"</string>
@@ -1186,6 +1188,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"Нажмите, чтобы показать дополнительные параметры."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Отладка по USB разрешена"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"Нажмите, чтобы отключить отладку по USB."</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Нажмите, чтобы отключить отладку USB."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Подготовка отчета об ошибке"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Разрешить доступ к информации об ошибке?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Отправка отчета об ошибке"</string>
@@ -1751,4 +1754,7 @@
<string name="app_category_news" msgid="7496506240743986873">"Новости и журналы"</string>
<string name="app_category_maps" msgid="5878491404538024367">"Карты и навигация"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"Работа"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Хранилище устройства"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index d776aaa..7440888 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"සංදර්ශනයේ විශාලන මට්ටම සහ පිහිටීම පාලනය කරන්න."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"අභින සිදු කරන්න"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"තට්ටු කිරීමට, ස්වයිප් කිරීමට, පින්ච් කිරීමට, සහ වෙනත් අභින සිදු කිරීමට හැකිය."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"ඇඟිලි සලකුණු ඉංගිත"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"උපාංග ඇඟිලි සලකුණු සංවේදකය මත සිදු කරන ඉංගිත ග්රහණය කළ හැකිය."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"තත්ව තීරුව අබල කරන්න හෝ වෙනස් කරන්න"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"තත්ව තීරුව අක්රිය කිරීමට හෝ පද්ධති නිරූපක එකතු හෝ ඉවත් කිරීමට යෙදුමට අවසර දේ."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"තත්ත්ව තීරුව බවට පත්වීම"</string>
@@ -1148,6 +1150,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"තවත් විකල්ප සඳහා තට්ටු කරන්න."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB නිදොස්කරණය සම්බන්ධිතයි"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"USB නිදොස්කරණය අබල කිරීමට තට්ටු කරන්න."</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"USB නිදොස්කරණය අබල කිරීමට තෝරන්න."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"දෝෂ වාර්තාවක් ගනිමින්…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"දෝෂ වාර්තාව බෙදා ගන්නද?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"දෝෂ වාර්තාවක් බෙදා ගනිමින්..."</string>
@@ -1691,4 +1694,7 @@
<string name="app_category_news" msgid="7496506240743986873">"පුවත් සහ සඟරා"</string>
<string name="app_category_maps" msgid="5878491404538024367">"සිතියම් සහ සංචලනය"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"ඵලදායිතාව"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"උපාංග ගබඩාව"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index c7b094a..47716da 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -284,6 +284,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Ovládajte úroveň priblíženia/oddialenia obrazovky a umiestnenie"</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Gestá"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Je možné použiť klepnutie, prejdenie, stiahnutie prstami a ďalšie gestá."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Gestá odtlačkov prstov"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Dokáže zaznamenať gestá vykonané na senzore odtlačkov prstov."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"zakázanie alebo zmeny stavového riadka"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Umožňuje aplikácii vypnúť stavový riadok alebo pridať a odstrániť systémové ikony."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"vydávanie sa za stavový riadok"</string>
@@ -1186,6 +1188,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"Klepnutím zobrazíte ďalšie možnosti."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Ladenie cez USB pripojené"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"Klepnutím zakážete ladenie cez USB."</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Výberom zakážete ladenie USB."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Preberá sa hlásenie chyby…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Chcete zdieľať hlásenie chyby?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Zdieľa sa hlásenie chyby…"</string>
@@ -1751,4 +1754,7 @@
<string name="app_category_news" msgid="7496506240743986873">"Noviny a časopisy"</string>
<string name="app_category_maps" msgid="5878491404538024367">"Mapy a navigácia"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"Produktivita"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Úložisko zariadenia"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index ab8264c..13102b5 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -284,6 +284,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Nadziranje stopnje povečave in položaja prikaza."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Izvajanje potez"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Mogoče je izvajanje dotikov, vlečenja, primikanja in razmikanja prstov ter drugih potez."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Poteze po tipalu prstnih odtisov"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Prepoznava poteze, narejene po tipalu prstnih odtisov naprave."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"onemogočanje ali spreminjanje vrstice stanja"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Aplikacijam omogoča onemogočenje vrstice stanja ali dodajanje in odstranjevanje ikon sistema."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"postane vrstica stanja"</string>
@@ -1186,6 +1188,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"Dotaknite se za več možnosti."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Iskanje napak prek USB je povezano"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"Dotaknite se za izklop odpravljanja napak prek USB."</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Izberite, če želite onemogočiti iskanje in odpravljanje napak prek vrat USB."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Zajemanje poročila o napakah …"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Želite poslati poročilo o napakah?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Pošiljanje poročila o napakah …"</string>
@@ -1751,4 +1754,7 @@
<string name="app_category_news" msgid="7496506240743986873">"Novice in revije"</string>
<string name="app_category_maps" msgid="5878491404538024367">"Zemljevidi in navigacija"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"Storilnost"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Shramba naprave"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index fc9384c..fd76f7d 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Kontrollo nivelin dhe pozicionimin e zmadhimit të ekranit."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Kryen gjeste"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Mund të trokasë, rrëshqasë, bashkojë gishtat dhe kryejë gjeste të tjera."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Gjestet e gjurmës së gishtit"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Mund të kapë gjestet e kryera në sensorin e gjurmës së gishtit të pajisjeve."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"çaktivizo ose modifiko shiritin e statusit"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Lejon aplikacionin të çaktivizojë shiritin e statusit dhe të heqë ikonat e sistemit."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"të bëhet shiriti i statusit"</string>
@@ -1146,6 +1148,8 @@
<string name="usb_notification_message" msgid="3370903770828407960">"Trokit për më shumë opsione."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Korrigjuesi i USB-së i lidhur"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"Trokit për të çaktivizuar korrigjimin e gabimeve të USB-së."</string>
+ <!-- no translation found for adb_active_notification_message (8470296818270110396) -->
+ <skip />
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Po merret raporti i defekteve në kod…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Të ndahet raporti i defektit në kod?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Po ndan raportin e defekteve në kod..."</string>
@@ -1689,4 +1693,7 @@
<string name="app_category_news" msgid="7496506240743986873">"Lajme dhe revista"</string>
<string name="app_category_maps" msgid="5878491404538024367">"Harta dhe navigim"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"Produktivitet"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Hapësira ruajtëse e pajisjes"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 93253c2..54b0fae 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -281,6 +281,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Управља нивоом зумирања приказа и одређивањем положаја."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Обављање покрета"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Може да додирује, листа, скупља приказ и обавља друге покрете."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Покрети за отисак прста"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Може да региструје покрете на сензору за отисак прста на уређају."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"онемогућавање или измена статусне траке"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Дозвољава апликацији да онемогући статусну траку или да додаје и уклања системске иконе."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"функционисање као статусна трака"</string>
@@ -1166,6 +1168,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"Додирните за још опција."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Отклањање грешака са USB-а је успостављено"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"Додирните да бисте онемогућили отклањање грешака са USB-а."</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Изаберите да бисте онемогућили отклањања грешака са USB-а."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Извештај о грешци се генерише…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Желите ли да поделите извештај о грешци?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Дели се извештај о грешци…"</string>
@@ -1720,4 +1723,7 @@
<string name="app_category_news" msgid="7496506240743986873">"Новости и часописи"</string>
<string name="app_category_maps" msgid="5878491404538024367">"Мапе и навигација"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"Продуктивност"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Меморијски простор уређаја"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 88089b9..e010b96 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Styr skärmens zoomnivå och positionering."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Göra rörelser"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Kan trycka, svepa, nypa och göra andra rörelser."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Fingeravtrycksrörelser"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Kan registrera rörelser som utförs med hjälp av enhetens fingeravtryckssensor."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"inaktivera eller ändra statusfält"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Tillåter att appen inaktiverar statusfältet eller lägger till och tar bort systemikoner."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"visas i statusfältet"</string>
@@ -1146,6 +1148,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"Tryck för fler alternativ."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB-felsökning ansluten"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"Tryck om du vill inaktivera USB-felsökning."</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Välj att inaktivera USB-felsökning."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Felrapporten överförs …"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Vill du dela felrapporten?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Felrapporten delas …"</string>
@@ -1689,4 +1692,7 @@
<string name="app_category_news" msgid="7496506240743986873">"Nyheter och tidskrifter"</string>
<string name="app_category_maps" msgid="5878491404538024367">"Kartor och navigation"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"Produktivitet"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Enhetens lagringsutrymme"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index db6f8cf..c363a2216 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -276,6 +276,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Dhibiti kiwango cha kukuza na nafasi cha onyesho."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Tekeleza ishara"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Unaweza kugonga, kutelezesha kidole, kubana na kutekeleza ishara zingine."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Ishara za alama ya kidole"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Inaweza kurekodi ishara zinazotekelezwa kwenye kitambua alama ya kidole."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"zima au rekebisha mwambaa hali"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Inaruhusu programu kulemaza upau wa hali au kuongeza na kutoa ikoni za mfumo."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"kuwa sehemu ya arifa"</string>
@@ -1144,6 +1146,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"Gonga ili upate chaguo zaidi."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Utatuaji wa USB umeunganishwa"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"Gonga ili uzime utatuaji wa USB."</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Chagua ili kulemaza utatuaji USB."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Inatayarisha ripoti ya hitilafu…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Ungependa kushiriki ripoti ya hitilafu?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Inashiriki ripoti ya hitilafu…"</string>
@@ -1687,4 +1690,7 @@
<string name="app_category_news" msgid="7496506240743986873">"Habari na Magazeti"</string>
<string name="app_category_maps" msgid="5878491404538024367">"Ramani na Maelekezo"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"Uzalishaji"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Hifadhi ya kifaa"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index e259a39..8a70c4e 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"திரையின் ஜூம் அளவையும் நிலையையும் கட்டுப்படுத்தலாம்."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"சைகைகளைச் செயல்படுத்துதல்"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"தட்டலாம், ஸ்வைப் செய்யலாம், பின்ச் செய்யலாம் மற்றும் பிற சைகைகளைச் செயல்படுத்தலாம்."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"கைரேகை சைகைகள்"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"சாதனத்தின் கைரேகை உணர்வி மேல் செய்யப்படும் சைகைகளைப் படமெடுக்க முடியும்."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"நிலைப் பட்டியை முடக்குதல் அல்லது மாற்றுதல்"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"நிலைப் பட்டியை முடக்க அல்லது முறைமையில் ஐகான்களைச் சேர்க்க மற்றும் அகற்ற பயன்பாட்டை அனுமதிக்கிறது."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"நிலைப் பட்டியில் இருக்கும்"</string>
@@ -1146,6 +1148,8 @@
<string name="usb_notification_message" msgid="3370903770828407960">"மேலும் விருப்பங்களுக்கு, தட்டவும்."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB பிழைதிருத்தம் இணைக்கப்பட்டது"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"USB பிழை திருத்தத்தை முடக்க, தட்டவும்."</string>
+ <!-- no translation found for adb_active_notification_message (8470296818270110396) -->
+ <skip />
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"பிழை அறிக்கையை எடுக்கிறது…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"பிழை அறிக்கையைப் பகிரவா?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"பிழை அறிக்கையைப் பகிர்கிறது…"</string>
@@ -1689,4 +1693,7 @@
<string name="app_category_news" msgid="7496506240743986873">"செய்திகளும் பத்திரிகைகளும்"</string>
<string name="app_category_maps" msgid="5878491404538024367">"வரைபடங்களும் வழிசெலுத்தலும்"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"உற்பத்தித்திறன்"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"சாதனச் சேமிப்பகம்"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index dc5653c..4d22092 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"డిస్ప్లే జూమ్ స్థాయి మరియు స్థానాన్ని నియంత్రిస్తుంది."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"సంజ్ఞలను చేయడం"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"నొక్కగలరు, స్వైప్ చేయగలరు, స్క్రీన్పై రెండు వేళ్లను ఉంచి ఆ వేళ్లను దగ్గరకు లేదా దూరానికి లాగగలరు మరియు ఇతర సంజ్ఞలను చేయగలరు."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"వేలిముద్ర సంజ్ఞలు"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"పరికరాల వేలిముద్ర సెన్సార్లో నిర్వహించిన సంజ్ఞలను క్యాప్చర్ చేయవచ్చు."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"స్థితి బార్ను నిలిపివేయడం లేదా సవరించడం"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"స్థితి బార్ను నిలిపివేయడానికి లేదా సిస్టమ్ చిహ్నాలను జోడించడానికి మరియు తీసివేయడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"స్థితి పట్టీగా ఉండటం"</string>
@@ -1146,6 +1148,8 @@
<string name="usb_notification_message" msgid="3370903770828407960">"మరిన్ని ఎంపికల కోసం నొక్కండి."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB డీబగ్గింగ్ కనెక్ట్ చేయబడింది"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"USB డీబగ్గింగ్ను నిలిపివేయడానికి నొక్కండి."</string>
+ <!-- no translation found for adb_active_notification_message (8470296818270110396) -->
+ <skip />
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"బగ్ నివేదికను తీస్తోంది…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"బగ్ నివేదికను భాగస్వామ్యం చేయాలా?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"బగ్ నివేదికను భాగస్వామ్యం చేస్తోంది..."</string>
@@ -1689,4 +1693,7 @@
<string name="app_category_news" msgid="7496506240743986873">"వార్తలు & వార్తాపత్రికలు"</string>
<string name="app_category_maps" msgid="5878491404538024367">"మ్యాప్స్ & నావిగేషన్"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"ఉత్పాదకత"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"పరికర నిల్వ"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index ae84073..38dfd84 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"ควบคุมระดับการซูมและการวางตำแหน่งของการแสดงผล"</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"ทำท่าทางสัมผัส"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"สามารถแตะ เลื่อน บีบ และทำท่าทางสัมผัสอื่นๆ"</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"ท่าทางสัมผัสลายนิ้วมือ"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"สามารถจับท่าทางสัมผัสที่เกิดขึ้นบนเซ็นเซอร์ลายนิ้วมือของอุปกรณ์"</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"ปิดการใช้งานหรือแก้ไขแถบสถานะ"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"อนุญาตให้แอปพลิเคชันปิดใช้งานแถบสถานะหรือเพิ่มและนำไอคอนระบบออก"</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"เป็นแถบสถานะ"</string>
@@ -1146,6 +1148,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"แตะเพื่อดูตัวเลือกเพิ่มเติม"</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"เชื่อมต่อการแก้ไขข้อบกพร่อง USB แล้ว"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"แตะเพื่อปิดใช้การแก้ไขข้อบกพร่องของ USB"</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"เลือกเพื่อปิดใช้งานการแก้ไขข้อบกพร่อง USB"</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"กำลังสร้างรายงานข้อบกพร่อง…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"แชร์รายงานข้อบกพร่องไหม"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"กำลังแชร์รายงานข้อบกพร่อง…"</string>
@@ -1689,4 +1692,7 @@
<string name="app_category_news" msgid="7496506240743986873">"ข่าวสารและนิตยสาร"</string>
<string name="app_category_maps" msgid="5878491404538024367">"แผนที่และการนำทาง"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"ประสิทธิภาพการทำงาน"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"พื้นที่เก็บข้อมูลของอุปกรณ์"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 3ca68da..06c6aa7 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Kontrolin ang antas ng pag-zoom at pagpoposisyon ng display."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Magsagawa ng mga galaw"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"May kakayahang mag-tap, mag-swipe, mag-pinch at magsagawa ng iba pang mga galaw."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Mga galaw gamit ang fingerprint"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Makukunan ang mga galaw na ginawa sa sensor para sa fingerprint ng mga device."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"i-disable o baguhin ang status bar"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Pinapayagan ang app na i-disable ang status bar o magdagdag at mag-alis ng mga icon ng system."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"maging status bar"</string>
@@ -1146,6 +1148,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"I-tap para sa higit pang mga opsyon."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Konektado ang debugging ng USB"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"I-tap upang i-disable ang pag-debug ng USB."</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Piliin upang i-disable ang debugging ng USB."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Kinukuha ang ulat ng bug…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Gusto mo bang ibahagi ang ulat ng bug?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Ibinabahagi ang ulat ng bug…"</string>
@@ -1689,4 +1692,7 @@
<string name="app_category_news" msgid="7496506240743986873">"Balita at Mga Magazine"</string>
<string name="app_category_maps" msgid="5878491404538024367">"Mga Mapa at Navigation"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"Productivity"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Storage ng device"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 70183a1..c6dd402 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Ekranın yakınlaştırma seviyesini ve konumunu kontrol edin."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Haraketleri yapma"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Hafifçe dokunabilir, hızlıca kaydırabilir, sıkıştırabilir ve diğer hareketleri yapabilirsiniz."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Parmak izi hareketleri"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Cihazların parmak izi sensörlerinde gerçekleştirilen hareketleri yakalayabilir."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"durum çubuğunu devre dışı bırak veya değiştir"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Uygulamaya, durum çubuğunu devre dışı bırakma ve sistem simgelerini ekleyip kaldırma izni verir."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"durum çubuğunda olma"</string>
@@ -1146,6 +1148,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"Diğer seçenekler için dokunun."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB hata ayıklaması bağlandı"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"USB hata ayıklama özelliğini devre dışı bırakmak için dokunun."</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"USB hata ayıklamasını devre dışı bırakmak için tıklayın."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Hata raporu alınıyor…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Hata raporu paylaşılsın mı?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Hata raporu paylaşılıyor..."</string>
@@ -1232,7 +1235,7 @@
<string name="wallpaper_binding_label" msgid="1240087844304687662">"Duvar Kağıdı"</string>
<string name="chooser_wallpaper" msgid="7873476199295190279">"Duvar kağıdını değiştir"</string>
<string name="notification_listener_binding_label" msgid="2014162835481906429">"Bildirim dinleyici"</string>
- <string name="vr_listener_binding_label" msgid="4316591939343607306">"Sanal Gerçeklik dinleyici"</string>
+ <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR dinleyici"</string>
<string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Durum sağlayıcı"</string>
<string name="notification_ranker_binding_label" msgid="774540592299064747">"Bildirim sıralama hizmeti"</string>
<string name="vpn_title" msgid="19615213552042827">"VPN etkinleştirildi"</string>
@@ -1689,4 +1692,7 @@
<string name="app_category_news" msgid="7496506240743986873">"Haberler ve Dergiler"</string>
<string name="app_category_maps" msgid="5878491404538024367">"Haritalar ve Navigasyon"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"Verimlilik"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Cihazdaki depolama alanı"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 3fd1f23..6b5070a 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -284,6 +284,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Контролювати масштаб і розташування екрана."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Виконання жестів"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Можна торкатися, проводити пальцем, стискати пальці та виконувати інші жести."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Жести на сканері відбитків пальців"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Фіксуються жести на сканері відбитків пальців."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"вимикати чи змін. рядок стану"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Дозволяє програмі вимикати рядок стану чи додавати та видаляти піктограми системи."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"відображатися як рядок стану"</string>
@@ -1186,6 +1188,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"Торкніться, щоб переглянути більше опцій."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Налагодження USB завершено"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"Торкніться, щоб вимкнути налагодження USB."</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Вибер., щоб вимкн. налагодж. USB."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Створюється повідомлення про помилку…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Надіслати звіт про помилку?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Надсилається звіт про помилку…"</string>
@@ -1751,4 +1754,7 @@
<string name="app_category_news" msgid="7496506240743986873">"Новини та журнали"</string>
<string name="app_category_maps" msgid="5878491404538024367">"Карти й навігація"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"Продуктивність"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Пам’ять пристрою"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index 86515b3..9f77dbb 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"ڈسپلے کے زوم کی سطح اور پوزیشن کو کنٹرول کریں۔"</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"اشارے انجام دیں"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"تھپتھپانا، سوائپ کرنا، چٹکی بھرنا اور دیگر اشارے انجام دے سکتی ہے"</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"فنگرپرنٹ کے اشارے"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"آلات کے فنگر پرنٹ سینسر پر کیے گئے اشاروں کو کیپچر کر سکتا ہے۔"</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"اسٹیٹس بار کو غیر فعال یا اس میں ترمیم کریں"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"ایپ کو اسٹیٹس بار غیر فعال کرنے یا سسٹم آئیکنز شامل کرنے اور ہٹانے کی اجازت دیتا ہے۔"</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"بطور اسٹیٹس بار کام لیں"</string>
@@ -1146,6 +1148,8 @@
<string name="usb_notification_message" msgid="3370903770828407960">"مزید اختیارات کیلئے تھپتھپائیں۔"</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB ڈیبگ کرنا مربوط ہو گیا"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"USB ڈیبگنگ کو غیر فعال کرنے کیلئے تھپتھپائیں۔"</string>
+ <!-- no translation found for adb_active_notification_message (8470296818270110396) -->
+ <skip />
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"بگ رپورٹ لی جا رہی ہے…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"بگ رپورٹ کا اشتراک کریں؟"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"بگ رپورٹ کا اشتراک ہو رہا ہے…"</string>
@@ -1689,4 +1693,7 @@
<string name="app_category_news" msgid="7496506240743986873">"خبریں اور میگزین"</string>
<string name="app_category_maps" msgid="5878491404538024367">"نقشے اور نیویگیشن"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"پروڈکٹیوٹی"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"آلہ کی اسٹوریج"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index 5f978c6..6f07869 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Ekranni kattalashtirish darajasi va joylashuvini boshqaradi."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Imo-ishoralar bilan boshqarish"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Bosish, surish; jipslashtirish va boshqa imo-ishoralarni amalga oshirish mumkin."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Barmoq izi ishoralari"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Barmoq izi skanerlarida kiritilgan ishoralarni taniy oladi."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"holat panelini o‘zgartirish yoki o‘chirish"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Ilova holat panelini o‘chirib qo‘yishi hamda tizim ikonkalarini qo‘shishi yoki olib tashlashi mumkin."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"holat qatorida ko‘rinishi"</string>
@@ -1146,6 +1148,8 @@
<string name="usb_notification_message" msgid="3370903770828407960">"Boshqa parametrlarini ko‘rish uchun bosing."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB orqali nosozliklarni tuzatish"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"O‘chirib qo‘yish uchun bu yerga bosing."</string>
+ <!-- no translation found for adb_active_notification_message (8470296818270110396) -->
+ <skip />
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Xatoliklar hisoboti olinmoqda…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Xatoliklar hisoboti yuborilsinmi?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Xatoliklar hisoboti yuborilmoqda…"</string>
@@ -1689,4 +1693,7 @@
<string name="app_category_news" msgid="7496506240743986873">"Yangiliklar va jurnallar"</string>
<string name="app_category_maps" msgid="5878491404538024367">"Xaritalar va navigatsiya"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"Ish va unumdorlik"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Qurilma xotirasi"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index e2c6e32..f2d9c8f 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Kiểm soát vị trí và mức thu phóng của màn hình."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Thực hiện cử chỉ"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Có thể nhấn, vuốt, chụm và thực hiện các cử chỉ khác."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Cử chỉ vân tay"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Có thể ghi lại các cử chỉ được thực hiện trên cảm biến vân tay của thiết bị."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"vô hiệu hóa hoặc sửa đổi thanh trạng thái"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Cho phép ứng dụng vô hiệu hóa thanh trạng thái hoặc thêm và xóa biểu tượng hệ thống."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"trở thành thanh trạng thái"</string>
@@ -1146,6 +1148,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"Nhấn để biết thêm tùy chọn."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Gỡ lỗi USB đã được kết nối"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"Nhấn để vô hiệu hóa gỡ lỗi USB."</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Chọn để vô hiệu hóa gỡ lỗi USB."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Đang thu thập báo cáo lỗi…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Chia sẻ báo cáo lỗi?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Đang chia sẻ báo cáo lỗi…"</string>
@@ -1689,4 +1692,7 @@
<string name="app_category_news" msgid="7496506240743986873">"Tin tức và tạp chí"</string>
<string name="app_category_maps" msgid="5878491404538024367">"Bản đồ và dẫn đường"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"Sản xuất"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Bộ nhớ của thiết bị"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 12f419b..96eba47 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"控制显示内容的缩放级别和位置。"</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"执行手势"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"可执行点按、滑动、双指张合等手势。"</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"指纹手势"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"可以捕获在设备指纹传感器上执行的手势。"</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"停用或修改状态栏"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"允许应用停用状态栏或者增删系统图标。"</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"用作状态栏"</string>
@@ -1146,6 +1148,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"点按即可查看更多选项。"</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"已连接到USB调试"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"点按即可停用 USB 调试功能。"</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"选择停用USB调试。"</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"正在生成错误报告…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"要分享错误报告吗?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"正在分享错误报告…"</string>
@@ -1689,4 +1692,7 @@
<string name="app_category_news" msgid="7496506240743986873">"新闻和杂志"</string>
<string name="app_category_maps" msgid="5878491404538024367">"地图和导航"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"办公"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"设备存储空间"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 9996617..234d45b 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"控制顯示屏的縮放程度和位置。"</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"執行手勢"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"可以輕按、快速滑動和兩指縮放,並執行其他手勢。"</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"指紋手勢"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"可擷取裝置指紋感應器上執行的手勢。"</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"停用或修改狀態列"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"允許應用程式停用狀態列,並可新增或移除系統圖示。"</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"成為狀態列"</string>
@@ -1146,6 +1148,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"輕按即可查看更多選項。"</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"已連接 USB 偵錯工具"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"輕按即可停用 USB 偵錯功能。"</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"選取即可停用 USB 偵錯。"</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"正在取得錯誤報告…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"要分享錯誤報告嗎?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"正在分享錯誤報告…"</string>
@@ -1689,4 +1692,7 @@
<string name="app_category_news" msgid="7496506240743986873">"新聞和雜誌"</string>
<string name="app_category_maps" msgid="5878491404538024367">"地圖和導航"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"生產力應用程式"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"裝置儲存空間"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 04c5a8e..0f0f176 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"控管顯示畫面的縮放等級和位置。"</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"使用手勢"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"可使用輕觸、滑動和雙指撥動等手勢。"</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"指紋手勢"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"可以擷取在裝置指紋感應器上執行的手勢。"</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"停用或變更狀態列"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"允許應用程式停用狀態列,並可新增或移除系統圖示。"</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"以狀態列顯示"</string>
@@ -1146,6 +1148,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"輕觸即可查看更多選項。"</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"已連接 USB 偵錯工具"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"輕觸即可停用 USB 偵錯。"</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"選取以停用 USB 偵錯。"</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"正在接收錯誤報告…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"要分享錯誤報告嗎?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"正在分享錯誤報告…"</string>
@@ -1689,4 +1692,7 @@
<string name="app_category_news" msgid="7496506240743986873">"新聞和雜誌"</string>
<string name="app_category_maps" msgid="5878491404538024367">"地圖和導航"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"生產應用"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"裝置儲存空間"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 095341a..938b332 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -278,6 +278,8 @@
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Lawula ileveli yokusondeza yesibonisi nendawo."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Yenza ukuthinta"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Ingathepha, iswayiphe, incinze, futhi yenze okunye ukuthintwa."</string>
+ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Ukuthinta kwezigxivizo zeminwe"</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Ingathatha ukuthinta okwenziwe kunzwa yezigxivizo zeminwe zamadivayisi."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"khubaza noma guqula ibha yomumo"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Ivumela uhlelo lokusebenza ukuthi yenze umudwa ochaza ngesimo ukuthi ungasebenzi noma ukufaka noma ukukhipha izithonjana zohlelo."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"yiba yibha yesimo"</string>
@@ -1146,6 +1148,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"Thepha ngezinketho eziningi."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Ukulungisa iphutha le-USB kuxhunyiwe"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"Thepha ukuze ukhubaze ukususa isiphazamisi se-USB."</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Khetha ukuvimbela ukulungisa iphutha le-USB."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Ithatha umbiko wesiphazamisi..."</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Yabelana ngombiko wesiphazamisi?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Yabelana ngombiko wesiphazamisi..."</string>
@@ -1689,4 +1692,7 @@
<string name="app_category_news" msgid="7496506240743986873">"Izindaba nomagazini"</string>
<string name="app_category_maps" msgid="5878491404538024367">"Amamephu nokuzula"</string>
<string name="app_category_productivity" msgid="3742083261781538852">"Ukukhiqiza"</string>
+ <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Isitoreji sedivayisi"</string>
+ <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+ <skip />
</resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index c548219..7f49f05 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -3392,6 +3392,8 @@
<flag name="flagRetrieveInteractiveWindows" value="0x00000040" />
<!-- Has flag {@link android.accessibilityservice.AccessibilityServiceInfo#FLAG_ENABLE_ACCESSIBILITY_VOLUME} -->
<flag name="flagEnableAccessibilityVolume" value="0x00000080" />
+ <!-- Has flag {@link android.accessibilityservice.AccessibilityServiceInfo#FLAG_REQUEST_ACCESSIBILITY_BUTTON} -->
+ <flag name="flagRequestAccessibilityButton" value="0x00000100" />
<!-- Has flag {@link android.accessibilityservice.AccessibilityServiceInfo#FLAG_CAPTURE_FINGERPRINT_GESTURES} -->
<flag name="flagCaptureFingerprintGestures" value="0x00000200" />
</attr>
@@ -3429,18 +3431,9 @@
<attr name="canRequestFilterKeyEvents" format="boolean" />
<!-- Attribute whether the accessibility service wants to be able to control
display magnification.
- <p>
- Required to allow setting the {@link android.accessibilityservice
- #AccessibilityServiceInfo#FLAG_CAN_CONTROL_MAGNIFICATION} flag.
- </p>
-->
<attr name="canControlMagnification" format="boolean" />
- <!-- Attribute whether the accessibility service wants to be able to perform gestures.
- <p>
- Required to allow setting the {@link android.accessibilityservice
- #AccessibilityServiceInfo#FLAG_CAN_PERFORM_GESTURES} flag.
- </p>
- -->
+ <!-- Attribute whether the accessibility service wants to be able to perform gestures. -->
<attr name="canPerformGestures" format="boolean" />
<!-- Attribute whether the accessibility service wants to be able to capture gestures from
the fingerprint sensor.
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 927988f..9824051 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -475,9 +475,6 @@
<dimen name="chooser_grid_padding">0dp</dimen>
- <item type="dimen" format="integer" name="time_picker_column_start_material">0</item>
- <item type="dimen" format="integer" name="time_picker_column_end_material">1</item>
-
<item type="dimen" name="aerr_padding_list_top">15dp</item>
<item type="dimen" name="aerr_padding_list_bottom">8dp</item>
diff --git a/core/res/res/values/dimens_material.xml b/core/res/res/values/dimens_material.xml
index ebe577c..e3fdcec 100644
--- a/core/res/res/values/dimens_material.xml
+++ b/core/res/res/values/dimens_material.xml
@@ -149,6 +149,7 @@
<dimen name="timepicker_radial_picker_dimen">296dp</dimen>
<dimen name="timepicker_radial_picker_top_margin">16dp</dimen>
<dimen name="timepicker_radial_picker_horizontal_margin">16dp</dimen>
+ <dimen name="timepicker_edit_text_size">24sp</dimen>
<!-- Used by RadialTimePicker in clock-style TimePicker. -->
<dimen name="timepicker_selector_radius">20dp</dimen>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index e00874f..19c5643 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4471,4 +4471,20 @@
<string name="device_storage_monitor_notification_channel">Device storage</string>
<!-- Channel name for UsbDeviceManager adb debugging notifications -->
<string name="adb_debugging_notification_channel_tv">USB debugging</string>
+
+ <!-- Label for the time picker hour input field. [CHAR LIMIT=20] -->
+ <string name="time_picker_hour_label">hour</string>
+ <!-- Label for the time picker minute input field. [CHAR LIMIT=20] -->
+ <string name="time_picker_minute_label">minute</string>
+ <!-- The title for the time picker dialog. [CHAR LIMIT=NONE] -->
+ <string name="time_picker_header_text">Set time</string>
+ <!-- Error shown to the user if they type in invalid hour or minute in the time picker. [CHAR LIMIT=NONE] -->
+ <string name="time_picker_input_error">Enter a valid time</string>
+ <!-- Label shown to the user in time picker to let them know that should type in time. [CHAR LIMIT=NONE] -->
+ <string name="time_picker_prompt_label">Type in time</string>
+ <!-- Accessibility string used for describing the button in time picker that changes the dialog to text input mode. [CHAR LIMIT=NONE] -->
+ <string name="time_picker_text_input_mode_description">Switch to text input mode for the time input.</string>
+ <!-- Accessibility string used for describing the button in time picker that changes the dialog to circular clock mode. [CHAR LIMIT=NONE] -->
+ <string name="time_picker_radial_mode_description">Switch to clock mode for the time input.</string>
+
</resources>
diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml
index 1e15348..8f061a3 100644
--- a/core/res/res/values/styles_material.xml
+++ b/core/res/res/values/styles_material.xml
@@ -426,6 +426,21 @@
<item name="textColor">@color/primary_text_secondary_when_activated_material_inverse</item>
</style>
+ <style name="TextAppearance.Material.TimePicker.InputHeader" parent="TextAppearance.Material">
+ <item name="textSize">@dimen/text_size_display_1_material</item>
+ <item name="textColor">@color/white</item>
+ <item name="fontFamily">sans-serif-medium</item>
+ </style>
+
+ <style name="TextAppearance.Material.TimePicker.InputField" parent="TextAppearance.Material">
+ <item name="textSize">@dimen/timepicker_edit_text_size</item>
+ </style>
+
+ <style name="TextAppearance.Material.TimePicker.PromptLabel" parent="TextAppearance.Material">
+ <item name="textSize">@dimen/timepicker_text_size_normal</item>
+ <item name="fontFamily">sans-serif-medium</item>
+ </style>
+
<style name="TextAppearance.Material.DatePicker.YearLabel" parent="TextAppearance.Material">
<item name="textColor">@color/primary_text_secondary_when_activated_material_inverse</item>
<item name="textSize">@dimen/date_picker_year_label_size</item>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index b95c20b..4143355 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -120,6 +120,7 @@
<java-symbol type="id" name="permission_list" />
<java-symbol type="id" name="pickers" />
<java-symbol type="id" name="prefs" />
+ <java-symbol type="id" name="prefs_container" />
<java-symbol type="id" name="prefs_frame" />
<java-symbol type="id" name="prev" />
<java-symbol type="id" name="progress" />
@@ -2842,4 +2843,21 @@
<!-- Accessibility fingerprint gestures -->
<java-symbol type="string" name="capability_title_canCaptureFingerprintGestures" />
<java-symbol type="string" name="capability_desc_canCaptureFingerprintGestures" />
+
+ <!-- Time picker -->
+ <java-symbol type="id" name="toggle_mode"/>
+ <java-symbol type="id" name="input_mode"/>
+ <java-symbol type="id" name="input_header"/>
+ <java-symbol type="id" name="input_separator"/>
+ <java-symbol type="id" name="input_hour"/>
+ <java-symbol type="id" name="input_minute"/>
+ <java-symbol type="id" name="am_pm_spinner"/>
+ <java-symbol type="id" name="label_hour"/>
+ <java-symbol type="id" name="label_minute"/>
+ <java-symbol type="id" name="label_error"/>
+ <java-symbol type="layout" name="time_picker_text_input_material"/>
+ <java-symbol type="drawable" name="btn_keyboard_key_material"/>
+ <java-symbol type="drawable" name="btn_event_material"/>
+ <java-symbol type="string" name="time_picker_text_input_mode_description"/>
+ <java-symbol type="string" name="time_picker_radial_mode_description"/>
</resources>
diff --git a/core/tests/coretests/src/android/net/RecommendationRequestTest.java b/core/tests/coretests/src/android/net/RecommendationRequestTest.java
index bd25500..e2e6883 100644
--- a/core/tests/coretests/src/android/net/RecommendationRequestTest.java
+++ b/core/tests/coretests/src/android/net/RecommendationRequestTest.java
@@ -96,7 +96,7 @@
RecommendationRequest parceled = passThroughParcel(request);
- assertEquals(0, parceled.getLastSelectedNetworkId());
+ assertEquals(-1, parceled.getLastSelectedNetworkId());
assertEquals(0, parceled.getLastSelectedNetworkTimestamp());
}
diff --git a/core/tests/coretests/src/android/provider/SettingsTest.java b/core/tests/coretests/src/android/provider/SettingsTest.java
index d76980a..1ff2056 100644
--- a/core/tests/coretests/src/android/provider/SettingsTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsTest.java
@@ -392,7 +392,6 @@
Settings.Secure.BACKUP_PROVISIONED,
Settings.Secure.BACKUP_TRANSPORT,
Settings.Secure.BLUETOOTH_HCI_LOG,
- Settings.Secure.BRIGHTNESS_USE_TWILIGHT, // Candidate for backup?
Settings.Secure.CARRIER_APPS_HANDLED,
Settings.Secure.COMPLETED_CATEGORY_PREFIX,
Settings.Secure.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS,
diff --git a/core/tests/coretests/src/android/view/ViewAttachTest.java b/core/tests/coretests/src/android/view/ViewAttachTest.java
index a73f5a6..44fcd13 100644
--- a/core/tests/coretests/src/android/view/ViewAttachTest.java
+++ b/core/tests/coretests/src/android/view/ViewAttachTest.java
@@ -16,9 +16,17 @@
package android.view;
+import android.content.Context;
import android.content.pm.ActivityInfo;
+import android.graphics.PixelFormat;
import android.os.SystemClock;
import android.test.ActivityInstrumentationTestCase2;
+import android.test.UiThreadTest;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+
+import com.android.frameworks.coretests.R;
public class ViewAttachTest extends
ActivityInstrumentationTestCase2<ViewAttachTestActivity> {
@@ -51,4 +59,38 @@
SystemClock.sleep(250);
}
}
+
+ /**
+ * Make sure that on any attached view, if the view is full-screen and hosted
+ * on a round device, the round scrollbars will be displayed even if the activity
+ * window is offset.
+ *
+ * @throws Throwable
+ */
+ @UiThreadTest
+ public void testRoundScrollbars() throws Throwable {
+ final ViewAttachTestActivity activity = getActivity();
+ final View rootView = activity.getWindow().getDecorView();
+ final WindowManager.LayoutParams params =
+ new WindowManager.LayoutParams(
+ rootView.getWidth(),
+ rootView.getHeight(),
+ 50, /* xPosition */
+ 0, /* yPosition */
+ WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
+ WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
+ PixelFormat.TRANSLUCENT);
+
+ rootView.setLayoutParams(params);
+
+ View contentView = activity.findViewById(R.id.view_attach_view);
+ boolean shouldDrawRoundScrollbars = contentView.shouldDrawRoundScrollbar();
+
+ if (activity.getResources().getConfiguration().isScreenRound()) {
+ assertTrue(shouldDrawRoundScrollbars);
+ } else {
+ // Never draw round scrollbars on non-round devices.
+ assertFalse(shouldDrawRoundScrollbars);
+ }
+ }
}
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index e46f166..9cdc660 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -155,6 +155,7 @@
<assign-permission name="android.permission.WAKE_LOCK" uid="cameraserver" />
<assign-permission name="android.permission.UPDATE_DEVICE_STATS" uid="cameraserver" />
<assign-permission name="android.permission.UPDATE_APP_OPS_STATS" uid="cameraserver" />
+ <assign-permission name="android.permission.GET_PROCESS_STATE_AND_OOM_SCORE" uid="cameraserver" />
<assign-permission name="android.permission.ACCESS_SURFACE_FLINGER" uid="graphics" />
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index c5961ab..039ab1f 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -132,6 +132,7 @@
<permission name="android.permission.ACCESS_IMS_CALL_SERVICE"/>
<permission name="android.permission.BIND_CARRIER_MESSAGING_SERVICE"/>
<permission name="android.permission.BIND_CARRIER_SERVICES"/>
+ <permission name="android.permission.BIND_IMS_SERVICE"/>
<permission name="android.permission.BIND_VISUAL_VOICEMAIL_SERVICE"/>
<permission name="android.permission.CALL_PRIVILEGED"/>
<permission name="android.permission.CHANGE_COMPONENT_ENABLED_STATE"/>
@@ -339,4 +340,4 @@
<permission name="android.permission.CONTROL_VPN"/>
</privapp-permissions>
-</permissions>
\ No newline at end of file
+</permissions>
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index a799fdf..692199d 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -192,7 +192,7 @@
ifneq (false,$(ANDROID_ENABLE_RENDERSCRIPT))
hwui_cflags += -DANDROID_ENABLE_RENDERSCRIPT
hwui_c_includes += \
- $(call intermediates-dir-for,STATIC_LIBRARIES,libRS,TARGET,) \
+ $(call intermediates-dir-for,STATIC_LIBRARIES,TARGET,) \
frameworks/rs/cpp \
frameworks/rs
endif
diff --git a/libs/hwui/hwui_static_deps.mk b/libs/hwui/hwui_static_deps.mk
index 37126a6..f69da48 100644
--- a/libs/hwui/hwui_static_deps.mk
+++ b/libs/hwui/hwui_static_deps.mk
@@ -29,5 +29,5 @@
libandroidfw
ifneq (false,$(ANDROID_ENABLE_RENDERSCRIPT))
- LOCAL_SHARED_LIBRARIES += libRS libRScpp
+ LOCAL_SHARED_LIBRARIES += libRScpp
endif
diff --git a/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp b/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp
index d05e7f6..2ead5c5 100644
--- a/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp
+++ b/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp
@@ -24,6 +24,7 @@
#include <SkGaussianEdgeShader.h>
#include <SkPathOps.h>
#include <SkRRectsGaussianEdgeMaskFilter.h>
+#include <SkShadowUtils.h>
namespace android {
namespace uirenderer {
@@ -115,498 +116,6 @@
}
}
-/**
- * @param canvas the destination for the shadow draws
- * @param shape the shape casting the shadow
- * @param casterZValue the Z value of the caster RRect
- * @param ambientAlpha the maximum alpha value to use when drawing the ambient shadow
- * @param draw the function used to draw 'shape'
- */
-template <typename Shape, typename F>
-static void DrawAmbientShadowGeneral(SkCanvas* canvas, const Shape& shape, float casterZValue,
- float ambientAlpha, F&& draw) {
- if (ambientAlpha <= 0) {
- return;
- }
-
- const float kHeightFactor = 1.f/128.f;
- const float kGeomFactor = 64;
-
- float umbraAlpha = 1 / (1 + SkMaxScalar(casterZValue*kHeightFactor, 0));
- float radius = casterZValue*kHeightFactor*kGeomFactor;
-
- sk_sp<SkMaskFilter> mf = SkBlurMaskFilter::Make(kNormal_SkBlurStyle,
- SkBlurMask::ConvertRadiusToSigma(radius), SkBlurMaskFilter::kNone_BlurFlag);
- SkPaint paint;
- paint.setAntiAlias(true);
- paint.setMaskFilter(std::move(mf));
- paint.setARGB(ambientAlpha*umbraAlpha, 0, 0, 0);
-
- draw(shape, paint);
-}
-
-/**
- * @param canvas the destination for the shadow draws
- * @param shape the shape casting the shadow
- * @param casterZValue the Z value of the caster RRect
- * @param lightPos the position of the light casting the shadow
- * @param lightWidth
- * @param spotAlpha the maximum alpha value to use when drawing the spot shadow
- * @param draw the function used to draw 'shape'
- */
-template <typename Shape, typename F>
-static void DrawSpotShadowGeneral(SkCanvas* canvas, const Shape& shape, float casterZValue,
- float spotAlpha, F&& draw) {
- if (spotAlpha <= 0) {
- return;
- }
-
- const Vector3 lightPos = SkiaPipeline::getLightCenter();
- float zRatio = casterZValue / (lightPos.z - casterZValue);
- // clamp
- if (zRatio < 0.0f) {
- zRatio = 0.0f;
- } else if (zRatio > 0.95f) {
- zRatio = 0.95f;
- }
-
- float blurRadius = SkiaPipeline::getLightRadius()*zRatio;
-
- SkAutoCanvasRestore acr(canvas, true);
-
- sk_sp<SkMaskFilter> mf = SkBlurMaskFilter::Make(kNormal_SkBlurStyle,
- SkBlurMask::ConvertRadiusToSigma(blurRadius), SkBlurMaskFilter::kNone_BlurFlag);
-
- SkPaint paint;
- paint.setAntiAlias(true);
- paint.setMaskFilter(std::move(mf));
- paint.setARGB(spotAlpha, 0, 0, 0);
-
- // approximate projection by translating and scaling projected offset of bounds center
- // TODO: compute the actual 2D projection
- SkScalar scale = lightPos.z / (lightPos.z - casterZValue);
- canvas->scale(scale, scale);
- SkPoint center = SkPoint::Make(shape.getBounds().centerX(), shape.getBounds().centerY());
- SkMatrix ctmInverse;
- if (!canvas->getTotalMatrix().invert(&ctmInverse)) {
- ALOGW("Matrix is degenerate. Will not render shadow!");
- return;
- }
- SkPoint lightPos2D = SkPoint::Make(lightPos.x, lightPos.y);
- ctmInverse.mapPoints(&lightPos2D, 1);
- canvas->translate(zRatio*(center.fX - lightPos2D.fX), zRatio*(center.fY - lightPos2D.fY));
-
- draw(shape, paint);
-}
-
-#define MAX_BLUR_RADIUS 16383.75f
-#define MAX_PAD 64
-
-/**
- * @param casterRect the rectangle bounds of the RRect casting the shadow
- * @param casterCornerRadius the x&y radius for all the corners of the RRect casting the shadow
- * @param ambientAlpha the maximum alpha value to use when drawing the ambient shadow
- * @param spotAlpha the maximum alpha value to use when drawing the spot shadow
- * @param casterAlpha the alpha value of the RRect casting the shadow (0.0-1.0 range)
- * @param casterZValue the Z value of the caster RRect
- * @param scaleFactor the scale needed to map from src-space to device-space
- * @param canvas the destination for the shadow draws
- */
-static void DrawRRectShadows(const SkRect& casterRect, SkScalar casterCornerRadius,
- SkScalar ambientAlpha, SkScalar spotAlpha, SkScalar casterAlpha, SkScalar casterZValue,
- SkScalar scaleFactor, SkCanvas* canvas) {
- SkASSERT(casterCornerRadius >= 0.0f);
-
- // For all of these, we need to ensure we have a rrect with radius >= 0.5f in device space
- const SkScalar minRadius = 0.5f / scaleFactor;
-
- const bool isOval = casterCornerRadius >= std::max(SkScalarHalf(casterRect.width()),
- SkScalarHalf(casterRect.height()));
- const bool isRect = casterCornerRadius <= minRadius;
-
- sk_sp<SkShader> edgeShader(SkGaussianEdgeShader::Make());
-
- if (ambientAlpha > 0.0f) {
- static const float kHeightFactor = 1.0f / 128.0f;
- static const float kGeomFactor = 64.0f;
-
- SkScalar srcSpaceAmbientRadius = casterZValue * kHeightFactor * kGeomFactor;
- // the device-space radius sent to the blur shader must fit in 14.2 fixed point
- if (srcSpaceAmbientRadius*scaleFactor > MAX_BLUR_RADIUS) {
- srcSpaceAmbientRadius = MAX_BLUR_RADIUS/scaleFactor;
- }
- const float umbraAlpha = 1.0f / (1.0f + std::max(casterZValue * kHeightFactor, 0.0f));
- const SkScalar ambientOffset = srcSpaceAmbientRadius * umbraAlpha;
-
- // For the ambient rrect, we inset the offset rect by half the srcSpaceAmbientRadius
- // to get our stroke shape.
- SkScalar ambientPathOutset = std::max(ambientOffset - srcSpaceAmbientRadius * 0.5f,
- minRadius);
-
- SkRRect ambientRRect;
- const SkRect temp = casterRect.makeOutset(ambientPathOutset, ambientPathOutset);
- if (isOval) {
- ambientRRect = SkRRect::MakeOval(temp);
- } else if (isRect) {
- ambientRRect = SkRRect::MakeRectXY(temp, ambientPathOutset, ambientPathOutset);
- } else {
- ambientRRect = SkRRect::MakeRectXY(temp, casterCornerRadius + ambientPathOutset,
- casterCornerRadius + ambientPathOutset);
- }
-
- SkPaint paint;
- paint.setAntiAlias(true);
- paint.setStyle(SkPaint::kStroke_Style);
- // we outset the stroke a little to cover up AA on the interior edge
- float pad = 0.5f;
- paint.setStrokeWidth(srcSpaceAmbientRadius + 2.0f * pad);
- // handle scale of radius and pad due to CTM
- pad *= scaleFactor;
- const SkScalar devSpaceAmbientRadius = srcSpaceAmbientRadius * scaleFactor;
- SkASSERT(devSpaceAmbientRadius <= MAX_BLUR_RADIUS);
- SkASSERT(pad < MAX_PAD);
- // convert devSpaceAmbientRadius to 14.2 fixed point and place in the R & G components
- // convert pad to 6.2 fixed point and place in the B component
- uint16_t iDevSpaceAmbientRadius = (uint16_t)(4.0f * devSpaceAmbientRadius);
- paint.setColor(SkColorSetARGB((unsigned char) ambientAlpha, iDevSpaceAmbientRadius >> 8,
- iDevSpaceAmbientRadius & 0xff, (unsigned char)(4.0f * pad)));
-
- paint.setShader(edgeShader);
- canvas->drawRRect(ambientRRect, paint);
- }
-
- if (spotAlpha > 0.0f) {
- const Vector3 lightPos = SkiaPipeline::getLightCenter();
- float zRatio = casterZValue / (lightPos.z - casterZValue);
- // clamp
- if (zRatio < 0.0f) {
- zRatio = 0.0f;
- } else if (zRatio > 0.95f) {
- zRatio = 0.95f;
- }
-
- const SkScalar lightWidth = SkiaPipeline::getLightRadius();
- SkScalar srcSpaceSpotRadius = 2.0f * lightWidth * zRatio;
- // the device-space radius sent to the blur shader must fit in 14.2 fixed point
- if (srcSpaceSpotRadius*scaleFactor > MAX_BLUR_RADIUS) {
- srcSpaceSpotRadius = MAX_BLUR_RADIUS/scaleFactor;
- }
-
- SkRRect spotRRect;
- if (isOval) {
- spotRRect = SkRRect::MakeOval(casterRect);
- } else if (isRect) {
- spotRRect = SkRRect::MakeRectXY(casterRect, minRadius, minRadius);
- } else {
- spotRRect = SkRRect::MakeRectXY(casterRect, casterCornerRadius, casterCornerRadius);
- }
-
- SkRRect spotShadowRRect;
- // Compute the scale and translation for the spot shadow.
- const SkScalar scale = lightPos.z / (lightPos.z - casterZValue);
- spotRRect.transform(SkMatrix::MakeScale(scale, scale), &spotShadowRRect);
-
- SkPoint center = SkPoint::Make(spotShadowRRect.rect().centerX(),
- spotShadowRRect.rect().centerY());
- SkMatrix ctmInverse;
- if (!canvas->getTotalMatrix().invert(&ctmInverse)) {
- ALOGW("Matrix is degenerate. Will not render spot shadow!");
- return;
- }
- SkPoint lightPos2D = SkPoint::Make(lightPos.x, lightPos.y);
- ctmInverse.mapPoints(&lightPos2D, 1);
- const SkPoint spotOffset = SkPoint::Make(zRatio*(center.fX - lightPos2D.fX),
- zRatio*(center.fY - lightPos2D.fY));
-
- SkAutoCanvasRestore acr(canvas, true);
-
- // We want to extend the stroked area in so that it meets up with the caster
- // geometry. The stroked geometry will, by definition already be inset half the
- // stroke width but we also have to account for the scaling.
- // We also add 1/2 to cover up AA on the interior edge.
- SkScalar scaleOffset = (scale - 1.0f) * SkTMax(SkTMax(SkTAbs(casterRect.fLeft),
- SkTAbs(casterRect.fRight)), SkTMax(SkTAbs(casterRect.fTop),
- SkTAbs(casterRect.fBottom)));
- SkScalar insetAmount = spotOffset.length() - (0.5f * srcSpaceSpotRadius) +
- scaleOffset + 0.5f;
-
- // Compute area
- SkScalar strokeWidth = srcSpaceSpotRadius + insetAmount;
- SkScalar strokedArea = 2.0f*strokeWidth * (spotShadowRRect.width()
- + spotShadowRRect.height());
- SkScalar filledArea = (spotShadowRRect.height() + srcSpaceSpotRadius)
- * (spotShadowRRect.width() + srcSpaceSpotRadius);
-
- SkPaint paint;
- paint.setAntiAlias(true);
-
- // If the area of the stroked geometry is larger than the fill geometry, just fill it.
- if (strokedArea > filledArea || casterAlpha < 1.0f || insetAmount < 0.0f) {
- paint.setStyle(SkPaint::kStrokeAndFill_Style);
- paint.setStrokeWidth(srcSpaceSpotRadius);
- } else {
- // Since we can't have unequal strokes, inset the shadow rect so the inner
- // and outer edges of the stroke will land where we want.
- SkRect insetRect = spotShadowRRect.rect().makeInset(insetAmount/2.0f, insetAmount/2.0f);
- SkScalar insetRad = SkTMax(spotShadowRRect.getSimpleRadii().fX - insetAmount/2.0f,
- minRadius);
- spotShadowRRect = SkRRect::MakeRectXY(insetRect, insetRad, insetRad);
- paint.setStyle(SkPaint::kStroke_Style);
- paint.setStrokeWidth(strokeWidth);
- }
-
- // handle scale of radius and pad due to CTM
- const SkScalar devSpaceSpotRadius = srcSpaceSpotRadius * scaleFactor;
- SkASSERT(devSpaceSpotRadius <= MAX_BLUR_RADIUS);
-
- const SkScalar devSpaceSpotPad = 0;
- SkASSERT(devSpaceSpotPad < MAX_PAD);
-
- // convert devSpaceSpotRadius to 14.2 fixed point and place in the R & G
- // components convert devSpaceSpotPad to 6.2 fixed point and place in the B component
- uint16_t iDevSpaceSpotRadius = (uint16_t)(4.0f * devSpaceSpotRadius);
- paint.setColor(SkColorSetARGB((unsigned char) spotAlpha, iDevSpaceSpotRadius >> 8,
- iDevSpaceSpotRadius & 0xff, (unsigned char)(4.0f * devSpaceSpotPad)));
- paint.setShader(edgeShader);
-
- canvas->translate(spotOffset.fX, spotOffset.fY);
- canvas->drawRRect(spotShadowRRect, paint);
- }
-}
-
-/**
- * @param casterRect the rectangle bounds of the RRect casting the shadow
- * @param casterCornerRadius the x&y radius for all the corners of the RRect casting the shadow
- * @param ambientAlpha the maximum alpha value to use when drawing the ambient shadow
- * @param spotAlpha the maximum alpha value to use when drawing the spot shadow
- * @param casterZValue the Z value of the caster RRect
- * @param scaleFactor the scale needed to map from src-space to device-space
- * @param clipRR the oval or rect with which the drawn roundrect must be intersected
- * @param canvas the destination for the shadow draws
- */
-static void DrawRRectShadowsWithClip(const SkRect& casterRect, SkScalar casterCornerRadius,
- SkScalar ambientAlpha, SkScalar spotAlpha, SkScalar casterZValue, SkScalar scaleFactor,
- const SkRRect& clipRR, SkCanvas* canvas) {
- SkASSERT(casterCornerRadius >= 0.0f);
-
- const bool isOval = casterCornerRadius >= std::max(SkScalarHalf(casterRect.width()),
- SkScalarHalf(casterRect.height()));
-
- if (ambientAlpha > 0.0f) {
- static const float kHeightFactor = 1.0f / 128.0f;
- static const float kGeomFactor = 64.0f;
-
- const SkScalar srcSpaceAmbientRadius = casterZValue * kHeightFactor * kGeomFactor;
- const SkScalar devSpaceAmbientRadius = srcSpaceAmbientRadius * scaleFactor;
-
- const float umbraAlpha = 1.0f / (1.0f + std::max(casterZValue * kHeightFactor, 0.0f));
- const SkScalar ambientOffset = srcSpaceAmbientRadius * umbraAlpha;
-
- const SkRect srcSpaceAmbientRect = casterRect.makeOutset(ambientOffset, ambientOffset);
- SkRect devSpaceAmbientRect;
- canvas->getTotalMatrix().mapRect(&devSpaceAmbientRect, srcSpaceAmbientRect);
-
- SkRRect devSpaceAmbientRRect;
- if (isOval) {
- devSpaceAmbientRRect = SkRRect::MakeOval(devSpaceAmbientRect);
- } else {
- const SkScalar devSpaceCornerRadius = scaleFactor * (casterCornerRadius + ambientOffset);
- devSpaceAmbientRRect = SkRRect::MakeRectXY(devSpaceAmbientRect, devSpaceCornerRadius,
- devSpaceCornerRadius);
- }
-
- const SkRect srcSpaceAmbClipRect = clipRR.rect().makeOutset(ambientOffset, ambientOffset);
- SkRect devSpaceAmbClipRect;
- canvas->getTotalMatrix().mapRect(&devSpaceAmbClipRect, srcSpaceAmbClipRect);
- SkRRect devSpaceAmbientClipRR;
- if (clipRR.isOval()) {
- devSpaceAmbientClipRR = SkRRect::MakeOval(devSpaceAmbClipRect);
- } else {
- SkASSERT(clipRR.isRect());
- devSpaceAmbientClipRR = SkRRect::MakeRect(devSpaceAmbClipRect);
- }
-
- SkRect cover = srcSpaceAmbClipRect;
- if (!cover.intersect(srcSpaceAmbientRect)) {
- return;
- }
-
- SkPaint paint;
- paint.setColor(SkColorSetARGB((unsigned char) ambientAlpha, 0, 0, 0));
- paint.setMaskFilter(SkRRectsGaussianEdgeMaskFilter::Make(devSpaceAmbientRRect,
- devSpaceAmbientClipRR, devSpaceAmbientRadius));
- canvas->drawRect(cover, paint);
- }
-
- if (spotAlpha > 0.0f) {
- const Vector3 lightPos = SkiaPipeline::getLightCenter();
- float zRatio = casterZValue / (lightPos.z - casterZValue);
- // clamp
- if (zRatio < 0.0f) {
- zRatio = 0.0f;
- } else if (zRatio > 0.95f) {
- zRatio = 0.95f;
- }
-
- const SkScalar lightWidth = SkiaPipeline::getLightRadius();
- const SkScalar srcSpaceSpotRadius = 2.0f * lightWidth * zRatio;
- const SkScalar devSpaceSpotRadius = srcSpaceSpotRadius * scaleFactor;
-
- // Compute the scale and translation for the spot shadow.
- const SkScalar scale = lightPos.z / (lightPos.z - casterZValue);
- const SkMatrix spotMatrix = SkMatrix::MakeScale(scale, scale);
-
- SkRect srcSpaceScaledRect = casterRect;
- spotMatrix.mapRect(&srcSpaceScaledRect);
- srcSpaceScaledRect.outset(SkScalarHalf(srcSpaceSpotRadius),
- SkScalarHalf(srcSpaceSpotRadius));
-
- SkRRect srcSpaceSpotRRect;
- if (isOval) {
- srcSpaceSpotRRect = SkRRect::MakeOval(srcSpaceScaledRect);
- } else {
- srcSpaceSpotRRect = SkRRect::MakeRectXY(srcSpaceScaledRect, casterCornerRadius * scale,
- casterCornerRadius * scale);
- }
-
- SkPoint center = SkPoint::Make(srcSpaceSpotRRect.rect().centerX(),
- srcSpaceSpotRRect.rect().centerY());
- SkMatrix ctmInverse;
- if (!canvas->getTotalMatrix().invert(&ctmInverse)) {
- ALOGW("Matrix is degenerate. Will not render spot shadow!");
- return;
- }
- SkPoint lightPos2D = SkPoint::Make(lightPos.x, lightPos.y);
- ctmInverse.mapPoints(&lightPos2D, 1);
- const SkPoint spotOffset = SkPoint::Make(zRatio*(center.fX - lightPos2D.fX),
- zRatio*(center.fY - lightPos2D.fY));
-
- SkAutoCanvasRestore acr(canvas, true);
- canvas->translate(spotOffset.fX, spotOffset.fY);
-
- SkRect devSpaceScaledRect;
- canvas->getTotalMatrix().mapRect(&devSpaceScaledRect, srcSpaceScaledRect);
-
- SkRRect devSpaceSpotRRect;
- if (isOval) {
- devSpaceSpotRRect = SkRRect::MakeOval(devSpaceScaledRect);
- } else {
- const SkScalar devSpaceScaledCornerRadius = casterCornerRadius * scale * scaleFactor;
- devSpaceSpotRRect = SkRRect::MakeRectXY(devSpaceScaledRect, devSpaceScaledCornerRadius,
- devSpaceScaledCornerRadius);
- }
-
- SkPaint paint;
- paint.setColor(SkColorSetARGB((unsigned char) spotAlpha, 0, 0, 0));
-
- SkRect srcSpaceScaledClipRect = clipRR.rect();
- spotMatrix.mapRect(&srcSpaceScaledClipRect);
- srcSpaceScaledClipRect.outset(SkScalarHalf(srcSpaceSpotRadius),
- SkScalarHalf(srcSpaceSpotRadius));
-
- SkRect devSpaceScaledClipRect;
- canvas->getTotalMatrix().mapRect(&devSpaceScaledClipRect, srcSpaceScaledClipRect);
- SkRRect devSpaceSpotClipRR;
- if (clipRR.isOval()) {
- devSpaceSpotClipRR = SkRRect::MakeOval(devSpaceScaledClipRect);
- } else {
- SkASSERT(clipRR.isRect());
- devSpaceSpotClipRR = SkRRect::MakeRect(devSpaceScaledClipRect);
- }
-
- paint.setMaskFilter(SkRRectsGaussianEdgeMaskFilter::Make(devSpaceSpotRRect,
- devSpaceSpotClipRR, devSpaceSpotRadius));
-
- SkRect cover = srcSpaceScaledClipRect;
- if (!cover.intersect(srcSpaceSpotRRect.rect())) {
- return;
- }
-
- canvas->drawRect(cover, paint);
- }
-}
-
-/**
- * @param casterRect the rectangle bounds of the RRect casting the shadow
- * @param casterCornerRadius the x&y radius for all the corners of the RRect casting the shadow
- * @param casterClipRect a rectangular clip that must be intersected with the
- * shadow-casting RRect prior to casting the shadow
- * @param revealClip a circular clip that must be interested with the castClipRect
- * and the shadow-casting rect prior to casting the shadow
- * @param ambientAlpha the maximum alpha value to use when drawing the ambient shadow
- * @param spotAlpha the maximum alpha value to use when drawing the spot shadow
- * @param casterAlpha the alpha value of the RRect casting the shadow (0.0-1.0 range)
- * @param casterZValue the Z value of the caster RRect
- * @param canvas the destination for the shadow draws
- *
- * We have special cases for 4 round rect shadow draws:
- * 1) a RRect clipped by a reveal animation
- * 2) a RRect clipped by a rectangle
- * 3) an unclipped RRect with non-uniform scale
- * 4) an unclipped RRect with uniform scale
- * 1,2 and 4 require that the scale is uniform.
- * 1 and 2 require that rects stay rects.
- */
-static bool DrawShadowsAsRRects(const SkRect& casterRect, SkScalar casterCornerRadius,
- const SkRect& casterClipRect, const RevealClip& revealClip, SkScalar ambientAlpha,
- SkScalar spotAlpha, SkScalar casterAlpha, SkScalar casterZValue, SkCanvas* canvas) {
- SkScalar scaleFactors[2];
- if (!canvas->getTotalMatrix().getMinMaxScales(scaleFactors)) {
- ALOGW("Matrix is degenerate. Will not render shadow!");
- return false;
- }
-
- // The casterClipRect will be empty when bounds clipping is disabled
- bool casterIsClippedByRect = !casterClipRect.isEmpty();
- bool uniformScale = scaleFactors[0] == scaleFactors[1];
-
- if (revealClip.willClip()) {
- if (casterIsClippedByRect || !uniformScale || !canvas->getTotalMatrix().rectStaysRect()) {
- return false; // Fall back to the slow path since PathOps are required
- }
-
- const float revealRadius = revealClip.getRadius();
- SkRect revealClipRect = SkRect::MakeLTRB(revealClip.getX()-revealRadius,
- revealClip.getY()-revealRadius, revealClip.getX()+revealRadius,
- revealClip.getY()+revealRadius);
- SkRRect revealClipRR = SkRRect::MakeOval(revealClipRect);
-
- DrawRRectShadowsWithClip(casterRect, casterCornerRadius, ambientAlpha, spotAlpha,
- casterZValue, scaleFactors[0], revealClipRR, canvas);
- return true;
- }
-
- if (casterIsClippedByRect) {
- if (!uniformScale || !canvas->getTotalMatrix().rectStaysRect()) {
- return false; // Fall back to the slow path since PathOps are required
- }
-
- SkRRect casterClipRR = SkRRect::MakeRect(casterClipRect);
-
- DrawRRectShadowsWithClip(casterRect, casterCornerRadius, ambientAlpha, spotAlpha,
- casterZValue, scaleFactors[0], casterClipRR, canvas);
- return true;
- }
-
- // The fast path needs uniform scale
- if (!uniformScale) {
- SkRRect casterRR = SkRRect::MakeRectXY(casterRect, casterCornerRadius, casterCornerRadius);
- DrawAmbientShadowGeneral(canvas, casterRR, casterZValue, ambientAlpha,
- [&](const SkRRect& rrect, const SkPaint& paint) {
- canvas->drawRRect(rrect, paint);
- });
- DrawSpotShadowGeneral(canvas, casterRR, casterZValue, spotAlpha,
- [&](const SkRRect& rrect, const SkPaint& paint) {
- canvas->drawRRect(rrect, paint);
- });
- return true;
- }
-
- DrawRRectShadows(casterRect, casterCornerRadius, ambientAlpha, spotAlpha, casterAlpha,
- casterZValue, scaleFactors[0], canvas);
- return true;
-}
-
// copied from FrameBuilder::deferShadow
void EndReorderBarrierDrawable::drawShadow(SkCanvas* canvas, RenderNodeDrawable* caster) {
const RenderProperties& casterProperties = caster->getNodeProperties();
@@ -626,8 +135,8 @@
return;
}
- float ambientAlpha = SkiaPipeline::getAmbientShadowAlpha()*casterAlpha;
- float spotAlpha = SkiaPipeline::getSpotShadowAlpha()*casterAlpha;
+ float ambientAlpha = (SkiaPipeline::getAmbientShadowAlpha()/255.f)*casterAlpha;
+ float spotAlpha = (SkiaPipeline::getSpotShadowAlpha()/255.f)*casterAlpha;
const float casterZValue = casterProperties.getZ();
const RevealClip& revealClip = casterProperties.getRevealClip();
@@ -659,19 +168,7 @@
hwuiMatrix.copyTo(shadowMatrix);
canvas->concat(shadowMatrix);
- const Outline& casterOutline = casterProperties.getOutline();
- Rect possibleRect;
- float radius;
- if (casterOutline.getAsRoundRect(&possibleRect, &radius)) {
- if (DrawShadowsAsRRects(possibleRect.toSkRect(), radius, casterClipRect, revealClip,
- ambientAlpha, spotAlpha, casterAlpha, casterZValue, canvas)) {
- return;
- }
- }
-
- // Hard cases and calls to general shadow code
const SkPath* casterOutlinePath = casterProperties.getOutline().getPath();
-
// holds temporary SkPath to store the result of intersections
SkPath tmpPath;
const SkPath* casterPath = casterOutlinePath;
@@ -691,16 +188,11 @@
Op(*casterPath, clipBoundsPath, kIntersect_SkPathOp, &tmpPath);
casterPath = &tmpPath;
}
-
- DrawAmbientShadowGeneral(canvas, *casterPath, casterZValue, ambientAlpha,
- [&](const SkPath& path, const SkPaint& paint) {
- canvas->drawPath(path, paint);
- });
-
- DrawSpotShadowGeneral(canvas, *casterPath, casterZValue, spotAlpha,
- [&](const SkPath& path, const SkPaint& paint) {
- canvas->drawPath(path, paint);
- });
+ const Vector3 lightPos = SkiaPipeline::getLightCenter();
+ SkPoint3 skiaLightPos = SkPoint3::Make(lightPos.x, lightPos.y, lightPos.z);
+ SkShadowUtils::DrawShadow(canvas, *casterPath, casterZValue, skiaLightPos,
+ SkiaPipeline::getLightRadius(), ambientAlpha, spotAlpha, SK_ColorBLACK,
+ casterAlpha < 1.0f ? SkShadowFlags::kTransparentOccluder_ShadowFlag : 0);
}
}; // namespace skiapipeline
diff --git a/libs/hwui/renderstate/RenderState.cpp b/libs/hwui/renderstate/RenderState.cpp
index 0d567f7..7dfc2ee 100644
--- a/libs/hwui/renderstate/RenderState.cpp
+++ b/libs/hwui/renderstate/RenderState.cpp
@@ -80,6 +80,7 @@
delete mStencil;
mStencil = nullptr;
+ destroyLayersInUpdater();
GpuMemoryTracker::onGpuContextDestroyed();
}
diff --git a/libs/hwui/renderstate/RenderState.h b/libs/hwui/renderstate/RenderState.h
index a44fa9d..f78bf7a 100644
--- a/libs/hwui/renderstate/RenderState.h
+++ b/libs/hwui/renderstate/RenderState.h
@@ -99,8 +99,6 @@
mActiveLayerUpdaters.erase(layerUpdater);
}
- void destroyLayersInUpdater();
-
// TODO: This system is a little clunky feeling, this could use some
// more thinking...
void postDecStrong(VirtualLightRefBase* object);
@@ -121,6 +119,7 @@
private:
void interruptForFunctorInvoke();
void resumeFromFunctorInvoke();
+ void destroyLayersInUpdater();
explicit RenderState(renderthread::RenderThread& thread);
~RenderState();
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 5a7de1d..a53e5e0 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -570,7 +570,6 @@
}
mRenderPipeline->onDestroyHardwareResources();
}
- mRenderThread.renderState().destroyLayersInUpdater();
}
void CanvasContext::trimMemory(RenderThread& thread, int level) {
diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp
index 454ce4d..c2c2f22 100644
--- a/libs/hwui/renderthread/VulkanManager.cpp
+++ b/libs/hwui/renderthread/VulkanManager.cpp
@@ -603,6 +603,11 @@
}
void VulkanManager::swapBuffers(VulkanSurface* surface) {
+ if (CC_UNLIKELY(Properties::waitForGpuCompletion)) {
+ ATRACE_NAME("Finishing GPU work");
+ mDeviceWaitIdle(mBackendContext->fDevice);
+ }
+
VulkanSurface::BackbufferInfo* backbuffer = surface->mBackbuffers +
surface->mCurrentBackbufferIndex;
GrVkImageInfo* imageInfo;
diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java
index 391a905..ce58a9c 100644
--- a/media/java/android/media/AudioAttributes.java
+++ b/media/java/android/media/AudioAttributes.java
@@ -913,13 +913,13 @@
}
}
/**
- * @hide
- * CANDIDATE FOR PUBLIC (or at least SYSTEM) API
* Returns the stream type matching the given attributes for volume control.
* Use this method to derive the stream type needed to configure the volume
- * control slider in an {@link Activity} with {@link Activity#setVolumeControlStream(int)}.
+ * control slider in an {@link android.app.Activity} with
+ * {@link android.app.Activity#setVolumeControlStream(int)}.
* <BR>Do not use this method to set the stream type on an audio player object
- * (e.g. {@link AudioTrack}, {@link MediaPlayer}), use <code>AudioAttributes</code> instead.
+ * (e.g. {@link AudioTrack}, {@link MediaPlayer}) as this is deprecated,
+ * use <code>AudioAttributes</code> instead.
* @param aa non-null AudioAttributes.
* @return a valid stream type for <code>Activity</code> or stream volume control that matches
* the attributes, or {@link AudioManager#USE_DEFAULT_STREAM_TYPE} if there isn't a direct
diff --git a/media/java/android/media/session/IOnMediaKeyListener.aidl b/media/java/android/media/session/IOnMediaKeyListener.aidl
index 7752357..aa98ea3 100644
--- a/media/java/android/media/session/IOnMediaKeyListener.aidl
+++ b/media/java/android/media/session/IOnMediaKeyListener.aidl
@@ -22,7 +22,7 @@
* Listener to handle media key.
* @hide
*/
-interface IOnMediaKeyListener {
+oneway interface IOnMediaKeyListener {
void onMediaKey(in KeyEvent event, in ResultReceiver result);
}
diff --git a/media/java/android/media/session/ISessionCallback.aidl b/media/java/android/media/session/ISessionCallback.aidl
index 2f6e260..a146c62 100644
--- a/media/java/android/media/session/ISessionCallback.aidl
+++ b/media/java/android/media/session/ISessionCallback.aidl
@@ -16,6 +16,7 @@
package android.media.session;
import android.content.Intent;
+import android.media.MediaDescription;
import android.media.Rating;
import android.net.Uri;
import android.os.Bundle;
@@ -49,6 +50,10 @@
void onRepeatMode(int repeatMode);
void onShuffleMode(boolean enabled);
void onCustomAction(String action, in Bundle args);
+ void onAddQueueItem(in MediaDescription description);
+ void onAddQueueItemAt(in MediaDescription description, int index);
+ void onRemoveQueueItem(in MediaDescription description);
+ void onRemoveQueueItemAt(int index);
// These callbacks are for volume handling
void onAdjustVolume(int direction);
diff --git a/media/java/android/media/session/ISessionController.aidl b/media/java/android/media/session/ISessionController.aidl
index e92758c..7b5233a 100644
--- a/media/java/android/media/session/ISessionController.aidl
+++ b/media/java/android/media/session/ISessionController.aidl
@@ -18,6 +18,7 @@
import android.app.PendingIntent;
import android.content.Intent;
import android.content.pm.ParceledListSlice;
+import android.media.MediaDescription;
import android.media.MediaMetadata;
import android.media.Rating;
import android.media.session.ISessionControllerCallback;
@@ -51,6 +52,11 @@
MediaMetadata getMetadata();
PlaybackState getPlaybackState();
ParceledListSlice getQueue();
+ void addQueueItem(in MediaDescription description);
+ void addQueueItemAt(in MediaDescription description, int index);
+ void removeQueueItem(in MediaDescription description);
+ void removeQueueItemAt(int index);
+
CharSequence getQueueTitle();
Bundle getExtras();
int getRatingType();
diff --git a/media/java/android/media/session/MediaController.java b/media/java/android/media/session/MediaController.java
index 8cbf8e1..bab2af2 100644
--- a/media/java/android/media/session/MediaController.java
+++ b/media/java/android/media/session/MediaController.java
@@ -23,6 +23,7 @@
import android.content.pm.ParceledListSlice;
import android.media.AudioAttributes;
import android.media.AudioManager;
+import android.media.MediaDescription;
import android.media.MediaMetadata;
import android.media.Rating;
import android.media.VolumeProvider;
@@ -38,6 +39,7 @@
import android.view.KeyEvent;
import java.lang.ref.WeakReference;
+import java.lang.UnsupportedOperationException;
import java.util.ArrayList;
import java.util.List;
@@ -111,8 +113,7 @@
}
/**
- * Get a {@link TransportControls} instance to send transport actions to
- * the associated session.
+ * Get a {@link TransportControls} instance to send transport actions to this session.
*
* @return A transport controls instance.
*/
@@ -151,7 +152,7 @@
try {
return mSessionBinder.getPlaybackState();
} catch (RemoteException e) {
- Log.wtf(TAG, "Error calling getPlaybackState.", e);
+ Log.wtf(TAG, "Error calling getPlaybackState", e);
return null;
}
}
@@ -165,7 +166,7 @@
try {
return mSessionBinder.getMetadata();
} catch (RemoteException e) {
- Log.wtf(TAG, "Error calling getMetadata.", e);
+ Log.wtf(TAG, "Error calling getMetadata", e);
return null;
}
}
@@ -183,12 +184,103 @@
return queue.getList();
}
} catch (RemoteException e) {
- Log.wtf(TAG, "Error calling getQueue.", e);
+ Log.wtf(TAG, "Error calling getQueue", e);
}
return null;
}
/**
+ * Add a queue item from the given {@code description} at the end of the play queue
+ * of this session. Not all sessions may support this.
+ *
+ * @param description The {@link MediaDescription} for creating the
+ * {@link MediaSession.QueueItem} to be inserted.
+ * @throws UnsupportedOperationException If this session doesn't support this.
+ * @see MediaSession#FLAG_HANDLES_QUEUE_COMMANDS
+ */
+ public void addQueueItem(MediaDescription description) {
+ try {
+ long flags = mSessionBinder.getFlags();
+ if ((flags & MediaSession.FLAG_HANDLES_QUEUE_COMMANDS) == 0) {
+ throw new UnsupportedOperationException(
+ "This session doesn't support queue management operations");
+ }
+ mSessionBinder.addQueueItem(description);
+ } catch (RemoteException e) {
+ Log.wtf(TAG, "Error calling addQueueItem", e);
+ }
+ }
+
+ /**
+ * Add a queue item from the given {@code description} at the specified position
+ * in the play queue of this session. Shifts the queue item currently at that position
+ * (if any) and any subsequent queue items to the right (adds one to their indices).
+ * Not all sessions may support this.
+ *
+ * @param description The {@link MediaDescription} for creating the
+ * {@link MediaSession.QueueItem} to be inserted.
+ * @param index The index at which the created {@link MediaSession.QueueItem} is to be inserted.
+ * @throws UnsupportedOperationException If this session doesn't support this.
+ * @see MediaSession#FLAG_HANDLES_QUEUE_COMMANDS
+ */
+ public void addQueueItem(MediaDescription description, int index) {
+ try {
+ long flags = mSessionBinder.getFlags();
+ if ((flags & MediaSession.FLAG_HANDLES_QUEUE_COMMANDS) == 0) {
+ throw new UnsupportedOperationException(
+ "This session doesn't support queue management operations");
+ }
+ mSessionBinder.addQueueItemAt(description, index);
+ } catch (RemoteException e) {
+ Log.wtf(TAG, "Error calling addQueueItemAt", e);
+ }
+ }
+
+ /**
+ * Remove the first occurrence of the specified {@link MediaSession.QueueItem}
+ * with the given {@link MediaDescription description} in the play queue of the associated
+ * session. Not all sessions may support this.
+ *
+ * @param description The {@link MediaDescription} for denoting the
+ * {@link MediaSession.QueueItem} to be removed.
+ * @throws UnsupportedOperationException If this session doesn't support this.
+ * @see MediaSession#FLAG_HANDLES_QUEUE_COMMANDS
+ */
+ public void removeQueueItem(MediaDescription description) {
+ try {
+ long flags = mSessionBinder.getFlags();
+ if ((flags & MediaSession.FLAG_HANDLES_QUEUE_COMMANDS) == 0) {
+ throw new UnsupportedOperationException(
+ "This session doesn't support queue management operations");
+ }
+ mSessionBinder.removeQueueItem(description);
+ } catch (RemoteException e) {
+ Log.wtf(TAG, "Error calling removeQueueItem", e);
+ }
+ }
+
+ /**
+ * Remove an queue item at the specified position in the play queue
+ * of this session. Not all sessions may support this.
+ *
+ * @param index The index of the element to be removed.
+ * @throws UnsupportedOperationException If this session doesn't support this.
+ * @see MediaSession#FLAG_HANDLES_QUEUE_COMMANDS
+ */
+ public void removeQueueItemAt(int index) {
+ try {
+ long flags = mSessionBinder.getFlags();
+ if ((flags & MediaSession.FLAG_HANDLES_QUEUE_COMMANDS) == 0) {
+ throw new UnsupportedOperationException(
+ "This session doesn't support queue management operations");
+ }
+ mSessionBinder.removeQueueItemAt(index);
+ } catch (RemoteException e) {
+ Log.wtf(TAG, "Error calling removeQueueItemAt", e);
+ }
+ }
+
+ /**
* Get the queue title for this session.
*/
public @Nullable CharSequence getQueueTitle() {
@@ -230,7 +322,7 @@
try {
return mSessionBinder.getRatingType();
} catch (RemoteException e) {
- Log.wtf(TAG, "Error calling getRatingType.", e);
+ Log.wtf(TAG, "Error calling getRatingType", e);
return Rating.RATING_NONE;
}
}
@@ -245,7 +337,7 @@
try {
return mSessionBinder.getRepeatMode();
} catch (RemoteException e) {
- Log.wtf(TAG, "Error calling getRepeatMode.", e);
+ Log.wtf(TAG, "Error calling getRepeatMode", e);
return PlaybackState.REPEAT_MODE_NONE;
}
}
@@ -259,7 +351,7 @@
try {
return mSessionBinder.isShuffleModeEnabled();
} catch (RemoteException e) {
- Log.wtf(TAG, "Error calling isShuffleModeEnabled.", e);
+ Log.wtf(TAG, "Error calling isShuffleModeEnabled", e);
return false;
}
}
@@ -273,7 +365,7 @@
try {
return mSessionBinder.getFlags();
} catch (RemoteException e) {
- Log.wtf(TAG, "Error calling getFlags.", e);
+ Log.wtf(TAG, "Error calling getFlags", e);
}
return 0;
}
@@ -290,7 +382,7 @@
result.maxVolume, result.currentVolume);
} catch (RemoteException e) {
- Log.wtf(TAG, "Error calling getAudioInfo.", e);
+ Log.wtf(TAG, "Error calling getAudioInfo", e);
}
return null;
}
@@ -305,7 +397,7 @@
try {
return mSessionBinder.getLaunchPendingIntent();
} catch (RemoteException e) {
- Log.wtf(TAG, "Error calling getPendingIntent.", e);
+ Log.wtf(TAG, "Error calling getPendingIntent", e);
}
return null;
}
@@ -334,7 +426,7 @@
try {
mSessionBinder.setVolumeTo(value, flags, mContext.getPackageName());
} catch (RemoteException e) {
- Log.wtf(TAG, "Error calling setVolumeTo.", e);
+ Log.wtf(TAG, "Error calling setVolumeTo", e);
}
}
@@ -355,7 +447,7 @@
try {
mSessionBinder.adjustVolume(direction, flags, mContext.getPackageName());
} catch (RemoteException e) {
- Log.wtf(TAG, "Error calling adjustVolumeBy.", e);
+ Log.wtf(TAG, "Error calling adjustVolumeBy", e);
}
}
@@ -421,7 +513,7 @@
try {
mSessionBinder.sendCommand(command, args, cb);
} catch (RemoteException e) {
- Log.d(TAG, "Dead object in sendCommand.", e);
+ Log.d(TAG, "Dead object in sendCommand", e);
}
}
@@ -435,7 +527,7 @@
try {
mPackageName = mSessionBinder.getPackageName();
} catch (RemoteException e) {
- Log.d(TAG, "Dead object in getPackageName.", e);
+ Log.d(TAG, "Dead object in getPackageName", e);
}
}
return mPackageName;
@@ -452,7 +544,7 @@
try {
mTag = mSessionBinder.getTag();
} catch (RemoteException e) {
- Log.d(TAG, "Dead object in getTag.", e);
+ Log.d(TAG, "Dead object in getTag", e);
}
}
return mTag;
@@ -652,7 +744,7 @@
try {
mSessionBinder.prepare();
} catch (RemoteException e) {
- Log.wtf(TAG, "Error calling prepare.", e);
+ Log.wtf(TAG, "Error calling prepare", e);
}
}
@@ -671,12 +763,12 @@
public void prepareFromMediaId(String mediaId, Bundle extras) {
if (TextUtils.isEmpty(mediaId)) {
throw new IllegalArgumentException(
- "You must specify a non-empty String for prepareFromMediaId.");
+ "You must specify a non-empty String for prepareFromMediaId");
}
try {
mSessionBinder.prepareFromMediaId(mediaId, extras);
} catch (RemoteException e) {
- Log.wtf(TAG, "Error calling prepare(" + mediaId + ").", e);
+ Log.wtf(TAG, "Error calling prepare(" + mediaId + ")", e);
}
}
@@ -702,7 +794,7 @@
try {
mSessionBinder.prepareFromSearch(query, extras);
} catch (RemoteException e) {
- Log.wtf(TAG, "Error calling prepare(" + query + ").", e);
+ Log.wtf(TAG, "Error calling prepare(" + query + ")", e);
}
}
@@ -721,12 +813,12 @@
public void prepareFromUri(Uri uri, Bundle extras) {
if (uri == null || Uri.EMPTY.equals(uri)) {
throw new IllegalArgumentException(
- "You must specify a non-empty Uri for prepareFromUri.");
+ "You must specify a non-empty Uri for prepareFromUri");
}
try {
mSessionBinder.prepareFromUri(uri, extras);
} catch (RemoteException e) {
- Log.wtf(TAG, "Error calling prepare(" + uri + ").", e);
+ Log.wtf(TAG, "Error calling prepare(" + uri + ")", e);
}
}
@@ -737,7 +829,7 @@
try {
mSessionBinder.play();
} catch (RemoteException e) {
- Log.wtf(TAG, "Error calling play.", e);
+ Log.wtf(TAG, "Error calling play", e);
}
}
@@ -751,12 +843,12 @@
public void playFromMediaId(String mediaId, Bundle extras) {
if (TextUtils.isEmpty(mediaId)) {
throw new IllegalArgumentException(
- "You must specify a non-empty String for playFromMediaId.");
+ "You must specify a non-empty String for playFromMediaId");
}
try {
mSessionBinder.playFromMediaId(mediaId, extras);
} catch (RemoteException e) {
- Log.wtf(TAG, "Error calling play(" + mediaId + ").", e);
+ Log.wtf(TAG, "Error calling play(" + mediaId + ")", e);
}
}
@@ -778,7 +870,7 @@
try {
mSessionBinder.playFromSearch(query, extras);
} catch (RemoteException e) {
- Log.wtf(TAG, "Error calling play(" + query + ").", e);
+ Log.wtf(TAG, "Error calling play(" + query + ")", e);
}
}
@@ -792,12 +884,12 @@
public void playFromUri(Uri uri, Bundle extras) {
if (uri == null || Uri.EMPTY.equals(uri)) {
throw new IllegalArgumentException(
- "You must specify a non-empty Uri for playFromUri.");
+ "You must specify a non-empty Uri for playFromUri");
}
try {
mSessionBinder.playFromUri(uri, extras);
} catch (RemoteException e) {
- Log.wtf(TAG, "Error calling play(" + uri + ").", e);
+ Log.wtf(TAG, "Error calling play(" + uri + ")", e);
}
}
@@ -809,7 +901,7 @@
try {
mSessionBinder.skipToQueueItem(id);
} catch (RemoteException e) {
- Log.wtf(TAG, "Error calling skipToItem(" + id + ").", e);
+ Log.wtf(TAG, "Error calling skipToItem(" + id + ")", e);
}
}
@@ -821,7 +913,7 @@
try {
mSessionBinder.pause();
} catch (RemoteException e) {
- Log.wtf(TAG, "Error calling pause.", e);
+ Log.wtf(TAG, "Error calling pause", e);
}
}
@@ -833,7 +925,7 @@
try {
mSessionBinder.stop();
} catch (RemoteException e) {
- Log.wtf(TAG, "Error calling stop.", e);
+ Log.wtf(TAG, "Error calling stop", e);
}
}
@@ -846,7 +938,7 @@
try {
mSessionBinder.seekTo(pos);
} catch (RemoteException e) {
- Log.wtf(TAG, "Error calling seekTo.", e);
+ Log.wtf(TAG, "Error calling seekTo", e);
}
}
@@ -858,7 +950,7 @@
try {
mSessionBinder.fastForward();
} catch (RemoteException e) {
- Log.wtf(TAG, "Error calling fastForward.", e);
+ Log.wtf(TAG, "Error calling fastForward", e);
}
}
@@ -869,7 +961,7 @@
try {
mSessionBinder.next();
} catch (RemoteException e) {
- Log.wtf(TAG, "Error calling next.", e);
+ Log.wtf(TAG, "Error calling next", e);
}
}
@@ -881,7 +973,7 @@
try {
mSessionBinder.rewind();
} catch (RemoteException e) {
- Log.wtf(TAG, "Error calling rewind.", e);
+ Log.wtf(TAG, "Error calling rewind", e);
}
}
@@ -892,7 +984,7 @@
try {
mSessionBinder.previous();
} catch (RemoteException e) {
- Log.wtf(TAG, "Error calling previous.", e);
+ Log.wtf(TAG, "Error calling previous", e);
}
}
@@ -907,7 +999,7 @@
try {
mSessionBinder.rate(rating);
} catch (RemoteException e) {
- Log.wtf(TAG, "Error calling rate.", e);
+ Log.wtf(TAG, "Error calling rate", e);
}
}
@@ -923,7 +1015,7 @@
try {
mSessionBinder.repeatMode(repeatMode);
} catch (RemoteException e) {
- Log.wtf(TAG, "Error calling setRepeatMode.", e);
+ Log.wtf(TAG, "Error calling setRepeatMode", e);
}
}
@@ -936,7 +1028,7 @@
try {
mSessionBinder.shuffleMode(enabled);
} catch (RemoteException e) {
- Log.wtf(TAG, "Error calling shuffleMode.", e);
+ Log.wtf(TAG, "Error calling shuffleMode", e);
}
}
@@ -950,7 +1042,7 @@
public void sendCustomAction(@NonNull PlaybackState.CustomAction customAction,
@Nullable Bundle args) {
if (customAction == null) {
- throw new IllegalArgumentException("CustomAction cannot be null.");
+ throw new IllegalArgumentException("CustomAction cannot be null");
}
sendCustomAction(customAction.getAction(), args);
}
@@ -966,12 +1058,12 @@
*/
public void sendCustomAction(@NonNull String action, @Nullable Bundle args) {
if (TextUtils.isEmpty(action)) {
- throw new IllegalArgumentException("CustomAction cannot be null.");
+ throw new IllegalArgumentException("CustomAction cannot be null");
}
try {
mSessionBinder.sendCustomAction(action, args);
} catch (RemoteException e) {
- Log.d(TAG, "Dead object in sendCustomAction.", e);
+ Log.d(TAG, "Dead object in sendCustomAction", e);
}
}
}
diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java
index 84dc93a..bee3f52 100644
--- a/media/java/android/media/session/MediaSession.java
+++ b/media/java/android/media/session/MediaSession.java
@@ -87,6 +87,12 @@
public static final int FLAG_HANDLES_TRANSPORT_CONTROLS = 1 << 1;
/**
+ * Set this flag on the session to indicate that it handles queue
+ * management commands through its {@link Callback}.
+ */
+ public static final int FLAG_HANDLES_QUEUE_COMMANDS = 1 << 2;
+
+ /**
* System only flag for a session that needs to have priority over all other
* sessions. This flag ensures this session will receive media button events
* regardless of the current ordering in the system.
@@ -100,6 +106,7 @@
@IntDef(flag = true, value = {
FLAG_HANDLES_MEDIA_BUTTONS,
FLAG_HANDLES_TRANSPORT_CONTROLS,
+ FLAG_HANDLES_QUEUE_COMMANDS,
FLAG_EXCLUSIVE_GLOBAL_PRIORITY })
public @interface SessionFlags { }
@@ -645,6 +652,22 @@
postToCallback(CallbackMessageHandler.MSG_CUSTOM_ACTION, action, args);
}
+ private void dispatchAddQueueItem(MediaDescription description) {
+ postToCallback(CallbackMessageHandler.MSG_ADD_QUEUE_ITEM, description);
+ }
+
+ private void dispatchAddQueueItem(MediaDescription description, int index) {
+ postToCallback(CallbackMessageHandler.MSG_ADD_QUEUE_ITEM_AT, description, index);
+ }
+
+ private void dispatchRemoveQueueItem(MediaDescription description) {
+ postToCallback(CallbackMessageHandler.MSG_REMOVE_QUEUE_ITEM, description);
+ }
+
+ private void dispatchRemoveQueueItemAt(int index) {
+ postToCallback(CallbackMessageHandler.MSG_REMOVE_QUEUE_ITEM_AT, index);
+ }
+
private void dispatchMediaButton(Intent mediaButtonIntent) {
postToCallback(CallbackMessageHandler.MSG_MEDIA_BUTTON, mediaButtonIntent);
}
@@ -666,10 +689,22 @@
postToCallback(CallbackMessageHandler.MSG_COMMAND, cmd);
}
+ private void postToCallback(int what, int arg1) {
+ postToCallback(what, null, arg1);
+ }
+
private void postToCallback(int what, Object obj) {
postToCallback(what, obj, null);
}
+ private void postToCallback(int what, Object obj, int arg1) {
+ synchronized (mLock) {
+ if (mCallback != null) {
+ mCallback.post(what, obj, arg1);
+ }
+ }
+ }
+
private void postToCallback(int what, Object obj, Bundle extras) {
synchronized (mLock) {
if (mCallback != null) {
@@ -1043,6 +1078,47 @@
*/
public void onCustomAction(@NonNull String action, @Nullable Bundle extras) {
}
+
+ /**
+ * Called when a {@link MediaController} wants to add a {@link QueueItem} with the given
+ * {@link MediaDescription description} at the end of the play queue.
+ *
+ * @param description The {@link MediaDescription} for creating the {@link QueueItem} to be
+ * inserted.
+ */
+ public void onAddQueueItem(MediaDescription description) {
+ }
+
+ /**
+ * Called when a {@link MediaController} wants to add a {@link QueueItem} with the given
+ * {@link MediaDescription description} at the specified position in the play queue.
+ *
+ * @param description The {@link MediaDescription} for creating the {@link QueueItem} to be
+ * inserted.
+ * @param index The index at which the created {@link QueueItem} is to be inserted.
+ */
+ public void onAddQueueItem(MediaDescription description, int index) {
+ }
+
+ /**
+ * Called when a {@link MediaController} wants to remove the first occurrence of the
+ * specified {@link QueueItem} with the given {@link MediaDescription description}
+ * in the play queue.
+ *
+ * @param description The {@link MediaDescription} for denoting the {@link QueueItem} to be
+ * removed.
+ */
+ public void onRemoveQueueItem(MediaDescription description) {
+ }
+
+ /**
+ * Called when a {@link MediaController} wants to remove a {@link QueueItem} at the
+ * specified position in the play queue.
+ *
+ * @param index The index of the element to be removed.
+ */
+ public void onRemoveQueueItemAt(int index) {
+ }
}
/**
@@ -1239,6 +1315,38 @@
}
@Override
+ public void onAddQueueItem(MediaDescription description) {
+ MediaSession session = mMediaSession.get();
+ if (session != null) {
+ session.dispatchAddQueueItem(description);
+ }
+ }
+
+ @Override
+ public void onAddQueueItemAt(MediaDescription description, int index) {
+ MediaSession session = mMediaSession.get();
+ if (session != null) {
+ session.dispatchAddQueueItem(description, index);
+ }
+ }
+
+ @Override
+ public void onRemoveQueueItem(MediaDescription description) {
+ MediaSession session = mMediaSession.get();
+ if (session != null) {
+ session.dispatchRemoveQueueItem(description);
+ }
+ }
+
+ @Override
+ public void onRemoveQueueItemAt(int index) {
+ MediaSession session = mMediaSession.get();
+ if (session != null) {
+ session.dispatchRemoveQueueItemAt(index);
+ }
+ }
+
+ @Override
public void onAdjustVolume(int direction) {
MediaSession session = mMediaSession.get();
if (session != null) {
@@ -1376,6 +1484,10 @@
private static final int MSG_CUSTOM_ACTION = 22;
private static final int MSG_ADJUST_VOLUME = 23;
private static final int MSG_SET_VOLUME = 24;
+ private static final int MSG_ADD_QUEUE_ITEM = 25;
+ private static final int MSG_ADD_QUEUE_ITEM_AT = 26;
+ private static final int MSG_REMOVE_QUEUE_ITEM = 27;
+ private static final int MSG_REMOVE_QUEUE_ITEM_AT = 28;
private MediaSession.Callback mCallback;
@@ -1465,7 +1577,7 @@
mCallback.onSetRating((Rating) msg.obj);
break;
case MSG_REPEAT_MODE:
- mCallback.onSetRepeatMode((int) msg.obj);
+ mCallback.onSetRepeatMode(msg.arg1);
break;
case MSG_SHUFFLE_MODE:
mCallback.onSetShuffleModeEnabled((boolean) msg.obj);
@@ -1473,12 +1585,24 @@
case MSG_CUSTOM_ACTION:
mCallback.onCustomAction((String) msg.obj, msg.getData());
break;
+ case MSG_ADD_QUEUE_ITEM:
+ mCallback.onAddQueueItem((MediaDescription) msg.obj);
+ break;
+ case MSG_ADD_QUEUE_ITEM_AT:
+ mCallback.onAddQueueItem((MediaDescription) msg.obj, msg.arg1);
+ break;
+ case MSG_REMOVE_QUEUE_ITEM:
+ mCallback.onRemoveQueueItem((MediaDescription) msg.obj);
+ break;
+ case MSG_REMOVE_QUEUE_ITEM_AT:
+ mCallback.onRemoveQueueItemAt(msg.arg1);
+ break;
case MSG_ADJUST_VOLUME:
synchronized (mLock) {
vp = mVolumeProvider;
}
if (vp != null) {
- vp.onAdjustVolume((int) msg.obj);
+ vp.onAdjustVolume(msg.arg1);
}
break;
case MSG_SET_VOLUME:
@@ -1486,7 +1610,7 @@
vp = mVolumeProvider;
}
if (vp != null) {
- vp.onSetVolumeTo((int) msg.obj);
+ vp.onSetVolumeTo(msg.arg1);
}
break;
}
diff --git a/opengl/java/android/opengl/GLU.java b/opengl/java/android/opengl/GLU.java
index ed64556..ef9bf167 100644
--- a/opengl/java/android/opengl/GLU.java
+++ b/opengl/java/android/opengl/GLU.java
@@ -203,8 +203,8 @@
* @param view the current view, {x, y, width, height}
* @param viewOffset the offset into the view array where the view vector
* data starts.
- * @param obj the output vector {objX, objY, objZ}, that returns the
- * computed object coordinates.
+ * @param obj the output vector {objX, objY, objZ, objW}, that returns the
+ * computed homogeneous object coordinates.
* @param objOffset the offset into the obj array where the obj vector data
* starts.
* @return A return value of GL10.GL_TRUE indicates success, a return value
diff --git a/packages/CompanionDeviceManager/Android.mk b/packages/CompanionDeviceManager/Android.mk
new file mode 100644
index 0000000..f730356
--- /dev/null
+++ b/packages/CompanionDeviceManager/Android.mk
@@ -0,0 +1,27 @@
+# Copyright (C) 2017 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := CompanionDeviceManager
+
+include $(BUILD_PACKAGE)
+
+include $(call all-makefiles-under, $(LOCAL_PATH))
diff --git a/packages/CompanionDeviceManager/AndroidManifest.xml b/packages/CompanionDeviceManager/AndroidManifest.xml
new file mode 100644
index 0000000..3eede54
--- /dev/null
+++ b/packages/CompanionDeviceManager/AndroidManifest.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (c) 2017 Google Inc.
+ *
+ * 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.
+ */
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.companiondevicemanager">
+
+ <permission
+ android:name="com.android.companiondevicemanager.permission.BIND"
+ android:protectionLevel="signature" />
+
+ <uses-permission android:name="android.permission.BLUETOOTH"/>
+ <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
+ <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
+
+ <application
+ android:allowClearUserData="true"
+ android:label="@string/app_label"
+ android:allowBackup="false"
+ android:supportsRtl="true">
+
+ <service
+ android:name=".DeviceDiscoveryService"
+ android:permission="android.permission.BIND_COMPANION_DEVICE_MANAGER_SERVICE"
+ android:exported="true">
+ </service>
+
+ <activity
+ android:name=".DeviceChooserActivity"
+ android:theme="@*android:style/Theme.Dialog.NoFrame"
+ android:permission="android.permission.BIND_COMPANION_DEVICE_MANAGER_SERVICE">
+ <!--TODO include url scheme filter similar to PrintSpooler -->
+ <intent-filter>
+ <action android:name="android.companiondevice.START_DISCOVERY" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
+
+ </application>
+
+</manifest>
diff --git a/packages/CompanionDeviceManager/MODULE_LICENSE_APACHE2 b/packages/CompanionDeviceManager/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/packages/CompanionDeviceManager/MODULE_LICENSE_APACHE2
diff --git a/packages/CompanionDeviceManager/NOTICE b/packages/CompanionDeviceManager/NOTICE
new file mode 100644
index 0000000..c5b1efa
--- /dev/null
+++ b/packages/CompanionDeviceManager/NOTICE
@@ -0,0 +1,190 @@
+
+ Copyright (c) 2005-2008, 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.
+
+ 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.
+
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
diff --git a/packages/CompanionDeviceManager/res/layout/device_chooser.xml b/packages/CompanionDeviceManager/res/layout/device_chooser.xml
new file mode 100644
index 0000000..ee08582
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/layout/device_chooser.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 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.
+-->
+
+<RelativeLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_weight="0.1"
+ >
+
+ <TextView
+ android:id="@+id/title"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textColor="@android:color/black"
+ style="@*android:style/TextAppearance.Widget.Toolbar.Title"
+ />
+
+ <ListView
+ android:id="@+id/device_list"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/title"
+ android:layout_above="@+id/buttons"
+ style="@android:style/Widget.Material.Light.ListView"
+ />
+
+ <LinearLayout
+ android:id="@+id/buttons"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentEnd="true"
+ android:gravity="end"
+ >
+ <Button
+ android:id="@+id/button_cancel"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Cancel"
+ style="@android:style/Widget.Material.Light.Button.Borderless.Colored"
+ />
+ <Button
+ android:id="@+id/button_pair"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Pair"
+ style="@android:style/Widget.Material.Light.Button.Borderless.Colored"
+ />
+ </LinearLayout>
+
+</RelativeLayout>
\ No newline at end of file
diff --git a/packages/CompanionDeviceManager/res/values/dimens.xml b/packages/CompanionDeviceManager/res/values/dimens.xml
new file mode 100644
index 0000000..da7b0d1
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values/dimens.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+ <!-- Padding applied on most UI elements -->
+ <dimen name="padding">12dp</dimen>
+
+</resources>
\ No newline at end of file
diff --git a/packages/CompanionDeviceManager/res/values/strings.xml b/packages/CompanionDeviceManager/res/values/strings.xml
new file mode 100644
index 0000000..c4195b50
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 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.
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+ <!-- Title of the CompanionDeviceManager application. [CHAR LIMIT=50] -->
+ <string name="app_label">Companion Device Manager</string>
+
+ <!-- Title of the device selection dialog. -->
+ <string name="chooser_title">Pair with <strong><xliff:g id="app_name" example="Android Wear">%1$s</xliff:g></strong> via Bluetooth?</string>
+
+</resources>
diff --git a/core/res/res/values-ldrtl/dimens.xml b/packages/CompanionDeviceManager/res/values/themes.xml
similarity index 62%
rename from core/res/res/values-ldrtl/dimens.xml
rename to packages/CompanionDeviceManager/res/values/themes.xml
index 807c042..465f8fc 100644
--- a/core/res/res/values-ldrtl/dimens.xml
+++ b/packages/CompanionDeviceManager/res/values/themes.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
+<!-- Copyright (C) 2017 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.
@@ -15,6 +15,11 @@
-->
<resources>
- <item type="dimen" format="integer" name="time_picker_column_start_material">1</item>
- <item type="dimen" format="integer" name="time_picker_column_end_material">0</item>
+
+ <!--TODO-->
+ <!--<style name="Theme.ChooserActivity" parent="@*android:style/Theme.Dialog.NoFrame">-->
+ <!--<!–<item name="android:windowBackground">@android:color/light_grey</item>–>-->
+ <!--<item name="android:backgroundColor">@android:color/light_grey</item>-->
+ <!--</style>-->
+
</resources>
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java
new file mode 100644
index 0000000..c95f940
--- /dev/null
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2017 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.companiondevicemanager;
+
+import android.app.Activity;
+import android.bluetooth.BluetoothDevice;
+import android.companion.CompanionDeviceManager;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.database.DataSetObserver;
+import android.graphics.Color;
+import android.os.Bundle;
+import android.text.Html;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.View;
+import android.widget.ListView;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+import android.widget.Toast;
+
+public class DeviceChooserActivity extends Activity {
+
+ private static final boolean DEBUG = false;
+ private static final String LOG_TAG = "DeviceChooserActivity";
+
+ private ListView mDeviceListView;
+ private View mPairButton;
+ private View mCancelButton;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ if (DEBUG) Log.i(LOG_TAG, "Started with intent " + getIntent());
+
+ setContentView(R.layout.device_chooser);
+ setTitle(Html.fromHtml(getString(R.string.chooser_title, getCallingAppName()), 0));
+ getWindow().getDecorView().getRootView().setBackgroundColor(Color.LTGRAY); //TODO theme
+
+ if (getService().mDevicesFound.isEmpty()) {
+ Log.e(LOG_TAG, "About to show UI, but no devices to show");
+ }
+
+ final DeviceDiscoveryService.DevicesAdapter adapter = getService().mDevicesAdapter;
+ mDeviceListView = (ListView) findViewById(R.id.device_list);
+ mDeviceListView.setAdapter(adapter);
+ mDeviceListView.addFooterView(getProgressBar(), null, false);
+
+ mPairButton = findViewById(R.id.button_pair);
+ mPairButton.setOnClickListener((view) ->
+ onPairTapped(getService().mSelectedDevice));
+ adapter.registerDataSetObserver(new DataSetObserver() {
+ @Override
+ public void onChanged() {
+ updatePairButtonEnabled();
+ }
+ });
+ updatePairButtonEnabled();
+ mCancelButton = findViewById(R.id.button_cancel);
+ mCancelButton.setOnClickListener((view) -> {
+ setResult(RESULT_CANCELED);
+ finish();
+ });
+ }
+
+ private CharSequence getCallingAppName() {
+ try {
+ final PackageManager packageManager = getPackageManager();
+ return packageManager.getApplicationLabel(
+ packageManager.getApplicationInfo(getService().mCallingPackage, 0));
+ } catch (PackageManager.NameNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public void setTitle(CharSequence title) {
+ final TextView titleView = (TextView) findViewById(R.id.title);
+ final int padding = getPadding(getResources());
+ titleView.setPadding(padding, padding, padding, padding);
+ titleView.setText(title);
+ }
+
+ //TODO put in resources xmls
+ private ProgressBar getProgressBar() {
+ final ProgressBar progressBar = new ProgressBar(this);
+ progressBar.setForegroundGravity(Gravity.CENTER_HORIZONTAL);
+ final int padding = getPadding(getResources());
+ progressBar.setPadding(padding, padding, padding, padding);
+ return progressBar;
+ }
+
+ static int getPadding(Resources r) {
+ return r.getDimensionPixelSize(R.dimen.padding);
+ //TODO
+// final float dp = r.getDisplayMetrics().density;
+// return (int)(12 * dp);
+ }
+
+ private void updatePairButtonEnabled() {
+ mPairButton.setEnabled(getService().mSelectedDevice != null);
+ }
+
+ private DeviceDiscoveryService getService() {
+ return DeviceDiscoveryService.sInstance;
+ }
+
+ protected void onPairTapped(BluetoothDevice selectedDevice) {
+ setResult(RESULT_OK,
+ new Intent().putExtra(CompanionDeviceManager.EXTRA_DEVICE, selectedDevice));
+ finish();
+ }
+
+ private void toast(String msg) {
+ Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
+ }
+}
\ No newline at end of file
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
new file mode 100644
index 0000000..a3eec0d
--- /dev/null
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
@@ -0,0 +1,273 @@
+/*
+ * Copyright (C) 2013 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.companiondevicemanager;
+
+import static android.companion.BluetoothDeviceFilterUtils.getDeviceDisplayName;
+import static android.companion.BluetoothLEDeviceFilter.nullsafe;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.PendingIntent;
+import android.app.Service;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothManager;
+import android.bluetooth.le.BluetoothLeScanner;
+import android.bluetooth.le.ScanCallback;
+import android.bluetooth.le.ScanFilter;
+import android.bluetooth.le.ScanResult;
+import android.bluetooth.le.ScanSettings;
+import android.companion.AssociationRequest;
+import android.companion.BluetoothDeviceFilterUtils;
+import android.companion.BluetoothLEDeviceFilter;
+import android.companion.ICompanionDeviceManagerService;
+import android.companion.IOnAssociateCallback;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.graphics.Color;
+import android.graphics.PorterDuff;
+import android.graphics.drawable.Drawable;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class DeviceDiscoveryService extends Service {
+
+ private static final boolean DEBUG = false;
+ private static final String LOG_TAG = "DeviceDiscoveryService";
+
+ static DeviceDiscoveryService sInstance;
+
+ private BluetoothAdapter mBluetoothAdapter;
+ private BluetoothLEDeviceFilter mFilter;
+ private ScanFilter mScanFilter;
+ private ScanSettings mDefaultScanSettings = new ScanSettings.Builder().build();
+ List<BluetoothDevice> mDevicesFound;
+ BluetoothDevice mSelectedDevice;
+ DevicesAdapter mDevicesAdapter;
+ IOnAssociateCallback mCallback;
+ String mCallingPackage;
+
+ private final ICompanionDeviceManagerService mBinder =
+ new ICompanionDeviceManagerService.Stub() {
+ @Override
+ public void startDiscovery(AssociationRequest request,
+ IOnAssociateCallback callback,
+ String callingPackage) throws RemoteException {
+ if (DEBUG) {
+ Log.i(LOG_TAG,
+ "startDiscovery() called with: filter = [" + request + "], callback = ["
+ + callback + "]");
+ }
+ mCallback = callback;
+ mCallingPackage = callingPackage;
+ DeviceDiscoveryService.this.startDiscovery(request);
+ }
+ };
+
+ private final ScanCallback mBLEScanCallback = new ScanCallback() {
+ @Override
+ public void onScanResult(int callbackType, ScanResult result) {
+ final BluetoothDevice device = result.getDevice();
+ if (callbackType == ScanSettings.CALLBACK_TYPE_MATCH_LOST) {
+ onDeviceLost(device);
+ } else {
+ onDeviceFound(device);
+ }
+ }
+ };
+
+ private BluetoothLeScanner mBLEScanner;
+
+ private BroadcastReceiver mBluetoothDeviceFoundBroadcastReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final BluetoothDevice device = intent.getParcelableExtra(
+ BluetoothDevice.EXTRA_DEVICE);
+ if (!mFilter.matches(device)) return; // ignore device
+
+ if (intent.getAction().equals(BluetoothDevice.ACTION_FOUND)) {
+ onDeviceFound(device);
+ } else {
+ onDeviceLost(device);
+ }
+ }
+ };
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ if (DEBUG) Log.i(LOG_TAG, "onBind(" + intent + ")");
+ return mBinder.asBinder();
+ }
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+
+ if (DEBUG) Log.i(LOG_TAG, "onCreate()");
+
+ mBluetoothAdapter = getSystemService(BluetoothManager.class).getAdapter();
+ mBLEScanner = mBluetoothAdapter.getBluetoothLeScanner();
+
+ mDevicesFound = new ArrayList<>();
+ mDevicesAdapter = new DevicesAdapter();
+
+ sInstance = this;
+ }
+
+ private void startDiscovery(AssociationRequest<?> request) {
+ //TODO support other protocols as well
+ mFilter = nullsafe((BluetoothLEDeviceFilter) request.getDeviceFilter());
+ mScanFilter = mFilter.getScanFilter();
+
+ reset();
+
+ final IntentFilter intentFilter = new IntentFilter();
+ intentFilter.addAction(BluetoothDevice.ACTION_FOUND);
+ intentFilter.addAction(BluetoothDevice.ACTION_DISAPPEARED);
+
+ registerReceiver(mBluetoothDeviceFoundBroadcastReceiver, intentFilter);
+ mBluetoothAdapter.startDiscovery();
+
+ mBLEScanner.startScan(
+ Collections.singletonList(mScanFilter), mDefaultScanSettings, mBLEScanCallback);
+ }
+
+ private void reset() {
+ mDevicesFound.clear();
+ mSelectedDevice = null;
+ mDevicesAdapter.notifyDataSetChanged();
+ }
+
+ @Override
+ public boolean onUnbind(Intent intent) {
+ stopScan();
+ return super.onUnbind(intent);
+ }
+
+ private void stopScan() {
+ if (DEBUG) Log.i(LOG_TAG, "stopScan() called");
+ mBluetoothAdapter.cancelDiscovery();
+ mBLEScanner.stopScan(mBLEScanCallback);
+ unregisterReceiver(mBluetoothDeviceFoundBroadcastReceiver);
+ stopSelf();
+ }
+
+ private void onDeviceFound(BluetoothDevice device) {
+ if (mDevicesFound.contains(device)) {
+ return;
+ }
+
+ if (DEBUG) {
+ Log.i(LOG_TAG, "Considering device " + getDeviceDisplayName(device));
+ }
+
+ if (!mFilter.matches(device)) {
+ return;
+ }
+
+ if (DEBUG) {
+ Log.i(LOG_TAG, "Found device " + getDeviceDisplayName(device));
+ }
+ if (mDevicesFound.isEmpty()) {
+ onReadyToShowUI();
+ }
+ mDevicesFound.add(device);
+ mDevicesAdapter.notifyDataSetChanged();
+ }
+
+ //TODO also, on timeout -> call onFailure
+ private void onReadyToShowUI() {
+ try {
+ mCallback.onSuccess(PendingIntent.getActivity(
+ this, 0,
+ new Intent(this, DeviceChooserActivity.class),
+ PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_CANCEL_CURRENT
+ | PendingIntent.FLAG_IMMUTABLE));
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private void onDeviceLost(BluetoothDevice device) {
+ mDevicesFound.remove(device);
+ mDevicesAdapter.notifyDataSetChanged();
+ if (DEBUG) {
+ Log.i(LOG_TAG, "Lost device " + getDeviceDisplayName(device));
+ }
+ }
+
+ class DevicesAdapter extends ArrayAdapter<BluetoothDevice> {
+ private Drawable BLUETOOTH_ICON = icon(android.R.drawable.stat_sys_data_bluetooth);
+
+ private Drawable icon(int drawableRes) {
+ Drawable icon = getResources().getDrawable(drawableRes, null);
+ icon.setTint(Color.DKGRAY);
+ return icon;
+ }
+
+ public DevicesAdapter() {
+ super(DeviceDiscoveryService.this, 0, mDevicesFound);
+ }
+
+ @Override
+ public View getView(
+ int position,
+ @Nullable View convertView,
+ @NonNull ViewGroup parent) {
+ TextView view = convertView instanceof TextView
+ ? (TextView) convertView
+ : newView();
+ bind(view, getItem(position));
+ return view;
+ }
+
+ private void bind(TextView textView, BluetoothDevice device) {
+ textView.setText(getDeviceDisplayName(device));
+ textView.setBackgroundColor(
+ device.equals(mSelectedDevice)
+ ? Color.GRAY
+ : Color.TRANSPARENT);
+ textView.setOnClickListener((view) -> {
+ mSelectedDevice = device;
+ notifyDataSetChanged();
+ });
+ }
+
+ //TODO move to a layout file
+ private TextView newView() {
+ final TextView textView = new TextView(DeviceDiscoveryService.this);
+ textView.setTextColor(Color.BLACK);
+ final int padding = DeviceChooserActivity.getPadding(getResources());
+ textView.setPadding(padding, padding, padding, padding);
+ textView.setCompoundDrawablesWithIntrinsicBounds(
+ BLUETOOTH_ICON, null, null, null);
+ textView.setCompoundDrawablePadding(padding);
+ return textView;
+ }
+ }
+}
diff --git a/packages/Keyguard/res/values-bn/strings.xml b/packages/Keyguard/res/values-bn/strings.xml
index 1a2a8dd..64c01bb 100644
--- a/packages/Keyguard/res/values-bn/strings.xml
+++ b/packages/Keyguard/res/values-bn/strings.xml
@@ -47,8 +47,8 @@
<string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"সিম কার্ডটি PUK কোড দিয়ে লক করা আছে৷"</string>
<string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"সিম কার্ড আনলক করা হচ্ছে…"</string>
<string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"পিন অঞ্চল"</string>
- <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM পিন অঞ্চল"</string>
- <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUK অঞ্চল"</string>
+ <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"সিম পিন অঞ্চল"</string>
+ <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"সিম PUK অঞ্চল"</string>
<string name="keyguard_accessibility_next_alarm" msgid="7269583073750518672">"<xliff:g id="ALARM">%1$s</xliff:g> এ পরবর্তী অ্যালার্ম সেট করা হয়েছে"</string>
<string name="keyboardview_keycode_delete" msgid="3337914833206635744">"মুছুন"</string>
<string name="keyboardview_keycode_enter" msgid="2985864015076059467">"Enter"</string>
@@ -59,11 +59,11 @@
<string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"<xliff:g id="NUMBER">%d</xliff:g> সেকেন্ডের মধ্যে আবার চেষ্টা করুন৷"</string>
<string name="kg_pattern_instructions" msgid="398978611683075868">"আপনার প্যাটার্ন আঁকুন"</string>
<string name="kg_sim_pin_instructions" msgid="2319508550934557331">"সিম পিন লিখুন"</string>
- <string name="kg_sim_pin_instructions_multi" msgid="7818515973197201434">"\"<xliff:g id="CARRIER">%1$s</xliff:g>\" এর জন্য SIM পিন লিখুন"</string>
+ <string name="kg_sim_pin_instructions_multi" msgid="7818515973197201434">"\"<xliff:g id="CARRIER">%1$s</xliff:g>\" এর জন্য সিম পিন লিখুন"</string>
<string name="kg_pin_instructions" msgid="2377242233495111557">"পিন লিখুন"</string>
<string name="kg_password_instructions" msgid="5753646556186936819">"পাসওয়ার্ড লিখুন"</string>
<string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"সিম এখন অক্ষম করা হয়েছে৷ অবিরত থাকতে PUK কোডটি লিখুন৷ বিশদ বিবরণের জন্য ক্যারিয়ারের সাথে যোগাযোগ করুন৷"</string>
- <string name="kg_puk_enter_puk_hint_multi" msgid="363822494559783025">"SIM \"<xliff:g id="CARRIER">%1$s</xliff:g>\" এখন অক্ষম করা হয়েছে৷ চালিয়ে যেতে PUK কোড লিখুন৷ বিস্তারিত জানার জন্য ক্যারিয়ারের সাথে যোগাযোগ করুন৷"</string>
+ <string name="kg_puk_enter_puk_hint_multi" msgid="363822494559783025">"সিম \"<xliff:g id="CARRIER">%1$s</xliff:g>\" এখন অক্ষম করা হয়েছে৷ চালিয়ে যেতে PUK কোড লিখুন৷ বিস্তারিত জানার জন্য ক্যারিয়ারের সাথে যোগাযোগ করুন৷"</string>
<string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"কাঙ্ক্ষিত পিন কোড লিখুন"</string>
<string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"কাঙ্ক্ষিত পিন কোড নিশ্চিত করুন"</string>
<string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"সিম কার্ড আনলক করা হচ্ছে…"</string>
@@ -91,13 +91,13 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"আপনি আপনার আনলকের প্যাটার্ন আঁকার ক্ষেত্রে <xliff:g id="NUMBER_0">%1$d</xliff:g> বার ভুল করেছেন৷ আর <xliff:g id="NUMBER_1">%2$d</xliff:g> বার অসফল প্রচেষ্টা করা হলে আপনাকে একটি ইমেল অ্যাকাউন্ট মারফত আপনার ফোন আনলক করতে বলা হবে৷\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> সেকেন্ডের মধ্যে আবার চেষ্টা করুন৷"</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"ভুল সিম পিন কোড, আপনার ডিভাইসটি আনলক করতে এখন আপনাকে অবশ্যই আপনার ক্যারিয়ারের সাথে যোগাযোগ করতে হবে৷"</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
- <item quantity="one">ভুল SIM পিন কোড, আপনার কাছে আর <xliff:g id="NUMBER_1">%d</xliff:g>টি প্রচেষ্টা বাকি রয়েছে৷</item>
- <item quantity="other">ভুল SIM পিন কোড, আপনার কাছে আর <xliff:g id="NUMBER_1">%d</xliff:g>টি প্রচেষ্টা বাকি রয়েছে৷</item>
+ <item quantity="one">ভুল সিম পিন কোড, আপনার কাছে আর <xliff:g id="NUMBER_1">%d</xliff:g>টি প্রচেষ্টা বাকি রয়েছে৷</item>
+ <item quantity="other">ভুল সিম পিন কোড, আপনার কাছে আর <xliff:g id="NUMBER_1">%d</xliff:g>টি প্রচেষ্টা বাকি রয়েছে৷</item>
</plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"SIMটি ব্যবহারের অযোগ্য৷ আপনার ক্যারিয়ারের সাথে যোগাযোগ করুন৷"</string>
<plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
- <item quantity="one">ভুল SIM PUK কোড, আপনার কাছে আর <xliff:g id="NUMBER_1">%d</xliff:g>টি প্রচেষ্টা বাকি রয়েছে এটির পরেই আপনার SIM স্থায়ীভাবে অব্যবহারযোগ্য হবে৷</item>
- <item quantity="other">ভুল SIM PUK কোড, আপনার কাছে আর <xliff:g id="NUMBER_1">%d</xliff:g>টি প্রচেষ্টা বাকি রয়েছে এটির পরেই আপনার SIM স্থায়ীভাবে অব্যবহারযোগ্য হবে৷</item>
+ <item quantity="one">ভুল সিম PUK কোড, আপনার কাছে আর <xliff:g id="NUMBER_1">%d</xliff:g>টি প্রচেষ্টা বাকি রয়েছে এটির পরেই আপনার সিম স্থায়ীভাবে অব্যবহারযোগ্য হবে৷</item>
+ <item quantity="other">ভুল সিম PUK কোড, আপনার কাছে আর <xliff:g id="NUMBER_1">%d</xliff:g>টি প্রচেষ্টা বাকি রয়েছে এটির পরেই আপনার সিম স্থায়ীভাবে অব্যবহারযোগ্য হবে৷</item>
</plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"সিম পিন ক্রিয়াকলাপটি ব্যর্থ হয়েছে!"</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"সিম PUK ক্রিয়াকলাপটি ব্যর্থ হয়েছে!"</string>
diff --git a/packages/Keyguard/res/values-da/strings.xml b/packages/Keyguard/res/values-da/strings.xml
index b98a253..0fb7416 100644
--- a/packages/Keyguard/res/values-da/strings.xml
+++ b/packages/Keyguard/res/values-da/strings.xml
@@ -58,7 +58,7 @@
<string name="kg_wrong_pin" msgid="1131306510833563801">"Forkert pinkode"</string>
<string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"Prøv igen om <xliff:g id="NUMBER">%d</xliff:g> sekunder."</string>
<string name="kg_pattern_instructions" msgid="398978611683075868">"Tegn dit mønster"</string>
- <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"Indtast pinkode til SIM"</string>
+ <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"Indtast pinkode til SIM-kort"</string>
<string name="kg_sim_pin_instructions_multi" msgid="7818515973197201434">"Indtast SIM-pinkoden for \"<xliff:g id="CARRIER">%1$s</xliff:g>\""</string>
<string name="kg_pin_instructions" msgid="2377242233495111557">"Indtast pinkode"</string>
<string name="kg_password_instructions" msgid="5753646556186936819">"Angiv adgangskode"</string>
@@ -105,13 +105,13 @@
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Ingen dækning."</string>
<string name="accessibility_ime_switch_button" msgid="2829803408288433429">"Skift indtastningsmetode"</string>
<string name="airplane_mode" msgid="3122107900897202805">"Flytilstand"</string>
- <string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"Du skal indtaste et mønster efter genstart af enheden"</string>
+ <string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"Du skal angive et mønster efter genstart af enheden"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"Der skal indtaste en pinkode efter genstart af enheden"</string>
<string name="kg_prompt_reason_restart_password" msgid="6504585392626524695">"Du skal indtaste en adgangskode efter genstart af enheden"</string>
<string name="kg_prompt_reason_timeout_pattern" msgid="3717506169674397620">"Der kræves et mønster som ekstra beskyttelse"</string>
<string name="kg_prompt_reason_timeout_pin" msgid="6951483704195396341">"Der kræves en pinkode som ekstra beskyttelse"</string>
<string name="kg_prompt_reason_timeout_password" msgid="7306667546971345027">"Der kræves en adgangskode som ekstra beskyttelse"</string>
- <string name="kg_prompt_reason_switch_profiles_pattern" msgid="8476293962695171574">"Du skal indtaste et mønster, når du skifter profil"</string>
+ <string name="kg_prompt_reason_switch_profiles_pattern" msgid="8476293962695171574">"Du skal angive et mønster, når du skifter profil"</string>
<string name="kg_prompt_reason_switch_profiles_pin" msgid="2343607138520460043">"Du skal indtaste en pinkode, når du skifter profil"</string>
<string name="kg_prompt_reason_switch_profiles_password" msgid="1295960907951965927">"Du skal indtaste en adgangskode, når du skifter profil"</string>
<string name="kg_prompt_reason_device_admin" msgid="5838877342219587193">"Enhedsadministratoren har låst enheden"</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/SuggestionParser.java b/packages/SettingsLib/src/com/android/settingslib/SuggestionParser.java
index 13bbc33..4b0ab59 100644
--- a/packages/SettingsLib/src/com/android/settingslib/SuggestionParser.java
+++ b/packages/SettingsLib/src/com/android/settingslib/SuggestionParser.java
@@ -94,16 +94,27 @@
private static final long MILLIS_IN_DAY = 24 * 60 * 60 * 1000;
+ // Default dismiss control for smart suggestions.
+ private static final String DEFAULT_SMART_DISMISS_CONTROL = "0,10";
+
private final Context mContext;
private final List<SuggestionCategory> mSuggestionList;
private final ArrayMap<Pair<String, String>, Tile> mAddCache = new ArrayMap<>();
private final SharedPreferences mSharedPrefs;
+ private final String mSmartDismissControl;
- public SuggestionParser(Context context, SharedPreferences sharedPrefs, int orderXml) {
+
+ public SuggestionParser(
+ Context context, SharedPreferences sharedPrefs, int orderXml, String smartDismissControl) {
mContext = context;
mSuggestionList = (List<SuggestionCategory>) new SuggestionOrderInflater(mContext)
.parse(orderXml);
mSharedPrefs = sharedPrefs;
+ mSmartDismissControl = smartDismissControl;
+ }
+
+ public SuggestionParser(Context context, SharedPreferences sharedPrefs, int orderXml) {
+ this(context, sharedPrefs, orderXml, DEFAULT_SMART_DISMISS_CONTROL);
}
@VisibleForTesting
@@ -111,26 +122,35 @@
mContext = context;
mSuggestionList = new ArrayList<SuggestionCategory>();
mSharedPrefs = sharedPrefs;
+ mSmartDismissControl = DEFAULT_SMART_DISMISS_CONTROL;
Log.wtf(TAG, "Only use this constructor for testing");
}
public List<Tile> getSuggestions() {
+ return getSuggestions(false);
+ }
+
+ public List<Tile> getSuggestions(boolean isSmartSuggestionEnabled) {
List<Tile> suggestions = new ArrayList<>();
final int N = mSuggestionList.size();
for (int i = 0; i < N; i++) {
- readSuggestions(mSuggestionList.get(i), suggestions);
+ readSuggestions(mSuggestionList.get(i), suggestions, isSmartSuggestionEnabled);
}
return suggestions;
}
+ public boolean dismissSuggestion(Tile suggestion) {
+ return dismissSuggestion(suggestion, false);
+ }
+
/**
* Dismisses a suggestion, returns true if the suggestion has no more dismisses left and should
* be disabled.
*/
- public boolean dismissSuggestion(Tile suggestion) {
+ public boolean dismissSuggestion(Tile suggestion, boolean isSmartSuggestionEnabled) {
String keyBase = suggestion.intent.getComponent().flattenToShortString();
int index = mSharedPrefs.getInt(keyBase + DISMISS_INDEX, 0);
- String dismissControl = suggestion.metaData.getString(META_DATA_DISMISS_CONTROL);
+ String dismissControl = getDismissControl(suggestion, isSmartSuggestionEnabled);
if (dismissControl == null || parseDismissString(dismissControl).length == index) {
return true;
}
@@ -141,20 +161,23 @@
}
@VisibleForTesting
- public void filterSuggestions(List<Tile> suggestions, int countBefore) {
+ public void filterSuggestions(
+ List<Tile> suggestions, int countBefore, boolean isSmartSuggestionEnabled) {
for (int i = countBefore; i < suggestions.size(); i++) {
if (!isAvailable(suggestions.get(i)) ||
!isSupported(suggestions.get(i)) ||
!satisifesRequiredUserType(suggestions.get(i)) ||
!satisfiesRequiredAccount(suggestions.get(i)) ||
!satisfiesConnectivity(suggestions.get(i)) ||
- isDismissed(suggestions.get(i))) {
+ isDismissed(suggestions.get(i), isSmartSuggestionEnabled)) {
suggestions.remove(i--);
}
}
}
- private void readSuggestions(SuggestionCategory category, List<Tile> suggestions) {
+ @VisibleForTesting
+ void readSuggestions(
+ SuggestionCategory category, List<Tile> suggestions, boolean isSmartSuggestionEnabled) {
int countBefore = suggestions.size();
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(category.category);
@@ -163,7 +186,7 @@
}
TileUtils.getTilesForIntent(mContext, new UserHandle(UserHandle.myUserId()), intent,
mAddCache, null, suggestions, true, false);
- filterSuggestions(suggestions, countBefore);
+ filterSuggestions(suggestions, countBefore, isSmartSuggestionEnabled);
if (!category.multiple && suggestions.size() > (countBefore + 1)) {
// If there are too many, remove them all and only re-add the one with the highest
// priority.
@@ -288,12 +311,11 @@
Settings.Secure.putInt(mContext.getContentResolver(), name, 1);
}
- private boolean isDismissed(Tile suggestion) {
- Object dismissObj = suggestion.metaData.get(META_DATA_DISMISS_CONTROL);
- if (dismissObj == null) {
+ private boolean isDismissed(Tile suggestion, boolean isSmartSuggestionEnabled) {
+ String dismissControl = getDismissControl(suggestion, isSmartSuggestionEnabled);
+ if (dismissControl == null) {
return false;
}
- String dismissControl = String.valueOf(dismissObj);
String keyBase = suggestion.intent.getComponent().flattenToShortString();
if (!mSharedPrefs.contains(keyBase + SETUP_TIME)) {
mSharedPrefs.edit()
@@ -333,7 +355,16 @@
return dismisses;
}
- private static class SuggestionCategory {
+ private String getDismissControl(Tile suggestion, boolean isSmartSuggestionEnabled) {
+ if (isSmartSuggestionEnabled) {
+ return mSmartDismissControl;
+ } else {
+ return suggestion.metaData.getString(META_DATA_DISMISS_CONTROL);
+ }
+ }
+
+ @VisibleForTesting
+ static class SuggestionCategory {
public String category;
public String pkg;
public boolean multiple;
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryKey.java b/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryKey.java
index 7e3f67b..d6bde81 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryKey.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryKey.java
@@ -36,7 +36,6 @@
public static final String CATEGORY_SECURITY = "com.android.settings.category.ia.security";
public static final String CATEGORY_ACCOUNT = "com.android.settings.category.ia.accounts";
public static final String CATEGORY_SYSTEM = "com.android.settings.category.ia.system";
- public static final String CATEGORY_SYSTEM_INPUT = "com.android.settings.category.ia.input";
public static final String CATEGORY_SYSTEM_LANGUAGE =
"com.android.settings.category.ia.language";
public static final String CATEGORY_SYSTEM_DEVELOPMENT =
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index 06ea445..82e69d8 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -222,21 +222,21 @@
if (isActive() && !other.isActive()) return -1;
if (!isActive() && other.isActive()) return 1;
- // Higher scores go before lower scores
- if (mRankingScore != other.mRankingScore) {
- return (mRankingScore > other.mRankingScore) ? -1 : 1;
- }
-
// Reachable one goes before unreachable one.
if (mRssi != Integer.MAX_VALUE && other.mRssi == Integer.MAX_VALUE) return -1;
if (mRssi == Integer.MAX_VALUE && other.mRssi != Integer.MAX_VALUE) return 1;
- // Configured one goes before unconfigured one.
+ // Configured (saved) one goes before unconfigured one.
if (networkId != WifiConfiguration.INVALID_NETWORK_ID
&& other.networkId == WifiConfiguration.INVALID_NETWORK_ID) return -1;
if (networkId == WifiConfiguration.INVALID_NETWORK_ID
&& other.networkId != WifiConfiguration.INVALID_NETWORK_ID) return 1;
+ // Higher scores go before lower scores
+ if (mRankingScore != other.mRankingScore) {
+ return (mRankingScore > other.mRankingScore) ? -1 : 1;
+ }
+
// Sort by signal strength, bucketed by level
int difference = WifiManager.calculateSignalLevel(other.mRssi, SIGNAL_LEVELS)
- WifiManager.calculateSignalLevel(mRssi, SIGNAL_LEVELS);
diff --git a/packages/SettingsLib/tests/robotests/Android.mk b/packages/SettingsLib/tests/robotests/Android.mk
index 7a89884a..596d614 100644
--- a/packages/SettingsLib/tests/robotests/Android.mk
+++ b/packages/SettingsLib/tests/robotests/Android.mk
@@ -43,6 +43,12 @@
LOCAL_SRC_FILES := \
$(call all-java-files-under, src)
+LOCAL_JAR_EXCLUDE_FILES := none
+
+LOCAL_RESOURCE_DIR := \
+ $(LOCAL_PATH)/res
+
+
include frameworks/base/packages/SettingsLib/common.mk
include $(BUILD_PACKAGE)
diff --git a/packages/SettingsLib/tests/robotests/res/xml/suggestion_ordering.xml b/packages/SettingsLib/tests/robotests/res/xml/suggestion_ordering.xml
new file mode 100644
index 0000000..1eeafba
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/res/xml/suggestion_ordering.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+
+<optional-steps>
+ <step category="com.android.settings.suggested.category.LOCK_SCREEN" />
+ <step category="com.android.settings.suggested.category.EMAIL" />
+ <step category="com.android.settings.suggested.category.PARTNER_ACCOUNT"
+ multiple="true" />
+ <step category="com.android.settings.suggested.category.HOTWORD" />
+ <step category="com.android.settings.suggested.category.DEFAULT"
+ multiple="true" />
+ <step category="com.android.settings.suggested.category.SETTINGS_ONLY"
+ multiple="true" />
+</optional-steps>
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/SettingLibRobolectricTestRunner.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/SettingLibRobolectricTestRunner.java
new file mode 100644
index 0000000..11c925e
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/SettingLibRobolectricTestRunner.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settingslib;
+
+import org.junit.runners.model.InitializationError;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
+import org.robolectric.manifest.AndroidManifest;
+import org.robolectric.res.Fs;
+import org.robolectric.res.ResourcePath;
+
+import java.util.List;
+
+public class SettingLibRobolectricTestRunner extends RobolectricTestRunner {
+
+ public SettingLibRobolectricTestRunner(Class<?> testClass) throws InitializationError {
+ super(testClass);
+ }
+
+ @Override
+ protected AndroidManifest getAppManifest(Config config) {
+ // Using the manifest file's relative path, we can figure out the application directory.
+ final String appRoot = "frameworks/base/packages/SettingsLib";
+ final String manifestPath = appRoot + "/AndroidManifest.xml";
+ final String resDir = appRoot + "/tests/robotests/res";
+ final String assetsDir = appRoot + config.assetDir();
+
+ final AndroidManifest manifest = new AndroidManifest(Fs.fileFromPath(manifestPath),
+ Fs.fileFromPath(resDir), Fs.fileFromPath(assetsDir));
+
+ manifest.setPackageName("com.android.settingslib");
+ return manifest;
+ }
+
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/SuggestionParserTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/SuggestionParserTest.java
new file mode 100644
index 0000000..0032cf0
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/SuggestionParserTest.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib;
+
+import android.util.Log;
+import android.content.Context;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.os.Bundle;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.preference.PreferenceManager;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
+
+import com.android.settingslib.drawer.Tile;
+import com.android.settingslib.drawer.TileUtilsTest;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(SettingLibRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class SuggestionParserTest {
+
+ @Mock
+ private PackageManager mPackageManager;
+ private Context mContext;
+ private SuggestionParser mSuggestionParser;
+ private SuggestionParser.SuggestionCategory mSuggestioCategory;
+ private List<Tile> mSuggestionsBeforeDismiss;
+ private List<Tile> mSuggestionsAfterDismiss;
+ private SharedPreferences mPrefs;
+ private Tile mSuggestion;
+ private List<ResolveInfo> mInfo;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = spy(RuntimeEnvironment.application);
+ when(mContext.getPackageManager()).thenReturn(mPackageManager);
+ mPrefs = PreferenceManager.getDefaultSharedPreferences(mContext);
+ mSuggestion = new Tile();
+ mSuggestion.intent = new Intent("action");
+ mSuggestion.intent.setComponent(new ComponentName("pkg", "cls"));
+ mSuggestion.metaData = new Bundle();
+ mSuggestionParser = new SuggestionParser(
+ mContext, mPrefs, R.xml.suggestion_ordering, "0,0");
+ mSuggestioCategory = new SuggestionParser.SuggestionCategory();
+ mSuggestioCategory.category = "category1";
+ mSuggestioCategory.multiple = true;
+ mInfo = new ArrayList<>();
+ ResolveInfo info1 = TileUtilsTest.newInfo(true, "category1");
+ info1.activityInfo.packageName = "pkg";
+ ResolveInfo info2 = TileUtilsTest.newInfo(true, "category1");
+ info2.activityInfo.packageName = "pkg2";
+ mInfo.add(info1);
+ mInfo.add(info2);
+ when(mPackageManager.queryIntentActivitiesAsUser(
+ any(Intent.class), anyInt(), anyInt())).thenReturn(mInfo);
+ }
+
+ @Test
+ public void testDismissSuggestion_withoutSmartSuggestion() {
+ assertThat(mSuggestionParser.dismissSuggestion(mSuggestion, false)).isTrue();
+ }
+
+ @Test
+ public void testDismissSuggestion_withSmartSuggestion() {
+ assertThat(mSuggestionParser.dismissSuggestion(mSuggestion, true)).isFalse();
+ }
+
+ @Test
+ public void testGetSuggestions_withoutSmartSuggestions() {
+ readAndDismissSuggestion(false);
+ mSuggestionParser.readSuggestions(mSuggestioCategory, mSuggestionsAfterDismiss, false);
+ assertThat(mSuggestionsBeforeDismiss.size()).isEqualTo(2);
+ assertThat(mSuggestionsAfterDismiss.size()).isEqualTo(1);
+ assertThat(mSuggestionsBeforeDismiss.get(1)).isEqualTo(mSuggestionsAfterDismiss.get(0));
+ }
+
+ @Test
+ public void testGetSuggestions_withSmartSuggestions() {
+ readAndDismissSuggestion(true);
+ assertThat(mSuggestionsBeforeDismiss.size()).isEqualTo(2);
+ assertThat(mSuggestionsAfterDismiss.size()).isEqualTo(2);
+ assertThat(mSuggestionsBeforeDismiss).isEqualTo(mSuggestionsAfterDismiss);
+ }
+
+ private void readAndDismissSuggestion(boolean isSmartSuggestionEnabled) {
+ mSuggestionsBeforeDismiss = new ArrayList<Tile>();
+ mSuggestionsAfterDismiss = new ArrayList<Tile>();
+ mSuggestionParser.readSuggestions(
+ mSuggestioCategory, mSuggestionsBeforeDismiss, isSmartSuggestionEnabled);
+ if (mSuggestionParser.dismissSuggestion(
+ mSuggestionsBeforeDismiss.get(0), isSmartSuggestionEnabled)) {
+ mInfo.remove(0);
+ }
+ mSuggestionParser.readSuggestions(
+ mSuggestioCategory, mSuggestionsAfterDismiss, isSmartSuggestionEnabled);
+ }
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/CategoryKeyTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/CategoryKeyTest.java
index b209f4e..40353e7 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/CategoryKeyTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/CategoryKeyTest.java
@@ -56,12 +56,11 @@
allKeys.add(CategoryKey.CATEGORY_SECURITY);
allKeys.add(CategoryKey.CATEGORY_ACCOUNT);
allKeys.add(CategoryKey.CATEGORY_SYSTEM);
- allKeys.add(CategoryKey.CATEGORY_SYSTEM_INPUT);
allKeys.add(CategoryKey.CATEGORY_SYSTEM_LANGUAGE);
allKeys.add(CategoryKey.CATEGORY_SYSTEM_DEVELOPMENT);
// DO NOT REMOVE ANYTHING ABOVE
- assertThat(allKeys.size()).isEqualTo(14);
+ assertThat(allKeys.size()).isEqualTo(13);
}
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
index 021a96c..1683901 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
@@ -40,6 +40,7 @@
import com.android.settingslib.SuggestionParser;
import com.android.settingslib.TestConfig;
+import com.android.settingslib.drawer.TileUtilsTest;
import static org.mockito.Mockito.atLeastOnce;
import org.junit.Before;
@@ -179,7 +180,7 @@
assertThat(outTiles.size()).isEqualTo(1);
SuggestionParser parser = new SuggestionParser(mContext, null);
- parser.filterSuggestions(outTiles, 0);
+ parser.filterSuggestions(outTiles, 0, false);
assertThat(outTiles.size()).isEqualTo(0);
}
@@ -303,16 +304,16 @@
assertThat(outTiles.get(0).summary).isEqualTo("dynamic-summary");
}
- private ResolveInfo newInfo(boolean systemApp, String category) {
+ public static ResolveInfo newInfo(boolean systemApp, String category) {
return newInfo(systemApp, category, null);
}
- private ResolveInfo newInfo(boolean systemApp, String category, String keyHint) {
+ private static ResolveInfo newInfo(boolean systemApp, String category, String keyHint) {
return newInfo(systemApp, category, keyHint, null, null);
}
- private ResolveInfo newInfo(boolean systemApp, String category, String keyHint, String iconUri,
- String summaryUri) {
+ private static ResolveInfo newInfo(boolean systemApp, String category, String keyHint,
+ String iconUri, String summaryUri) {
ResolveInfo info = new ResolveInfo();
info.system = systemApp;
info.activityInfo = new ActivityInfo();
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index 8bbc8c9..4ddafac 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -1399,9 +1399,6 @@
Settings.Secure.NIGHT_DISPLAY_CUSTOM_END_TIME,
SecureSettingsProto.NIGHT_DISPLAY_CUSTOM_END_TIME);
dumpSetting(s, p,
- Settings.Secure.BRIGHTNESS_USE_TWILIGHT,
- SecureSettingsProto.BRIGHTNESS_USE_TWILIGHT);
- dumpSetting(s, p,
Settings.Secure.ENABLED_VR_LISTENERS,
SecureSettingsProto.ENABLED_VR_LISTENERS);
dumpSetting(s, p,
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_accessibility_button.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_accessibility_button.png
new file mode 100644
index 0000000..0615668
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_accessibility_button.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_accessibility_button_dark.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_accessibility_button_dark.png
new file mode 100644
index 0000000..839e5ed
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_accessibility_button_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_accessibility_button.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_accessibility_button.png
new file mode 100644
index 0000000..1480c865
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_accessibility_button.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_accessibility_button_dark.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_accessibility_button_dark.png
new file mode 100644
index 0000000..66e11fb
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_accessibility_button_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_accessibility_button.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_accessibility_button.png
new file mode 100644
index 0000000..d2fe0c3
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_accessibility_button.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_accessibility_button_dark.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_accessibility_button_dark.png
new file mode 100644
index 0000000..5923269
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_accessibility_button_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_accessibility_button.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_accessibility_button.png
new file mode 100644
index 0000000..d0196e5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_accessibility_button.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_accessibility_button_dark.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_accessibility_button_dark.png
new file mode 100644
index 0000000..d3a2b39
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_accessibility_button_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_accessibility_button.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_accessibility_button.png
new file mode 100644
index 0000000..726643c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_accessibility_button.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_accessibility_button_dark.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_accessibility_button_dark.png
new file mode 100644
index 0000000..31078f6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_accessibility_button_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/layout/menu_ime.xml b/packages/SystemUI/res/layout/menu_ime.xml
index 5e85ba0..6bd79a4 100644
--- a/packages/SystemUI/res/layout/menu_ime.xml
+++ b/packages/SystemUI/res/layout/menu_ime.xml
@@ -39,4 +39,13 @@
android:contentDescription="@string/accessibility_ime_switch_button"
android:scaleType="centerInside"
/>
+ <com.android.systemui.statusbar.policy.KeyButtonView
+ android:id="@+id/accessibility_button"
+ android:layout_width="@dimen/navigation_extra_key_width"
+ android:layout_height="match_parent"
+ android:layout_marginEnd="2dp"
+ android:visibility="invisible"
+ android:contentDescription="@string/accessibility_accessibility_button"
+ android:scaleType="centerInside"
+ />
</FrameLayout>
diff --git a/packages/SystemUI/res/layout/super_status_bar.xml b/packages/SystemUI/res/layout/super_status_bar.xml
index 92a9da9..c2686f8 100644
--- a/packages/SystemUI/res/layout/super_status_bar.xml
+++ b/packages/SystemUI/res/layout/super_status_bar.xml
@@ -73,7 +73,7 @@
<include layout="@layout/status_bar_expanded"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:visibility="gone" />
+ android:visibility="invisible" />
<com.android.systemui.statusbar.ScrimView android:id="@+id/scrim_in_front"
android:layout_width="match_parent"
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 363b3e2..2cc2621 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -207,6 +207,8 @@
<string name="accessibility_home">Home</string>
<!-- Content description of the menu button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_menu">Menu</string>
+ <!-- Content description of the accessibility button in the navigation bar (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_accessibility_button">Accessibility</string>
<!-- Content description of the recents button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_recent">Overview</string>
<!-- Content description of the search button for accessibility. [CHAR LIMIT=NONE] -->
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
index a9ac2d9..27070ed 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -87,6 +87,7 @@
* above.
*/
private final Class<?>[] SERVICES_PER_USER = new Class[] {
+ Dependency.class,
Recents.class,
PipUI.class
};
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
index aa22618..7c15096 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
@@ -16,6 +16,7 @@
package com.android.systemui.doze;
+import android.app.AlarmManager;
import android.app.Application;
import android.app.PendingIntent;
import android.content.Context;
@@ -25,10 +26,7 @@
import android.os.SystemClock;
import com.android.internal.hardware.AmbientDisplayConfiguration;
-import com.android.systemui.SystemUI;
import com.android.systemui.SystemUIApplication;
-import com.android.systemui.plugins.PluginListener;
-import com.android.systemui.plugins.PluginManager;
import com.android.systemui.plugins.doze.DozeProvider;
import com.android.systemui.statusbar.phone.DozeParameters;
@@ -45,6 +43,7 @@
Context context = dozeService;
SensorManager sensorManager = context.getSystemService(SensorManager.class);
PowerManager powerManager = context.getSystemService(PowerManager.class);
+ AlarmManager alarmManager = context.getSystemService(AlarmManager.class);
DozeHost host = getHost(dozeService);
AmbientDisplayConfiguration config = new AmbientDisplayConfiguration(context);
@@ -57,7 +56,7 @@
machine.setParts(new DozeMachine.Part[]{
createDozeTriggers(context, sensorManager, host, config, params, handler, wakeLock,
machine),
- createDozeUi(context, host, wakeLock, machine),
+ createDozeUi(context, host, wakeLock, machine, handler, alarmManager),
});
return machine;
@@ -72,7 +71,7 @@
}
private DozeMachine.Part createDozeUi(Context context, DozeHost host, WakeLock wakeLock,
- DozeMachine machine) {
+ DozeMachine machine, Handler handler, AlarmManager alarmManager) {
if (mDozePlugin != null) {
DozeProvider.DozeUi dozeUi = mDozePlugin.provideDozeUi(context,
pluginMachine(context, machine, host),
@@ -82,7 +81,7 @@
pluginState(newState));
};
} else {
- return new DozeUi(context, machine, wakeLock, host);
+ return new DozeUi(context, alarmManager, machine, wakeLock, host, handler);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java b/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java
index 00d2298..f3fb1ef 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java
@@ -30,15 +30,12 @@
void stopDozing();
void dozeTimeTick();
boolean isPowerSaveActive();
- boolean isNotificationLightOn();
boolean isPulsingBlocked();
void startPendingIntentDismissingKeyguard(PendingIntent intent);
interface Callback {
- default void onNewNotifications() {}
default void onNotificationHeadsUp() {}
- default void onNotificationLight(boolean on) {}
default void onPowerSaveChanged(boolean active) {}
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
index 95e49ce..76e0283 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
@@ -16,7 +16,13 @@
package com.android.systemui.doze;
+import android.app.AlarmManager;
import android.content.Context;
+import android.os.Handler;
+import android.os.SystemClock;
+
+import java.util.Calendar;
+import java.util.GregorianCalendar;
/**
* The policy controlling doze.
@@ -24,16 +30,25 @@
public class DozeUi implements DozeMachine.Part {
private final Context mContext;
+ private final AlarmManager mAlarmManager;
private final DozeHost mHost;
- private DozeFactory.WakeLock mWakeLock;
- private DozeMachine mMachine;
+ private final Handler mHandler;
+ private final DozeFactory.WakeLock mWakeLock;
+ private final DozeMachine mMachine;
+ private final AlarmManager.OnAlarmListener mTimeTick;
- public DozeUi(Context context, DozeMachine machine, DozeFactory.WakeLock wakeLock,
- DozeHost host) {
+ private boolean mTimeTickScheduled = false;
+
+ public DozeUi(Context context, AlarmManager alarmManager, DozeMachine machine,
+ DozeFactory.WakeLock wakeLock, DozeHost host, Handler handler) {
mContext = context;
+ mAlarmManager = alarmManager;
mMachine = machine;
mWakeLock = wakeLock;
mHost = host;
+ mHandler = handler;
+
+ mTimeTick = this::onTimeTick;
}
private void pulseWhileDozing(int reason) {
@@ -54,6 +69,12 @@
@Override
public void transitionTo(DozeMachine.State oldState, DozeMachine.State newState) {
switch (newState) {
+ case DOZE_AOD:
+ scheduleTimeTick();
+ break;
+ case DOZE:
+ unscheduleTimeTick();
+ break;
case DOZE_REQUEST_PULSE:
pulseWhileDozing(DozeLog.PULSE_REASON_NOTIFICATION /* TODO */);
break;
@@ -62,7 +83,52 @@
break;
case FINISH:
mHost.stopDozing();
+ unscheduleTimeTick();
break;
}
}
+
+ private void scheduleTimeTick() {
+ if (mTimeTickScheduled) {
+ return;
+ }
+
+ long delta = roundToNextMinute(System.currentTimeMillis()) - System.currentTimeMillis();
+ mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,
+ SystemClock.elapsedRealtime() + delta, "doze_time_tick", mTimeTick, mHandler);
+
+ mTimeTickScheduled = true;
+ }
+
+ private void unscheduleTimeTick() {
+ if (!mTimeTickScheduled) {
+ return;
+ }
+ mAlarmManager.cancel(mTimeTick);
+ }
+
+ private long roundToNextMinute(long timeInMillis) {
+ Calendar calendar = GregorianCalendar.getInstance();
+ calendar.setTimeInMillis(timeInMillis);
+ calendar.set(Calendar.MILLISECOND, 0);
+ calendar.set(Calendar.SECOND, 0);
+ calendar.add(Calendar.MINUTE, 1);
+
+ return calendar.getTimeInMillis();
+ }
+
+ private void onTimeTick() {
+ if (!mTimeTickScheduled) {
+ // Alarm was canceled, but we still got the callback. Ignore.
+ return;
+ }
+
+ mHost.dozeTimeTick();
+
+ // Keep wakelock until a frame has been pushed.
+ mHandler.post(mWakeLock.wrap(() -> {}));
+
+ mTimeTickScheduled = false;
+ scheduleTimeTick();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
index 3afbc35..dea56aa1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
@@ -237,6 +237,8 @@
i.setPackage(mComponent.getPackageName());
i = resolveIntent(i);
if (i != null) {
+ i.putExtra(TileService.EXTRA_COMPONENT, mComponent);
+ i.putExtra(TileService.EXTRA_STATE, mTile.getState());
return i;
}
return new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).setData(
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
index 70f8109..dab5967 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
@@ -16,6 +16,9 @@
package com.android.systemui.qs.tiles;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.UserManager;
@@ -37,6 +40,9 @@
/** Quick settings tile: Hotspot **/
public class HotspotTile extends QSTile<QSTile.AirplaneBooleanState> {
+ static final Intent TETHER_SETTINGS = new Intent().setComponent(new ComponentName(
+ "com.android.settings", "com.android.settings.TetherSettings"));
+
private final AnimationIcon mEnable =
new AnimationIcon(R.drawable.ic_hotspot_enable_animation,
R.drawable.ic_hotspot_disable);
@@ -94,7 +100,7 @@
@Override
public Intent getLongClickIntent() {
- return new Intent(Settings.ACTION_WIRELESS_SETTINGS);
+ return new Intent(TETHER_SETTINGS);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Recents.java b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
index 9157e33..e635162 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Recents.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
@@ -205,7 +205,6 @@
sTaskLoader = new RecentsTaskLoader(mContext);
sConfiguration = new RecentsConfiguration(mContext);
mHandler = new Handler();
- getComponent(CommandQueue.class).addCallbacks(this);
UiModeManager uiModeManager = (UiModeManager) mContext.
getSystemService(Context.UI_MODE_SERVICE);
if (uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION) {
@@ -234,6 +233,7 @@
if (sSystemServicesProxy.isSystemUser(processUser)) {
// For the system user, initialize an instance of the interface that we can pass to the
// secondary user
+ getComponent(CommandQueue.class).addCallbacks(this);
mSystemToUserCallbacks = new RecentsSystemUser(mContext, mImpl);
} else {
// For the secondary user, bind to the primary user's service to get a persistent
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index 609e3fb..8091199 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -76,6 +76,7 @@
import com.android.systemui.recents.views.TaskStackViewScroller;
import com.android.systemui.recents.views.TaskViewHeader;
import com.android.systemui.recents.views.TaskViewTransform;
+import com.android.systemui.recents.views.grid.TaskGridLayoutAlgorithm;
import com.android.systemui.stackdivider.DividerView;
import com.android.systemui.statusbar.phone.NavigationBarGestureHelper;
import com.android.systemui.statusbar.phone.StatusBar;
@@ -637,10 +638,21 @@
stackLayout.initialize(displayRect, windowRect, mTaskStackBounds,
TaskStackLayoutAlgorithm.StackState.getStackStateForStack(stack));
mDummyStackView.setTasks(stack, false /* allowNotifyStackChanges */);
+ // Get the width of a task view so that we know how wide to draw the header bar.
+ int taskViewWidth = 0;
+ if (mDummyStackView.useGridLayout()) {
+ TaskGridLayoutAlgorithm gridLayout = mDummyStackView.getGridAlgorithm();
+ gridLayout.initialize(windowRect);
+ taskViewWidth = (int) gridLayout.getTransform(0 /* taskIndex */,
+ stack.getTaskCount(), new TaskViewTransform(), stackLayout).rect.width();
+ } else {
+ Rect taskViewBounds = stackLayout.getUntransformedTaskViewBounds();
+ if (!taskViewBounds.isEmpty()) {
+ taskViewWidth = taskViewBounds.width();
+ }
+ }
- Rect taskViewBounds = stackLayout.getUntransformedTaskViewBounds();
- if (!taskViewBounds.isEmpty()) {
- int taskViewWidth = taskViewBounds.width();
+ if (taskViewWidth > 0) {
synchronized (mHeaderBarLock) {
if (mHeaderBar.getMeasuredWidth() != taskViewWidth ||
mHeaderBar.getMeasuredHeight() != mTaskBarHeight) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index fb94c7e..0160eb7 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -96,6 +96,7 @@
import com.android.systemui.recents.model.TaskStack;
import com.android.systemui.recents.views.grid.GridTaskView;
+import com.android.systemui.recents.views.grid.TaskGridLayoutAlgorithm;
import com.android.systemui.recents.views.grid.TaskViewFocusFrame;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
@@ -447,6 +448,11 @@
return mLayoutAlgorithm;
}
+ /** Returns the grid algorithm for this task stack. */
+ public TaskGridLayoutAlgorithm getGridAlgorithm() {
+ return mLayoutAlgorithm.mTaskGridLayoutAlgorithm;
+ }
+
/**
* Returns the touch handler for this task stack.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
index b9a0f74..0b09acc 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
@@ -72,6 +72,10 @@
return mMinimized;
}
+ public boolean isHomeStackResizable() {
+ return mHomeStackResizable;
+ }
+
private void addDivider(Configuration configuration) {
mView = (DividerView)
LayoutInflater.from(mContext).inflate(R.layout.docked_stack_divider, null);
@@ -119,6 +123,7 @@
mView.post(new Runnable() {
@Override
public void run() {
+ mHomeStackResizable = isHomeStackResizable;
if (mMinimized != minimized) {
mMinimized = minimized;
updateTouchable();
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index 49035ba..6f59fe2 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -1241,7 +1241,8 @@
public final void onBusEvent(UndockingTaskEvent undockingTaskEvent) {
int dockSide = mWindowManagerProxy.getDockSide();
- if (dockSide != WindowManager.DOCKED_INVALID && !mDockedStackMinimized) {
+ if (dockSide != WindowManager.DOCKED_INVALID && (mHomeStackResizable
+ || !mDockedStackMinimized)) {
startDragging(false /* animate */, false /* touching */);
SnapTarget target = dockSideTopLeft(dockSide)
? mSnapAlgorithm.getDismissEndTarget()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
index 4b1baa2..0bd6491 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
@@ -105,7 +105,7 @@
private boolean mDimmed;
private boolean mDark;
- private int mBgTint = NO_COLOR;
+ protected int mBgTint = NO_COLOR;
private float mBgAlpha = 1f;
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 477701c..9245df0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -63,9 +63,6 @@
private static final int MSG_SET_WINDOW_STATE = 12 << MSG_SHIFT;
private static final int MSG_SHOW_RECENT_APPS = 13 << MSG_SHIFT;
private static final int MSG_HIDE_RECENT_APPS = 14 << MSG_SHIFT;
- private static final int MSG_BUZZ_BEEP_BLINKED = 15 << MSG_SHIFT;
- private static final int MSG_NOTIFICATION_LIGHT_OFF = 16 << MSG_SHIFT;
- private static final int MSG_NOTIFICATION_LIGHT_PULSE = 17 << MSG_SHIFT;
private static final int MSG_SHOW_SCREEN_PIN_REQUEST = 18 << MSG_SHIFT;
private static final int MSG_APP_TRANSITION_PENDING = 19 << MSG_SHIFT;
private static final int MSG_APP_TRANSITION_CANCELLED = 20 << MSG_SHIFT;
@@ -121,9 +118,6 @@
default void toggleKeyboardShortcutsMenu(int deviceId) { }
default void cancelPreloadRecentApps() { }
default void setWindowState(int window, int state) { }
- default void buzzBeepBlinked() { }
- default void notificationLightOff() { }
- default void notificationLightPulse(int argb, int onMillis, int offMillis) { }
default void showScreenPinningRequest(int taskId) { }
default void appTransitionPending() { }
default void appTransitionCancelled() { }
@@ -313,26 +307,6 @@
}
}
- public void buzzBeepBlinked() {
- synchronized (mLock) {
- mHandler.removeMessages(MSG_BUZZ_BEEP_BLINKED);
- mHandler.sendEmptyMessage(MSG_BUZZ_BEEP_BLINKED);
- }
- }
-
- public void notificationLightOff() {
- synchronized (mLock) {
- mHandler.sendEmptyMessage(MSG_NOTIFICATION_LIGHT_OFF);
- }
- }
-
- public void notificationLightPulse(int argb, int onMillis, int offMillis) {
- synchronized (mLock) {
- mHandler.obtainMessage(MSG_NOTIFICATION_LIGHT_PULSE, onMillis, offMillis, argb)
- .sendToTarget();
- }
- }
-
public void showScreenPinningRequest(int taskId) {
synchronized (mLock) {
mHandler.obtainMessage(MSG_SHOW_SCREEN_PIN_REQUEST, taskId, 0, null)
@@ -524,21 +498,6 @@
mCallbacks.get(i).setWindowState(msg.arg1, msg.arg2);
}
break;
- case MSG_BUZZ_BEEP_BLINKED:
- for (int i = 0; i < mCallbacks.size(); i++) {
- mCallbacks.get(i).buzzBeepBlinked();
- }
- break;
- case MSG_NOTIFICATION_LIGHT_OFF:
- for (int i = 0; i < mCallbacks.size(); i++) {
- mCallbacks.get(i).notificationLightOff();
- }
- break;
- case MSG_NOTIFICATION_LIGHT_PULSE:
- for (int i = 0; i < mCallbacks.size(); i++) {
- mCallbacks.get(i).notificationLightPulse((Integer) msg.obj, msg.arg1, msg.arg2);
- }
- break;
case MSG_SHOW_SCREEN_PIN_REQUEST:
for (int i = 0; i < mCallbacks.size(); i++) {
mCallbacks.get(i).showScreenPinningRequest(msg.arg1);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 85e2bd6..2e9c7fd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -1880,14 +1880,14 @@
} else if (isUserLocked()) {
return mChildrenContainer.getGroupExpandFraction();
}
- } else if (isColorized()) {
+ } else if (isColorized() && (!mIsLowPriority || isExpanded())) {
return -1.0f;
}
return 0.0f;
}
private boolean isColorized() {
- return mIsColorized;
+ return mIsColorized && mBgTint != NO_COLOR;
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index e8e9d4e..2425076 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -68,6 +68,7 @@
private float mMaxShelfEnd;
private int mRelativeOffset;
private boolean mInteractive;
+ private boolean mAnimationsEnabled = true;
public NotificationShelf(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -388,12 +389,13 @@
View rowIcon = row.getNotificationIcon();
float notificationIconPosition = row.getTranslationY() + row.getContentTranslation();
- if (usingLinearInterpolation) {
+ boolean stayingInShelf = row.isInShelf() && !row.isTransformingIntoShelf();
+ if (usingLinearInterpolation && !stayingInShelf) {
// If we interpolate from the notification position, this might lead to a slightly
// odd interpolation, since the notification position changes as well. Let's interpolate
// from a fixed distance. We can only do this if we don't animate and the icon is
// always in the interpolated positon.
- notificationIconPosition = mMaxShelfEnd - getIntrinsicHeight() - iconTransformDistance;
+ notificationIconPosition = getTranslationY() - iconTransformDistance;
}
float notificationIconSize = 0.0f;
int iconTopPadding;
@@ -426,7 +428,7 @@
iconState.hidden = transitionAmount == 0.0f;
iconState.alpha = alpha;
iconState.yTranslation = iconYTranslation;
- if (row.isInShelf() && !row.isTransformingIntoShelf()) {
+ if (stayingInShelf) {
iconState.iconAppearAmount = 1.0f;
iconState.alpha = 1.0f;
iconState.scaleX = 1.0f;
@@ -573,6 +575,15 @@
mMaxShelfEnd = maxShelfEnd;
}
+ public void setAnimationsEnabled(boolean enabled) {
+ mAnimationsEnabled = enabled;
+ mCollapsedIcons.setAnimationsEnabled(enabled);
+ if (!enabled) {
+ // we need to wait with enabling the animations until the first frame has passed
+ mShelfIcons.setAnimationsEnabled(false);
+ }
+ }
+
private class ShelfState extends ExpandableViewState {
private float openedAmount;
private boolean hasItemsInStableShelf;
@@ -585,6 +596,7 @@
setOpenedAmount(openedAmount);
updateAppearance();
setHasItemsInStableShelf(hasItemsInStableShelf);
+ mShelfIcons.setAnimationsEnabled(mAnimationsEnabled);
}
@Override
@@ -594,6 +606,7 @@
setOpenedAmount(openedAmount);
updateAppearance();
setHasItemsInStableShelf(hasItemsInStableShelf);
+ mShelfIcons.setAnimationsEnabled(mAnimationsEnabled);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationCustomViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationCustomViewWrapper.java
index 03c7325..e5f32df 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationCustomViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationCustomViewWrapper.java
@@ -105,6 +105,11 @@
}
@Override
+ protected boolean shouldClearBackgroundOnReapply() {
+ return false;
+ }
+
+ @Override
public int getCustomBackgroundColor() {
int customBackgroundColor = super.getCustomBackgroundColor();
if (customBackgroundColor == 0 && mShowingLegacyBackground) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
index 836482a..5f5e1e4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
@@ -93,7 +93,9 @@
public void notifyContentUpdated(StatusBarNotification notification, boolean isLowPriority) {
mDarkInitialized = false;
Drawable background = mView.getBackground();
- mBackgroundColor = 0;
+ if (shouldClearBackgroundOnReapply()) {
+ mBackgroundColor = 0;
+ }
if (background instanceof ColorDrawable) {
mBackgroundColor = ((ColorDrawable) background).getColor();
mView.setBackground(null);
@@ -101,6 +103,10 @@
mShouldInvertDark = mBackgroundColor == 0 || isColorLight(mBackgroundColor);
}
+ protected boolean shouldClearBackgroundOnReapply() {
+ return true;
+ }
+
private boolean isColorLight(int backgroundColor) {
return Color.alpha(backgroundColor) == 0
|| ColorUtils.calculateLuminance(backgroundColor) > 0.5;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
index 62b536e..808cd21 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -23,6 +23,7 @@
import static com.android.systemui.statusbar.phone.StatusBar.DEBUG_WINDOW_STATE;
import static com.android.systemui.statusbar.phone.StatusBar.dumpBarTransitions;
+import android.accessibilityservice.AccessibilityServiceInfo;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityManagerNative;
@@ -79,6 +80,7 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.util.List;
import java.util.Locale;
/**
@@ -101,7 +103,7 @@
private int mNavigationIconHints = 0;
private int mNavigationBarMode;
- protected AccessibilityManager mAccessibilityManager;
+ private AccessibilityManager mAccessibilityManager;
private int mDisabledFlags1;
private StatusBar mStatusBar;
@@ -132,6 +134,8 @@
mDivider = SysUiServiceProvider.getComponent(getContext(), Divider.class);
mWindowManager = getContext().getSystemService(WindowManager.class);
mAccessibilityManager = getContext().getSystemService(AccessibilityManager.class);
+ mAccessibilityManager.addAccessibilityServicesStateChangeListener(
+ this::updateAccessibilityServicesState);
if (savedInstanceState != null) {
mDisabledFlags1 = savedInstanceState.getInt(EXTRA_DISABLE_STATE, 0);
}
@@ -149,6 +153,8 @@
public void onDestroy() {
super.onDestroy();
mCommandQueue.removeCallbacks(this);
+ mAccessibilityManager.removeAccessibilityServicesStateChangeListener(
+ this::updateAccessibilityServicesState);
try {
WindowManagerGlobal.getWindowManagerService()
.removeRotationWatcher(mRotationWatcher);
@@ -402,6 +408,10 @@
ButtonDispatcher homeButton = mNavigationBarView.getHomeButton();
homeButton.setOnTouchListener(this::onHomeTouch);
homeButton.setOnLongClickListener(this::onHomeLongClick);
+
+ ButtonDispatcher accessibilityButton = mNavigationBarView.getAccessibilityButton();
+ accessibilityButton.setOnClickListener(this::onAccessibilityClick);
+ accessibilityButton.setOnLongClickListener(this::onAccessibilityLongClick);
}
private boolean onHomeTouch(View v, MotionEvent event) {
@@ -553,6 +563,34 @@
MetricsEvent.ACTION_WINDOW_UNDOCK_LONGPRESS);
}
+ private void onAccessibilityClick(View v) {
+ mAccessibilityManager.notifyAccessibilityButtonClicked();
+ }
+
+ private boolean onAccessibilityLongClick(View v) {
+ // TODO(b/34720082): Target service selection via long click
+ android.widget.Toast.makeText(getContext(), "Service selection coming soon...",
+ android.widget.Toast.LENGTH_LONG).show();
+ return true;
+ }
+
+ private void updateAccessibilityServicesState() {
+ final List<AccessibilityServiceInfo> services =
+ mAccessibilityManager.getEnabledAccessibilityServiceList(
+ AccessibilityServiceInfo.FEEDBACK_ALL_MASK);
+ int requestingServices = 0;
+ for (int i = services.size() - 1; i >= 0; --i) {
+ AccessibilityServiceInfo info = services.get(i);
+ if ((info.flags & AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON) != 0) {
+ requestingServices++;
+ }
+ }
+
+ final boolean showAccessibilityButton = requestingServices >= 1;
+ final boolean targetSelection = requestingServices >= 2;
+ mNavigationBarView.setAccessibilityButtonState(showAccessibilityButton, targetSelection);
+ }
+
// ----- Methods that StatusBar talks to (should be minimized) -----
public void setLightBarController(LightBarController lightBarController) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index dced747..5d13289 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -78,6 +78,8 @@
private int mCurrentRotation = -1;
boolean mShowMenu;
+ boolean mShowAccessibilityButton;
+ boolean mLongClickableAccessibilityButton;
int mDisabledFlags = 0;
int mNavigationIconHints = 0;
@@ -89,6 +91,7 @@
private KeyButtonDrawable mDockedIcon;
private KeyButtonDrawable mImeIcon;
private KeyButtonDrawable mMenuIcon;
+ private KeyButtonDrawable mAccessibilityIcon;
private GestureHelper mGestureHelper;
private DeadZone mDeadZone;
@@ -202,6 +205,9 @@
mVertical = false;
mShowMenu = false;
+ mShowAccessibilityButton = false;
+ mLongClickableAccessibilityButton = false;
+
mConfiguration = new Configuration();
mConfiguration.updateFrom(context.getResources().getConfiguration());
updateIcons(context, Configuration.EMPTY, mConfiguration);
@@ -213,6 +219,8 @@
mButtonDispatchers.put(R.id.recent_apps, new ButtonDispatcher(R.id.recent_apps));
mButtonDispatchers.put(R.id.menu, new ButtonDispatcher(R.id.menu));
mButtonDispatchers.put(R.id.ime_switcher, new ButtonDispatcher(R.id.ime_switcher));
+ mButtonDispatchers.put(R.id.accessibility_button,
+ new ButtonDispatcher(R.id.accessibility_button));
}
public BarTransitions getBarTransitions() {
@@ -287,6 +295,10 @@
return mButtonDispatchers.get(R.id.ime_switcher);
}
+ public ButtonDispatcher getAccessibilityButton() {
+ return mButtonDispatchers.get(R.id.accessibility_button);
+ }
+
public SparseArray<ButtonDispatcher> getButtonDispatchers() {
return mButtonDispatchers;
}
@@ -320,6 +332,8 @@
mRecentIcon = getDrawable(ctx,
R.drawable.ic_sysbar_recent, R.drawable.ic_sysbar_recent_dark);
mMenuIcon = getDrawable(ctx, R.drawable.ic_sysbar_menu, R.drawable.ic_sysbar_menu_dark);
+ mAccessibilityIcon = getDrawable(ctx, R.drawable.ic_sysbar_accessibility_button,
+ R.drawable.ic_sysbar_accessibility_button_dark);
Context darkContext = new ContextThemeWrapper(ctx, R.style.DualToneDarkTheme);
Context lightContext = new ContextThemeWrapper(ctx, R.style.DualToneLightTheme);
@@ -411,6 +425,9 @@
setMenuVisibility(mShowMenu, true);
getMenuButton().setImageDrawable(mMenuIcon);
+ setAccessibilityButtonState(mShowAccessibilityButton, mLongClickableAccessibilityButton);
+ getAccessibilityButton().setImageDrawable(mAccessibilityIcon);
+
setDisabledFlags(mDisabledFlags, true);
mBarTransitions.reapplyDarkIntensity();
@@ -517,13 +534,25 @@
mShowMenu = show;
- // Only show Menu if IME switcher not shown.
- final boolean shouldShow = mShowMenu &&
+ // Only show Menu if IME switcher and Accessibility button not shown.
+ final boolean shouldShow = mShowMenu && !mShowAccessibilityButton &&
((mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_IME_SHOWN) == 0);
getMenuButton().setVisibility(shouldShow ? View.VISIBLE : View.INVISIBLE);
}
+ public void setAccessibilityButtonState(final boolean visible, final boolean longClickable) {
+ mShowAccessibilityButton = visible;
+ mLongClickableAccessibilityButton = longClickable;
+ if (visible) {
+ // Accessibility button overrides Menu button.
+ setMenuVisibility(false, true);
+ }
+
+ getAccessibilityButton().setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
+ getAccessibilityButton().setLongClickable(longClickable);
+ }
+
@Override
public void onFinishInflate() {
mNavigationInflaterView = (NavigationBarInflaterView) findViewById(
@@ -814,6 +843,7 @@
dumpButton(pw, "home", getHomeButton());
dumpButton(pw, "rcnt", getRecentsButton());
dumpButton(pw, "menu", getMenuButton());
+ dumpButton(pw, "a11y", getAccessibilityButton());
pw.println(" }");
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
index c25a45c..571ae26 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
@@ -104,6 +104,7 @@
private float mOpenedAmount = 0.0f;
private float mVisualOverflowAdaption;
private boolean mDisallowNextAnimation;
+ private boolean mAnimationsEnabled = true;
public NotificationIconContainer(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -255,7 +256,7 @@
iconState.visibleState = StatusBarIconView.STATE_ICON;
if (firstOverflowIndex == -1 && (isAmbient
|| (translationX >= (noOverflowAfter ? layoutEnd - mIconSize : overflowStart)))) {
- firstOverflowIndex = noOverflowAfter ? i - 1 : i;
+ firstOverflowIndex = noOverflowAfter && !isAmbient ? i - 1 : i;
int totalDotLength = mStaticDotRadius * 6 + 2 * mDotPadding;
visualOverflowStart = overflowStart + mIconSize * (1 + OVERFLOW_EARLY_AMOUNT)
- totalDotLength / 2
@@ -422,6 +423,20 @@
return mIconSize;
}
+ public void setAnimationsEnabled(boolean enabled) {
+ if (!enabled && mAnimationsEnabled) {
+ for (int i = 0; i < getChildCount(); i++) {
+ View child = getChildAt(i);
+ ViewState childState = mIconStates.get(child);
+ if (childState != null) {
+ childState.cancelAnimations(child);
+ childState.applyToView(child);
+ }
+ }
+ }
+ mAnimationsEnabled = enabled;
+ }
+
public class IconState extends ViewState {
public float iconAppearAmount = 1.0f;
public float clampedAppearAmount = 1.0f;
@@ -438,52 +453,59 @@
StatusBarIconView icon = (StatusBarIconView) view;
boolean animate = false;
AnimationProperties animationProperties = null;
- if (justAdded) {
- super.applyToView(icon);
- icon.setAlpha(0.0f);
- icon.setVisibleState(StatusBarIconView.STATE_HIDDEN, false /* animate */);
- animationProperties = ADD_ICON_PROPERTIES;
- animate = true;
- } else if (visibleState != icon.getVisibleState()) {
- animationProperties = DOT_ANIMATION_PROPERTIES;
- animate = true;
- }
- if (!animate && mAddAnimationStartIndex >= 0
- && indexOfChild(view) >= mAddAnimationStartIndex
- && (icon.getVisibleState() != StatusBarIconView.STATE_HIDDEN
- || visibleState != StatusBarIconView.STATE_HIDDEN)) {
- animationProperties = DOT_ANIMATION_PROPERTIES;
- animate = true;
- }
- if (needsCannedAnimation) {
- AnimationFilter animationFilter = mTempProperties.getAnimationFilter();
- animationFilter.reset();
- animationFilter.combineFilter(ICON_ANIMATION_PROPERTIES.getAnimationFilter());
- mTempProperties.resetCustomInterpolators();
- mTempProperties.combineCustomInterpolators(ICON_ANIMATION_PROPERTIES);
- if (animationProperties != null) {
- animationFilter.combineFilter(animationProperties.getAnimationFilter());
- mTempProperties.combineCustomInterpolators(animationProperties);
+ boolean animationsAllowed = mAnimationsEnabled && !mDisallowNextAnimation;
+ if (animationsAllowed) {
+ if (justAdded) {
+ super.applyToView(icon);
+ if (iconAppearAmount != 0.0f) {
+ icon.setAlpha(0.0f);
+ icon.setVisibleState(StatusBarIconView.STATE_HIDDEN,
+ false /* animate */);
+ animationProperties = ADD_ICON_PROPERTIES;
+ animate = true;
+ }
+ } else if (visibleState != icon.getVisibleState()) {
+ animationProperties = DOT_ANIMATION_PROPERTIES;
+ animate = true;
}
- animationProperties = mTempProperties;
- animationProperties.setDuration(CANNED_ANIMATION_DURATION);
- animate = true;
- mCannedAnimationStartIndex = indexOfChild(view);
+ if (!animate && mAddAnimationStartIndex >= 0
+ && indexOfChild(view) >= mAddAnimationStartIndex
+ && (icon.getVisibleState() != StatusBarIconView.STATE_HIDDEN
+ || visibleState != StatusBarIconView.STATE_HIDDEN)) {
+ animationProperties = DOT_ANIMATION_PROPERTIES;
+ animate = true;
+ }
+ if (needsCannedAnimation) {
+ AnimationFilter animationFilter = mTempProperties.getAnimationFilter();
+ animationFilter.reset();
+ animationFilter.combineFilter(
+ ICON_ANIMATION_PROPERTIES.getAnimationFilter());
+ mTempProperties.resetCustomInterpolators();
+ mTempProperties.combineCustomInterpolators(ICON_ANIMATION_PROPERTIES);
+ if (animationProperties != null) {
+ animationFilter.combineFilter(animationProperties.getAnimationFilter());
+ mTempProperties.combineCustomInterpolators(animationProperties);
+ }
+ animationProperties = mTempProperties;
+ animationProperties.setDuration(CANNED_ANIMATION_DURATION);
+ animate = true;
+ mCannedAnimationStartIndex = indexOfChild(view);
+ }
+ if (!animate && mCannedAnimationStartIndex >= 0
+ && indexOfChild(view) > mCannedAnimationStartIndex
+ && (icon.getVisibleState() != StatusBarIconView.STATE_HIDDEN
+ || visibleState != StatusBarIconView.STATE_HIDDEN)) {
+ AnimationFilter animationFilter = mTempProperties.getAnimationFilter();
+ animationFilter.reset();
+ animationFilter.animateX();
+ mTempProperties.resetCustomInterpolators();
+ animationProperties = mTempProperties;
+ animationProperties.setDuration(CANNED_ANIMATION_DURATION);
+ animate = true;
+ }
}
- if (!animate && mCannedAnimationStartIndex >= 0
- && indexOfChild(view) > mCannedAnimationStartIndex
- && (icon.getVisibleState() != StatusBarIconView.STATE_HIDDEN
- || visibleState != StatusBarIconView.STATE_HIDDEN)) {
- AnimationFilter animationFilter = mTempProperties.getAnimationFilter();
- animationFilter.reset();
- animationFilter.animateX();
- mTempProperties.resetCustomInterpolators();
- animationProperties = mTempProperties;
- animationProperties.setDuration(CANNED_ANIMATION_DURATION);
- animate = true;
- }
- icon.setVisibleState(visibleState);
- if (animate && !mDisallowNextAnimation) {
+ icon.setVisibleState(visibleState, animationsAllowed);
+ if (animate) {
animateTo(icon, animationProperties);
} else {
super.applyToView(view);
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 638c12f..54c67d2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -603,8 +603,6 @@
new ArraySet<>();
private long mLastVisibilityReportUptimeMs;
- private final ShadeUpdates mShadeUpdates = new ShadeUpdates();
-
private Runnable mLaunchTransitionEndRunnable;
protected boolean mLaunchTransitionFadingAway;
private ExpandableNotificationRow mDraggedDownRow;
@@ -1501,7 +1499,7 @@
ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT, null, metricsDockAction);
} else {
Divider divider = getComponent(Divider.class);
- if (divider != null && divider.isMinimized()) {
+ if (divider != null && divider.isMinimized() && !divider.isHomeStackResizable()) {
// Undocking from the minimized state is not supported
return false;
} else {
@@ -1894,7 +1892,6 @@
updateEmptyShadeView();
updateQsExpansionEnabled();
- mShadeUpdates.check();
// Let's also update the icons
mIconController.updateNotificationIcons(mNotificationData);
@@ -3071,24 +3068,6 @@
}
@Override // CommandQueue
- public void buzzBeepBlinked() {
- }
-
- @Override
- public void notificationLightOff() {
- if (mDozeServiceHost != null) {
- mDozeServiceHost.fireNotificationLight(false);
- }
- }
-
- @Override
- public void notificationLightPulse(int argb, int onMillis, int offMillis) {
- if (mDozeServiceHost != null) {
- mDozeServiceHost.fireNotificationLight(true);
- }
- }
-
- @Override // CommandQueue
public void setSystemUiVisibility(int vis, int fullscreenStackVis, int dockedStackVis,
int mask, Rect fullscreenStackBounds, Rect dockedStackBounds) {
final int oldVal = mSystemUiVisibility;
@@ -5059,44 +5038,9 @@
return mStatusBarKeyguardViewManager.isShowing();
}
- private final class ShadeUpdates {
- private final ArraySet<String> mVisibleNotifications = new ArraySet<String>();
- private final ArraySet<String> mNewVisibleNotifications = new ArraySet<String>();
-
- public void check() {
- mNewVisibleNotifications.clear();
- ArrayList<Entry> activeNotifications = mNotificationData.getActiveNotifications();
- for (int i = 0; i < activeNotifications.size(); i++) {
- final Entry entry = activeNotifications.get(i);
- final boolean visible = entry.row != null
- && entry.row.getVisibility() == View.VISIBLE;
- if (visible) {
- mNewVisibleNotifications.add(entry.key + entry.notification.getPostTime());
- }
- }
- final boolean updates = !mVisibleNotifications.containsAll(mNewVisibleNotifications);
- mVisibleNotifications.clear();
- mVisibleNotifications.addAll(mNewVisibleNotifications);
-
- // We have new notifications
- if (updates && mDozeServiceHost != null) {
- mDozeServiceHost.fireNewNotifications();
- }
- }
- }
-
private final class DozeServiceHost implements DozeHost {
- // Amount of time to allow to update the time shown on the screen before releasing
- // the wakelock. This timeout is design to compensate for the fact that we don't
- // currently have a way to know when time display contents have actually been
- // refreshed once we've finished rendering a new frame.
- private static final long PROCESSING_TIME = 500;
-
private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>();
- // Keeps the last reported state by fireNotificationLight.
- private boolean mNotificationLightOn;
-
@Override
public String toString() {
return "PSB.DozeServiceHost[mCallbacks=" + mCallbacks.size() + "]";
@@ -5114,19 +5058,6 @@
}
}
- public void fireNotificationLight(boolean on) {
- mNotificationLightOn = on;
- for (Callback callback : mCallbacks) {
- callback.onNotificationLight(on);
- }
- }
-
- public void fireNewNotifications() {
- for (Callback callback : mCallbacks) {
- callback.onNewNotifications();
- }
- }
-
@Override
public void addCallback(@NonNull Callback callback) {
mCallbacks.add(callback);
@@ -5192,11 +5123,6 @@
}
@Override
- public boolean isNotificationLightOn() {
- return mNotificationLightOn;
- }
-
- @Override
public void startPendingIntentDismissingKeyguard(PendingIntent intent) {
StatusBar.this.startPendingIntentDismissingKeyguard(intent);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 6006d5a..11927729 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -2766,6 +2766,7 @@
private void updateNotificationAnimationStates() {
boolean running = mAnimationsEnabled || mPulsing;
+ mShelf.setAnimationsEnabled(running);
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
index ab562d1..5d11ef3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
@@ -42,104 +42,11 @@
private IStatusBarService mBarService;
@Override
- public void setIcon(String slot, StatusBarIcon icon) {
- }
-
- @Override
- public void removeIcon(String slot) {
- }
-
- public void removeNotification(String key, RankingMap ranking) {
- }
-
- @Override
- public void disable(int state1, int state2, boolean animate) {
- }
-
- @Override
- public void animateExpandNotificationsPanel() {
- }
-
- @Override
- public void animateCollapsePanels(int flags) {
- }
-
- @Override
- public void setSystemUiVisibility(int vis, int fullscreenStackVis, int dockedStackVis,
- int mask, Rect fullscreenStackBounds, Rect dockedStackBounds) {
- }
-
- @Override
- public void topAppWindowChanged(boolean visible) {
- }
-
- @Override
- public void setImeWindowStatus(IBinder token, int vis, int backDisposition,
- boolean showImeSwitcher) {
- }
-
- @Override // CommandQueue
- public void setWindowState(int window, int state) {
- }
-
- @Override // CommandQueue
- public void buzzBeepBlinked() {
- }
-
- @Override // CommandQueue
- public void notificationLightOff() {
- }
-
- @Override // CommandQueue
- public void notificationLightPulse(int argb, int onMillis, int offMillis) {
- }
-
- @Override
- public void animateExpandSettingsPanel(String subPanel) {
- }
-
- @Override
- public void showScreenPinningRequest(int taskId) {
- }
-
- @Override
- public void appTransitionPending() {
- }
-
- @Override
- public void appTransitionCancelled() {
- }
-
- @Override
- public void appTransitionStarting(long startTime, long duration) {
- }
-
- @Override
- public void appTransitionFinished() {
- }
-
- @Override
- public void onCameraLaunchGestureDetected(int source) {
- }
-
- @Override
public void showTvPictureInPictureMenu() {
PipManager.getInstance().showTvPictureInPictureMenu();
}
@Override
- public void addQsTile(ComponentName tile) {
- }
-
- @Override
- public void remQsTile(ComponentName tile) {
- }
-
- @Override
- public void clickTile(ComponentName tile) {
- }
-
- @Override
public void start() {
putComponent(TvStatusBar.class, this);
CommandQueue commandQueue = getComponent(CommandQueue.class);
@@ -160,8 +67,4 @@
}
}
- @Override
- public void handleSystemNavigationKey(int arg1) {
- // Not implemented
- }
}
diff --git a/packages/SystemUI/tests/res/layout/custom_view_dark.xml b/packages/SystemUI/tests/res/layout/custom_view_dark.xml
new file mode 100644
index 0000000..9e460a5
--- /dev/null
+++ b/packages/SystemUI/tests/res/layout/custom_view_dark.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 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.
+-->
+<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="#ff000000"
+ />
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java
index 43f8629..5b22986 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java
@@ -171,27 +171,6 @@
}
@Test
- public void testBuzzBeepBlink() {
- mCommandQueue.buzzBeepBlinked();
- waitForIdleSync();
- verify(mCallbacks).buzzBeepBlinked();
- }
-
- @Test
- public void testNotificationLightOff() {
- mCommandQueue.notificationLightOff();
- waitForIdleSync();
- verify(mCallbacks).notificationLightOff();
- }
-
- @Test
- public void testNotificationLightPulse() {
- mCommandQueue.notificationLightPulse(1, 2, 3);
- waitForIdleSync();
- verify(mCallbacks).notificationLightPulse(eq(1), eq(2), eq(3));
- }
-
- @Test
public void testScreenPinRequest() {
mCommandQueue.showScreenPinningRequest(1);
waitForIdleSync();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationCustomViewWrapperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationCustomViewWrapperTest.java
new file mode 100644
index 0000000..d07cea1
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationCustomViewWrapperTest.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar;
+
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.annotation.UiThreadTest;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.View;
+import android.widget.RemoteViews;
+
+import com.android.systemui.R;
+import com.android.systemui.statusbar.notification.NotificationCustomViewWrapper;
+import com.android.systemui.statusbar.notification.NotificationViewWrapper;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class NotificationCustomViewWrapperTest {
+
+ private Context mContext;
+ private ExpandableNotificationRow mRow;
+
+ @Before
+ @UiThreadTest
+ public void setUp() {
+ mContext = InstrumentationRegistry.getTargetContext();
+ mRow = new ExpandableNotificationRow(mContext, null);
+ }
+
+ @Test
+ public void testBackgroundPersists() {
+ RemoteViews views = new RemoteViews(mContext.getPackageName(), R.layout.custom_view_dark);
+ View v = views.apply(mContext, null);
+ NotificationViewWrapper wrap = NotificationCustomViewWrapper.wrap(mContext, v, mRow);
+ wrap.notifyContentUpdated(null, false /* isLowPriority */);
+ Assert.assertTrue(wrap.getCustomBackgroundColor() != 0);
+ views.reapply(mContext, v);
+ wrap.notifyContentUpdated(null, false /* isLowPriority */);
+ Assert.assertTrue(wrap.getCustomBackgroundColor() != 0);
+ }
+
+}
\ No newline at end of file
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index a861522..3d9ef02 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -70,6 +70,8 @@
import android.os.UserManagerInternal;
import android.provider.Settings;
import android.hardware.fingerprint.IFingerprintService;
+import android.provider.SettingsStringUtil.ComponentNameSet;
+import android.provider.SettingsStringUtil.SettingStringHelper;
import android.text.TextUtils;
import android.text.TextUtils.SimpleStringSplitter;
import android.util.Slog;
@@ -98,9 +100,9 @@
import com.android.internal.content.PackageMonitor;
import com.android.internal.os.SomeArgs;
import com.android.server.LocalServices;
-
import com.android.server.policy.AccessibilityShortcutController;
import com.android.server.statusbar.StatusBarManagerInternal;
+
import org.xmlpull.v1.XmlPullParserException;
import java.io.FileDescriptor;
@@ -445,7 +447,7 @@
}
return userState.getClientState();
} else {
- userState.mClients.register(client);
+ userState.mUserClients.register(client);
// If this client is not for the current user we do not
// return a state since it is not for the foreground user.
// We will send the state to the client on a user switch.
@@ -813,6 +815,42 @@
}
}
+ /**
+ * Invoked remotely over AIDL by SysUi when the accessibility button within the system's
+ * navigation area has been clicked.
+ */
+ @Override
+ public void notifyAccessibilityButtonClicked() {
+ if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Caller does not hold permission "
+ + android.Manifest.permission.STATUS_BAR);
+ }
+ synchronized (mLock) {
+ notifyAccessibilityButtonClickedLocked();
+ }
+ }
+
+ /**
+ * Invoked remotely over AIDL by SysUi when the availability of the accessibility
+ * button within the system's navigation area has changed.
+ *
+ * @param available {@code true} if the accessibility button is available to the
+ * user, {@code false} otherwise
+ */
+ @Override
+ public void notifyAccessibilityButtonAvailabilityChanged(boolean available) {
+ if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Caller does not hold permission "
+ + android.Manifest.permission.STATUS_BAR);
+ }
+ synchronized (mLock) {
+ notifyAccessibilityButtonAvailabilityChangedLocked(available);
+ }
+ }
+
+
boolean onGesture(int gestureId) {
synchronized (mLock) {
boolean handled = notifyGestureLocked(gestureId, false);
@@ -927,7 +965,7 @@
oldUserState.onSwitchToAnotherUser();
// Disable the local managers for the old user.
- if (oldUserState.mClients.getRegisteredCallbackCount() > 0) {
+ if (oldUserState.mUserClients.getRegisteredCallbackCount() > 0) {
mMainHandler.obtainMessage(MainHandler.MSG_SEND_CLEARED_STATE_TO_CLIENTS_FOR_USER,
oldUserState.mUserId, 0).sendToTarget();
}
@@ -1044,6 +1082,28 @@
}
}
+ private void notifyAccessibilityButtonClickedLocked() {
+ final UserState state = getCurrentUserStateLocked();
+ for (int i = state.mBoundServices.size() - 1; i >= 0; i--) {
+ final Service service = state.mBoundServices.get(i);
+ // TODO(b/34720082): Only notify a single user-defined service
+ if (service.mRequestAccessibilityButton) {
+ service.notifyAccessibilityButtonClickedLocked();
+ }
+ }
+ }
+
+ private void notifyAccessibilityButtonAvailabilityChangedLocked(boolean available) {
+ final UserState state = getCurrentUserStateLocked();
+ state.mIsAccessibilityButtonAvailable = available;
+ for (int i = state.mBoundServices.size() - 1; i >= 0; i--) {
+ final Service service = state.mBoundServices.get(i);
+ if (service.mRequestAccessibilityButton) {
+ service.notifyAccessibilityButtonAvailabilityChangedLocked(available);
+ }
+ }
+ }
+
/**
* Removes an AccessibilityInteractionConnection.
*
@@ -1178,7 +1238,7 @@
service.onAdded();
userState.mBoundServices.add(service);
userState.mComponentNameToServiceMap.put(service.mComponentName, service);
- scheduleNotifyClientsOfServicesStateChange();
+ scheduleNotifyClientsOfServicesStateChange(userState);
}
} catch (RemoteException re) {
/* do nothing */
@@ -1200,7 +1260,7 @@
Service boundService = userState.mBoundServices.get(i);
userState.mComponentNameToServiceMap.put(boundService.mComponentName, boundService);
}
- scheduleNotifyClientsOfServicesStateChange();
+ scheduleNotifyClientsOfServicesStateChange(userState);
}
/**
@@ -1362,16 +1422,16 @@
final int clientState = userState.getClientState();
if (userState.mLastSentClientState != clientState
&& (mGlobalClients.getRegisteredCallbackCount() > 0
- || userState.mClients.getRegisteredCallbackCount() > 0)) {
+ || userState.mUserClients.getRegisteredCallbackCount() > 0)) {
userState.mLastSentClientState = clientState;
mMainHandler.obtainMessage(MainHandler.MSG_SEND_STATE_TO_CLIENTS,
clientState, userState.mUserId).sendToTarget();
}
}
- private void scheduleNotifyClientsOfServicesStateChange() {
- mMainHandler.obtainMessage(MainHandler.MSG_SEND_SERVICES_STATE_CHANGED_TO_CLIENTS)
- .sendToTarget();
+ private void scheduleNotifyClientsOfServicesStateChange(UserState userState) {
+ mMainHandler.obtainMessage(MainHandler.MSG_SEND_SERVICES_STATE_CHANGED_TO_CLIENTS,
+ userState.mUserId).sendToTarget();
}
private void scheduleUpdateInputFilter(UserState userState) {
@@ -2013,10 +2073,12 @@
* Enables accessibility service specified by {@param componentName} for the {@param userId}.
*/
private void enableAccessibilityServiceLocked(ComponentName componentName, int userId) {
- SettingsStringHelper settingsHelper = new SettingsStringHelper(
- Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, userId);
- settingsHelper.addService(componentName);
- settingsHelper.writeToSettings();
+ final SettingStringHelper setting =
+ new SettingStringHelper(
+ mContext.getContentResolver(),
+ Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
+ userId);
+ setting.write(ComponentNameSet.add(setting.read(), componentName));
UserState userState = getUserStateLocked(userId);
if (userState.mEnabledServices.add(componentName)) {
@@ -2028,10 +2090,12 @@
* Disables accessibility service specified by {@param componentName} for the {@param userId}.
*/
private void disableAccessibilityServiceLocked(ComponentName componentName, int userId) {
- SettingsStringHelper settingsHelper = new SettingsStringHelper(
- Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, userId);
- settingsHelper.deleteService(componentName);
- settingsHelper.writeToSettings();
+ final SettingStringHelper setting =
+ new SettingStringHelper(
+ mContext.getContentResolver(),
+ Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
+ userId);
+ setting.write(ComponentNameSet.remove(setting.read(), componentName));
UserState userState = getUserStateLocked(userId);
if (userState.mEnabledServices.remove(componentName)) {
@@ -2060,45 +2124,6 @@
return mFingerprintGestureDispatcher.onFingerprintGesture(gestureKeyCode);
}
- private class SettingsStringHelper {
- private static final String SETTINGS_DELIMITER = ":";
- private ContentResolver mContentResolver;
- private final String mSettingsName;
- private Set<String> mServices;
- private final int mUserId;
-
- public SettingsStringHelper(String name, int userId) {
- mUserId = userId;
- mSettingsName = name;
- mContentResolver = mContext.getContentResolver();
- String servicesString = Settings.Secure.getStringForUser(
- mContentResolver, mSettingsName, userId);
- mServices = new HashSet();
- if (!TextUtils.isEmpty(servicesString)) {
- final TextUtils.SimpleStringSplitter colonSplitter =
- new TextUtils.SimpleStringSplitter(SETTINGS_DELIMITER.charAt(0));
- colonSplitter.setString(servicesString);
- while (colonSplitter.hasNext()) {
- final String serviceName = colonSplitter.next();
- mServices.add(serviceName);
- }
- }
- }
-
- public void addService(ComponentName component) {
- mServices.add(component.flattenToString());
- }
-
- public void deleteService(ComponentName component) {
- mServices.remove(component.flattenToString());
- }
-
- public void writeToSettings() {
- Settings.Secure.putStringForUser(mContentResolver, mSettingsName,
- TextUtils.join(SETTINGS_DELIMITER, mServices), mUserId);
- }
- }
-
@Override
public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
mSecurityPolicy.enforceCallingPermission(Manifest.permission.DUMP, FUNCTION_DUMP);
@@ -2225,12 +2250,12 @@
final int clientState = msg.arg1;
final int userId = msg.arg2;
sendStateToClients(clientState, mGlobalClients);
- sendStateToClientsForUser(clientState, userId);
+ sendStateToClients(clientState, getUserClientsForId(userId));
} break;
case MSG_SEND_CLEARED_STATE_TO_CLIENTS_FOR_USER: {
final int userId = msg.arg1;
- sendStateToClientsForUser(0, userId);
+ sendStateToClients(0, getUserClientsForId(userId));
} break;
case MSG_ANNOUNCE_NEW_USER_IF_NEEDED: {
@@ -2257,7 +2282,9 @@
} break;
case MSG_SEND_SERVICES_STATE_CHANGED_TO_CLIENTS: {
- notifyClientsOfServicesStateChange();
+ final int userId = msg.arg1;
+ notifyClientsOfServicesStateChange(mGlobalClients);
+ notifyClientsOfServicesStateChange(getUserClientsForId(userId));
} break;
case MSG_UPDATE_FINGERPRINT: {
@@ -2282,12 +2309,12 @@
}
}
- private void sendStateToClientsForUser(int clientState, int userId) {
+ private RemoteCallbackList<IAccessibilityManagerClient> getUserClientsForId(int userId) {
final UserState userState;
synchronized (mLock) {
userState = getUserStateLocked(userId);
}
- sendStateToClients(clientState, userState.mClients);
+ return userState.mUserClients;
}
private void sendStateToClients(int clientState,
@@ -2307,11 +2334,8 @@
}
}
- private void notifyClientsOfServicesStateChange() {
- RemoteCallbackList<IAccessibilityManagerClient> clients;
- synchronized (mLock) {
- clients = getCurrentUserStateLocked().mClients;
- }
+ private void notifyClientsOfServicesStateChange(
+ RemoteCallbackList<IAccessibilityManagerClient> clients) {
try {
final int userClientCount = clients.beginBroadcast();
for (int i = 0; i < userClientCount; i++) {
@@ -2426,6 +2450,8 @@
boolean mCaptureFingerprintGestures;
+ boolean mRequestAccessibilityButton;
+
int mFetchFlags;
long mNotificationTimeout;
@@ -2581,6 +2607,8 @@
& AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS) != 0;
mCaptureFingerprintGestures = (info.flags
& AccessibilityServiceInfo.FLAG_CAPTURE_FINGERPRINT_GESTURES) != 0;
+ mRequestAccessibilityButton = (info.flags
+ & AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON) != 0;
}
/**
@@ -2694,7 +2722,7 @@
}
UserState userState = getUserStateLocked(mUserId);
onUserStateChangedLocked(userState);
- scheduleNotifyClientsOfServicesStateChange();
+ scheduleNotifyClientsOfServicesStateChange(userState);
}
} finally {
Binder.restoreCallingIdentity(identity);
@@ -3332,6 +3360,19 @@
}
@Override
+ public boolean isAccessibilityButtonAvailable() {
+ final UserState userState;
+ synchronized (mLock) {
+ if (!isCalledForCurrentUserLocked()) {
+ return false;
+ }
+ userState = getCurrentUserStateLocked();
+ }
+
+ return mRequestAccessibilityButton && userState.mIsAccessibilityButtonAvailable;
+ }
+
+ @Override
public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
mSecurityPolicy.enforceCallingPermission(Manifest.permission.DUMP, FUNCTION_DUMP);
synchronized (mLock) {
@@ -3544,6 +3585,14 @@
mInvocationHandler.notifySoftKeyboardShowModeChangedLocked(showState);
}
+ public void notifyAccessibilityButtonClickedLocked() {
+ mInvocationHandler.notifyAccessibilityButtonClickedLocked();
+ }
+
+ public void notifyAccessibilityButtonAvailabilityChangedLocked(boolean available) {
+ mInvocationHandler.notifyAccessibilityButtonAvailabilityChangedLocked(available);
+ }
+
/**
* Called by the invocation handler to notify the service that the
* state of magnification has changed.
@@ -3582,6 +3631,36 @@
}
}
+ private void notifyAccessibilityButtonClickedInternal() {
+ final IAccessibilityServiceClient listener;
+ synchronized (mLock) {
+ listener = mServiceInterface;
+ }
+ if (listener != null) {
+ try {
+ listener.onAccessibilityButtonClicked();
+ } catch (RemoteException re) {
+ Slog.e(LOG_TAG, "Error sending accessibility button click to " + mService, re);
+ }
+ }
+ }
+
+ private void notifyAccessibilityButtonAvailabilityChangedInternal(boolean available) {
+ final IAccessibilityServiceClient listener;
+ synchronized (mLock) {
+ listener = mServiceInterface;
+ }
+ if (listener != null) {
+ try {
+ listener.onAccessibilityButtonAvailabilityChanged(available);
+ } catch (RemoteException re) {
+ Slog.e(LOG_TAG,
+ "Error sending accessibility button availability change to " + mService,
+ re);
+ }
+ }
+ }
+
private void notifyGestureInternal(int gestureId) {
final IAccessibilityServiceClient listener;
synchronized (mLock) {
@@ -3723,6 +3802,8 @@
private static final int MSG_ON_MAGNIFICATION_CHANGED = 5;
private static final int MSG_ON_SOFT_KEYBOARD_STATE_CHANGED = 6;
+ private static final int MSG_ON_ACCESSIBILITY_BUTTON_CLICKED = 7;
+ private static final int MSG_ON_ACCESSIBILITY_BUTTON_AVAILABILITY_CHANGED = 8;
private boolean mIsMagnificationCallbackEnabled = false;
private boolean mIsSoftKeyboardCallbackEnabled = false;
@@ -3758,6 +3839,15 @@
notifySoftKeyboardShowModeChangedInternal(showState);
} break;
+ case MSG_ON_ACCESSIBILITY_BUTTON_CLICKED: {
+ notifyAccessibilityButtonClickedInternal();
+ } break;
+
+ case MSG_ON_ACCESSIBILITY_BUTTON_AVAILABILITY_CHANGED: {
+ final boolean available = (message.arg1 != 0);
+ notifyAccessibilityButtonAvailabilityChangedInternal(available);
+ } break;
+
default: {
throw new IllegalArgumentException("Unknown message: " + type);
}
@@ -3797,6 +3887,17 @@
public void setSoftKeyboardCallbackEnabled(boolean enabled) {
mIsSoftKeyboardCallbackEnabled = enabled;
}
+
+ public void notifyAccessibilityButtonClickedLocked() {
+ final Message msg = obtainMessage(MSG_ON_ACCESSIBILITY_BUTTON_CLICKED);
+ msg.sendToTarget();
+ }
+
+ public void notifyAccessibilityButtonAvailabilityChangedLocked(boolean available) {
+ final Message msg = obtainMessage(MSG_ON_ACCESSIBILITY_BUTTON_AVAILABILITY_CHANGED,
+ (available ? 1 : 0), 0);
+ msg.sendToTarget();
+ }
}
}
@@ -4467,7 +4568,7 @@
// Non-transient state.
- public final RemoteCallbackList<IAccessibilityManagerClient> mClients =
+ public final RemoteCallbackList<IAccessibilityManagerClient> mUserClients =
new RemoteCallbackList<>();
public final SparseArray<AccessibilityConnectionWrapper> mInteractionConnections =
@@ -4501,6 +4602,8 @@
public int mSoftKeyboardShowMode = 0;
+ public boolean mIsAccessibilityButtonAvailable;
+
public boolean mIsTouchExplorationEnabled;
public boolean mIsTextHighContrastEnabled;
public boolean mIsEnhancedWebAccessibilityEnabled;
@@ -4575,6 +4678,9 @@
mIsDisplayMagnificationEnabled = false;
mIsAutoclickEnabled = false;
mSoftKeyboardShowMode = 0;
+
+ // Clear state tracked from system UI
+ mIsAccessibilityButtonAvailable = false;
}
public void destroyUiAutomationService() {
diff --git a/services/core/java/com/android/server/LockSettingsStrongAuth.java b/services/core/java/com/android/server/LockSettingsStrongAuth.java
index 1314110..f5fe3db 100644
--- a/services/core/java/com/android/server/LockSettingsStrongAuth.java
+++ b/services/core/java/com/android/server/LockSettingsStrongAuth.java
@@ -51,6 +51,7 @@
private static final int MSG_REGISTER_TRACKER = 2;
private static final int MSG_UNREGISTER_TRACKER = 3;
private static final int MSG_REMOVE_USER = 4;
+ private static final int MSG_SCHEDULE_STRONG_AUTH_TIMEOUT = 5;
private static final String STRONG_AUTH_TIMEOUT_ALARM_TAG =
"LockSettingsStrongAuth.timeoutForUser";
@@ -128,6 +129,23 @@
}
}
+ private void handleScheduleStrongAuthTimeout(int userId) {
+ final DevicePolicyManager dpm =
+ (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
+ long when = SystemClock.elapsedRealtime() + dpm.getRequiredStrongAuthTimeout(null, userId);
+ // cancel current alarm listener for the user (if there was one)
+ StrongAuthTimeoutAlarmListener alarm = mStrongAuthTimeoutAlarmListenerForUser.get(userId);
+ if (alarm != null) {
+ mAlarmManager.cancel(alarm);
+ } else {
+ alarm = new StrongAuthTimeoutAlarmListener(userId);
+ mStrongAuthTimeoutAlarmListenerForUser.put(userId, alarm);
+ }
+ // schedule a new alarm listener for the user
+ mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, when, STRONG_AUTH_TIMEOUT_ALARM_TAG,
+ alarm, mHandler);
+ }
+
private void notifyStrongAuthTrackers(int strongAuthReason, int userId) {
for (int i = 0; i < mStrongAuthTrackers.size(); i++) {
try {
@@ -151,7 +169,8 @@
}
public void removeUser(int userId) {
- mHandler.obtainMessage(MSG_REMOVE_USER, userId, 0).sendToTarget();
+ final int argNotUsed = 0;
+ mHandler.obtainMessage(MSG_REMOVE_USER, userId, argNotUsed).sendToTarget();
}
public void requireStrongAuth(int strongAuthReason, int userId) {
@@ -169,29 +188,8 @@
}
public void reportSuccessfulStrongAuthUnlock(int userId) {
- scheduleStrongAuthTimeout(userId);
- }
-
- private void scheduleStrongAuthTimeout(int userId) {
- final DevicePolicyManager dpm =
- (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
- long when = SystemClock.elapsedRealtime() + dpm.getRequiredStrongAuthTimeout(null, userId);
- // cancel current alarm listener for the user (if there was one)
- StrongAuthTimeoutAlarmListener alarm = mStrongAuthTimeoutAlarmListenerForUser.get(userId);
- if (alarm != null) {
- mAlarmManager.cancel(alarm);
- } else {
- alarm = new StrongAuthTimeoutAlarmListener(userId);
- mStrongAuthTimeoutAlarmListenerForUser.put(userId, alarm);
- }
- // schedule a new alarm listener for the user
- final long ident = Binder.clearCallingIdentity();
- try {
- mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, when, STRONG_AUTH_TIMEOUT_ALARM_TAG,
- alarm, mHandler);
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
+ final int argNotUsed = 0;
+ mHandler.obtainMessage(MSG_SCHEDULE_STRONG_AUTH_TIMEOUT, userId, argNotUsed).sendToTarget();
}
private class StrongAuthTimeoutAlarmListener implements OnAlarmListener {
@@ -224,6 +222,9 @@
case MSG_REMOVE_USER:
handleRemoveUser(msg.arg1);
break;
+ case MSG_SCHEDULE_STRONG_AUTH_TIMEOUT:
+ handleScheduleStrongAuthTimeout(msg.arg1);
+ break;
}
}
};
diff --git a/services/core/java/com/android/server/NetworkScoreService.java b/services/core/java/com/android/server/NetworkScoreService.java
index 22dbf44..5fe8b1a 100644
--- a/services/core/java/com/android/server/NetworkScoreService.java
+++ b/services/core/java/com/android/server/NetworkScoreService.java
@@ -927,7 +927,7 @@
try {
for (int i = 0; i < count; i++) {
consumer.accept(callbackList.getBroadcastItem(i),
- callbackList.getRegisteredCallbackCookie(i));
+ callbackList.getBroadcastCookie(i));
}
} finally {
callbackList.finishBroadcast();
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 5655dc5..041fee2 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -16,6 +16,8 @@
package com.android.server.am;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
import static com.android.server.am.ActivityManagerDebugConfig.*;
import java.io.FileDescriptor;
@@ -1391,8 +1393,7 @@
}
if (r != null) {
if (mAm.checkComponentPermission(r.permission,
- callingPid, callingUid, r.appInfo.uid, r.exported)
- != PackageManager.PERMISSION_GRANTED) {
+ callingPid, callingUid, r.appInfo.uid, r.exported) != PERMISSION_GRANTED) {
if (!r.exported) {
Slog.w(TAG, "Permission Denial: Accessing service " + r.name
+ " from pid=" + callingPid
@@ -2775,16 +2776,15 @@
return info;
}
- List<ActivityManager.RunningServiceInfo> getRunningServiceInfoLocked(int maxNum, int flags) {
+ List<ActivityManager.RunningServiceInfo> getRunningServiceInfoLocked(int maxNum, int flags,
+ int callingUid, boolean allowed) {
ArrayList<ActivityManager.RunningServiceInfo> res
= new ArrayList<ActivityManager.RunningServiceInfo>();
- final int uid = Binder.getCallingUid();
final long ident = Binder.clearCallingIdentity();
try {
- if (ActivityManager.checkUidPermission(
- android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
- uid) == PackageManager.PERMISSION_GRANTED) {
+ if (ActivityManager.checkUidPermission(INTERACT_ACROSS_USERS_FULL, callingUid)
+ == PERMISSION_GRANTED) {
int[] users = mAm.mUserController.getUsers();
for (int ui=0; ui<users.length && res.size() < maxNum; ui++) {
ArrayMap<ComponentName, ServiceRecord> alls = getServicesLocked(users[ui]);
@@ -2802,16 +2802,20 @@
res.add(info);
}
} else {
- int userId = UserHandle.getUserId(uid);
+ int userId = UserHandle.getUserId(callingUid);
ArrayMap<ComponentName, ServiceRecord> alls = getServicesLocked(userId);
for (int i=0; i<alls.size() && res.size() < maxNum; i++) {
ServiceRecord sr = alls.valueAt(i);
- res.add(makeRunningServiceInfoLocked(sr));
+
+ if (allowed || (sr.app != null && sr.app.uid == callingUid)) {
+ res.add(makeRunningServiceInfoLocked(sr));
+ }
}
for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
ServiceRecord r = mRestartingServices.get(i);
- if (r.userId == userId) {
+ if (r.userId == userId
+ && (allowed || (r.app != null && r.app.uid == callingUid))) {
ActivityManager.RunningServiceInfo info =
makeRunningServiceInfoLocked(r);
info.restarting = r.nextRestartTime;
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 5ed8290..d75048d 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -17467,7 +17467,11 @@
int flags) {
enforceNotIsolatedCaller("getServices");
synchronized (this) {
- return mServices.getRunningServiceInfoLocked(maxNum, flags);
+ final int callingUid = Binder.getCallingUid();
+ final boolean allowed = isGetTasksAllowed("getServices", Binder.getCallingPid(),
+ callingUid);
+
+ return mServices.getRunningServiceInfoLocked(maxNum, flags, callingUid, allowed);
}
}
diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
index 3da49d8..168744b 100644
--- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java
+++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
@@ -18,9 +18,6 @@
import com.android.server.EventLogTags;
import com.android.server.LocalServices;
-import com.android.server.twilight.TwilightListener;
-import com.android.server.twilight.TwilightManager;
-import com.android.server.twilight.TwilightState;
import android.annotation.Nullable;
import android.hardware.Sensor;
@@ -55,9 +52,6 @@
// non-zero, which in turn ensures that the total weight is non-zero.
private static final long AMBIENT_LIGHT_PREDICTION_TIME_MILLIS = 100;
- // Specifies the maximum magnitude of the time of day adjustment.
- private static final float TWILIGHT_ADJUSTMENT_MAX_GAMMA = 1f;
-
// Debounce for sampling user-initiated changes in display brightness to ensure
// the user is satisfied with the result before storing the sample.
private static final int BRIGHTNESS_ADJUSTMENT_SAMPLE_DEBOUNCE_MILLIS = 10000;
@@ -74,9 +68,6 @@
// The light sensor, or null if not available or needed.
private final Sensor mLightSensor;
- // The twilight service.
- private final TwilightManager mTwilight;
-
// The auto-brightness spline adjustment.
// The brightness values have been scaled to a range of 0..1.
private final Spline mScreenAutoBrightnessSpline;
@@ -186,8 +177,6 @@
private int mBrightnessAdjustmentSampleOldBrightness;
private float mBrightnessAdjustmentSampleOldGamma;
- private boolean mUseTwilight;
-
public AutomaticBrightnessController(Callbacks callbacks, Looper looper,
SensorManager sensorManager, Spline autoBrightnessSpline, int lightSensorWarmUpTime,
int brightnessMin, int brightnessMax, float dozeScaleFactor,
@@ -196,7 +185,6 @@
int ambientLightHorizon, float autoBrightnessAdjustmentMaxGamma,
HysteresisLevels dynamicHysteresis) {
mCallbacks = callbacks;
- mTwilight = LocalServices.getService(TwilightManager.class);
mSensorManager = sensorManager;
mScreenAutoBrightnessSpline = autoBrightnessSpline;
mScreenBrightnessRangeMinimum = brightnessMin;
@@ -233,7 +221,7 @@
}
public void configure(boolean enable, float adjustment, boolean dozing,
- boolean userInitiatedChange, boolean useTwilight) {
+ boolean userInitiatedChange) {
// While dozing, the application processor may be suspended which will prevent us from
// receiving new information from the light sensor. On some devices, we may be able to
// switch to a wake-up light sensor instead but for now we will simply disable the sensor
@@ -242,7 +230,6 @@
mDozing = dozing;
boolean changed = setLightSensorEnabled(enable && !dozing);
changed |= setScreenAutoBrightnessAdjustment(adjustment);
- changed |= setUseTwilight(useTwilight);
if (changed) {
updateAutoBrightness(false /*sendUpdate*/);
}
@@ -251,17 +238,6 @@
}
}
- private boolean setUseTwilight(boolean useTwilight) {
- if (mUseTwilight == useTwilight) return false;
- if (useTwilight) {
- mTwilight.registerListener(mTwilightListener, mHandler);
- } else {
- mTwilight.unregisterListener(mTwilightListener);
- }
- mUseTwilight = useTwilight;
- return true;
- }
-
public void dump(PrintWriter pw) {
pw.println();
pw.println("Automatic Brightness Controller Configuration:");
@@ -276,7 +252,6 @@
pw.println();
pw.println("Automatic Brightness Controller State:");
pw.println(" mLightSensor=" + mLightSensor);
- pw.println(" mTwilight.getLastTwilightState()=" + mTwilight.getLastTwilightState());
pw.println(" mLightSensorEnabled=" + mLightSensorEnabled);
pw.println(" mLightSensorEnableTime=" + TimeUtils.formatUptime(mLightSensorEnableTime));
pw.println(" mAmbientLux=" + mAmbientLux);
@@ -522,19 +497,6 @@
}
}
- if (mUseTwilight) {
- TwilightState state = mTwilight.getLastTwilightState();
- if (state != null && state.isNight()) {
- final long duration = state.sunriseTimeMillis() - state.sunsetTimeMillis();
- final long progress = System.currentTimeMillis() - state.sunsetTimeMillis();
- final float amount = (float) Math.pow(2.0 * progress / duration - 1.0, 2.0);
- gamma *= 1 + amount * TWILIGHT_ADJUSTMENT_MAX_GAMMA;
- if (DEBUG) {
- Slog.d(TAG, "updateAutoBrightness: twilight amount=" + amount);
- }
- }
- }
-
if (gamma != 1.0f) {
final float in = value;
value = MathUtils.pow(value, gamma);
@@ -649,13 +611,6 @@
}
};
- private final TwilightListener mTwilightListener = new TwilightListener() {
- @Override
- public void onTwilightStateChanged(@Nullable TwilightState state) {
- updateAutoBrightness(true /*sendUpdate*/);
- }
- };
-
/** Callbacks to request updates to the display's power state. */
interface Callbacks {
void updateBrightness();
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 015345c..bed269c 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -642,7 +642,7 @@
&& mPowerRequest.brightnessSetByUser;
mAutomaticBrightnessController.configure(autoBrightnessEnabled,
mPowerRequest.screenAutoBrightnessAdjustment, state != Display.STATE_ON,
- userInitiatedChange, mPowerRequest.useTwilight);
+ userInitiatedChange);
}
// Apply brightness boost.
diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java
index d1f7cfd..e83b228 100644
--- a/services/core/java/com/android/server/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java
@@ -83,6 +83,7 @@
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
/**
@@ -113,6 +114,8 @@
new ArrayList<>();
private final CopyOnWriteArrayList<IFingerprintClientActiveCallback> mClientActiveCallbacks =
new CopyOnWriteArrayList<>();
+ private final Map<Integer, Long> mAuthenticatorIds =
+ Collections.synchronizedMap(new HashMap<>());
private final AppOpsManager mAppOps;
private static final long FAIL_LOCKOUT_TIMEOUT_MS = 30*1000;
private static final int MAX_FAILED_ATTEMPTS = 5;
@@ -130,7 +133,6 @@
private final UserManager mUserManager;
private ClientMonitor mCurrentClient;
private ClientMonitor mPendingClient;
- private long mCurrentAuthenticatorId;
private PerformanceStats mPerformanceStats;
// Normal fingerprint authentications are tracked by mPerformanceMap.
@@ -239,6 +241,7 @@
if (DEBUG) Slog.v(TAG, "Fingerprint HAL id: " + mHalDeviceId);
if (mHalDeviceId != 0) {
+ loadAuthenticatorIds();
updateActiveGroup(ActivityManager.getCurrentUser(), null);
} else {
Slog.w(TAG, "Failed to open Fingerprint HAL!");
@@ -249,6 +252,26 @@
return mDaemon;
}
+ /** Populates existing authenticator ids. To be used only during the start of the service. */
+ private void loadAuthenticatorIds() {
+ // This operation can be expensive, so keep track of the elapsed time. Might need to move to
+ // background if it takes too long.
+ long t = System.currentTimeMillis();
+
+ mAuthenticatorIds.clear();
+ for (UserInfo user : UserManager.get(mContext).getUsers(true /* excludeDying */)) {
+ int userId = getUserOrWorkProfileId(null, user.id);
+ if (!mAuthenticatorIds.containsKey(userId)) {
+ updateActiveGroup(userId, null);
+ }
+ }
+
+ t = System.currentTimeMillis() - t;
+ if (t > 1000) {
+ Slog.w(TAG, "loadAuthenticatorIds() taking too long: " + t + "ms");
+ }
+ }
+
protected void handleEnumerate(long deviceId, int fingerId, int groupId, int remaining) {
if (DEBUG) Slog.w(TAG, "Enumerate: fid=" + fingerId + ", gid="
+ groupId + "rem=" + remaining);
@@ -499,14 +522,23 @@
boolean isCurrentUserOrProfile(int userId) {
UserManager um = UserManager.get(mContext);
-
- // Allow current user or profiles of the current user...
- for (int profileId : um.getEnabledProfileIds(mCurrentUserId)) {
- if (profileId == userId) {
- return true;
- }
+ if (um == null) {
+ Slog.e(TAG, "Unable to acquire UserManager");
+ return false;
}
- return false;
+
+ final long token = Binder.clearCallingIdentity();
+ try {
+ // Allow current user or profiles of the current user...
+ for (int profileId : um.getEnabledProfileIds(mCurrentUserId)) {
+ if (profileId == userId) {
+ return true;
+ }
+ }
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
private boolean isForegroundActivity(int uid, int pid) {
@@ -1195,7 +1227,7 @@
daemon.setActiveGroup(userId, fpDir.getAbsolutePath());
mCurrentUserId = userId;
}
- mCurrentAuthenticatorId = daemon.getAuthenticatorId();
+ mAuthenticatorIds.put(userId, daemon.getAuthenticatorId());
} catch (RemoteException e) {
Slog.e(TAG, "Failed to setActiveGroup():", e);
}
@@ -1218,8 +1250,14 @@
* @return true if this is a work profile
*/
private boolean isWorkProfile(int userId) {
- UserInfo info = mUserManager.getUserInfo(userId);
- return info != null && info.isManagedProfile();
+ UserInfo userInfo = null;
+ final long token = Binder.clearCallingIdentity();
+ try {
+ userInfo = mUserManager.getUserInfo(userId);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ return userInfo != null && userInfo.isManagedProfile();
}
private void listenForUserSwitches() {
@@ -1239,9 +1277,11 @@
/***
* @param opPackageName the name of the calling package
- * @return authenticator id for the current user
+ * @return authenticator id for the calling user
*/
public long getAuthenticatorId(String opPackageName) {
- return mCurrentAuthenticatorId;
+ final int userId = getUserOrWorkProfileId(opPackageName, UserHandle.getCallingUserId());
+ Long authenticatorId = mAuthenticatorIds.get(userId);
+ return authenticatorId != null ? authenticatorId : 0;
}
}
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index ede6e30..10ecb86 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -1123,6 +1123,38 @@
}
}
+ public void addQueueItem(MediaDescription description) {
+ try {
+ mCb.onAddQueueItem(description);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Remote failure in addQueueItem.", e);
+ }
+ }
+
+ public void addQueueItemAt(MediaDescription description, int index) {
+ try {
+ mCb.onAddQueueItemAt(description, index);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Remote failure in addQueueItemAt.", e);
+ }
+ }
+
+ public void removeQueueItem(MediaDescription description) {
+ try {
+ mCb.onRemoveQueueItem(description);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Remote failure in removeQueueItem.", e);
+ }
+ }
+
+ public void removeQueueItemAt(int index) {
+ try {
+ mCb.onRemoveQueueItemAt(index);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Remote failure in removeQueueItem.", e);
+ }
+ }
+
public void adjustVolume(int direction) {
try {
mCb.onAdjustVolume(direction);
@@ -1397,6 +1429,30 @@
}
@Override
+ public void addQueueItem(MediaDescription description) {
+ updateCallingPackage();
+ mSessionCb.addQueueItem(description);
+ }
+
+ @Override
+ public void addQueueItemAt(MediaDescription description, int index) {
+ updateCallingPackage();
+ mSessionCb.addQueueItemAt(description, index);
+ }
+
+ @Override
+ public void removeQueueItem(MediaDescription description) {
+ updateCallingPackage();
+ mSessionCb.removeQueueItem(description);
+ }
+
+ @Override
+ public void removeQueueItemAt(int index) {
+ updateCallingPackage();
+ mSessionCb.removeQueueItemAt(index);
+ }
+
+ @Override
public CharSequence getQueueTitle() {
return mQueueTitle;
}
diff --git a/services/core/java/com/android/server/notification/NotificationComparator.java b/services/core/java/com/android/server/notification/NotificationComparator.java
index 279bf90..d6c89a4 100644
--- a/services/core/java/com/android/server/notification/NotificationComparator.java
+++ b/services/core/java/com/android/server/notification/NotificationComparator.java
@@ -159,8 +159,7 @@
}
private boolean isMediaNotification(NotificationRecord record) {
- return record.getNotification().extras.getParcelable(
- Notification.EXTRA_MEDIA_SESSION) != null;
+ return record.getNotification().hasMediaSession();
}
private boolean isCall(NotificationRecord record) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 0e5ea6e..4207998 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -833,7 +833,6 @@
private List<String> mKeepUninstalledPackages;
private UserManagerInternal mUserManagerInternal;
- private final UserDataPreparer mUserDataPreparer;
private File mCacheDir;
@@ -1937,7 +1936,7 @@
// Clean up any users or apps that were removed or recreated
// while this volume was missing
- reconcileUsers(volumeUuid);
+ sUserManager.reconcileUsers(volumeUuid);
reconcileApps(volumeUuid);
// Clean up any install sessions that expired or were
@@ -2161,19 +2160,24 @@
if (SystemProperties.getInt("ro.cp_system_other_odex", 0) == 1) {
SystemProperties.set(CP_PREOPT_PROPERTY, "requested");
// We will wait for up to 100 seconds.
- final long timeEnd = SystemClock.uptimeMillis() + 100 * 1000;
+ final long timeStart = SystemClock.uptimeMillis();
+ final long timeEnd = timeStart + 100 * 1000;
+ long timeNow = timeStart;
while (!SystemProperties.get(CP_PREOPT_PROPERTY).equals("finished")) {
try {
Thread.sleep(WAIT_TIME_MS);
} catch (InterruptedException e) {
// Do nothing
}
- if (SystemClock.uptimeMillis() > timeEnd) {
+ timeNow = SystemClock.uptimeMillis();
+ if (timeNow > timeEnd) {
SystemProperties.set(CP_PREOPT_PROPERTY, "timed-out");
Slog.wtf(TAG, "cppreopt did not finish!");
break;
}
}
+
+ Slog.i(TAG, "cppreopts took " + (timeNow - timeStart) + " ms");
}
}
@@ -2265,8 +2269,8 @@
mEphemeralInstallDir = new File(dataDir, "app-ephemeral");
mAsecInternalPath = new File(dataDir, "app-asec").getPath();
mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
- mUserDataPreparer = new UserDataPreparer(mInstaller, mInstallLock, mContext, mOnlyCore);
- sUserManager = new UserManagerService(context, this, mUserDataPreparer, mPackages);
+ sUserManager = new UserManagerService(context, this,
+ new UserDataPreparer(mInstaller, mInstallLock, mContext, mOnlyCore), mPackages);
// Propagate permission configuration in to package manager.
ArrayMap<String, SystemConfig.PermissionEntry> permConfig
@@ -19966,7 +19970,7 @@
});
// Now that we're mostly running, clean up stale users and apps
- reconcileUsers(StorageManager.UUID_PRIVATE_INTERNAL);
+ sUserManager.reconcileUsers(StorageManager.UUID_PRIVATE_INTERNAL);
reconcileApps(StorageManager.UUID_PRIVATE_INTERNAL);
}
@@ -21304,60 +21308,6 @@
}
}
- /**
- * Examine all users present on given mounted volume, and destroy data
- * belonging to users that are no longer valid, or whose user ID has been
- * recycled.
- */
- private void reconcileUsers(String volumeUuid) {
- final List<File> files = new ArrayList<>();
- Collections.addAll(files, FileUtils
- .listFilesOrEmpty(Environment.getDataUserDeDirectory(volumeUuid)));
- Collections.addAll(files, FileUtils
- .listFilesOrEmpty(Environment.getDataUserCeDirectory(volumeUuid)));
- Collections.addAll(files, FileUtils
- .listFilesOrEmpty(Environment.getDataSystemDeDirectory()));
- Collections.addAll(files, FileUtils
- .listFilesOrEmpty(Environment.getDataSystemCeDirectory()));
- Collections.addAll(files, FileUtils
- .listFilesOrEmpty(Environment.getDataMiscCeDirectory()));
- for (File file : files) {
- if (!file.isDirectory()) continue;
-
- final int userId;
- final UserInfo info;
- try {
- userId = Integer.parseInt(file.getName());
- info = sUserManager.getUserInfo(userId);
- } catch (NumberFormatException e) {
- Slog.w(TAG, "Invalid user directory " + file);
- continue;
- }
-
- boolean destroyUser = false;
- if (info == null) {
- logCriticalInfo(Log.WARN, "Destroying user directory " + file
- + " because no matching user was found");
- destroyUser = true;
- } else if (!mOnlyCore) {
- try {
- UserManagerService.enforceSerialNumber(file, info.serialNumber);
- } catch (IOException e) {
- logCriticalInfo(Log.WARN, "Destroying user directory " + file
- + " because we failed to enforce serial number: " + e);
- destroyUser = true;
- }
- }
-
- if (destroyUser) {
- synchronized (mInstallLock) {
- mUserDataPreparer.destroyUserDataLI(volumeUuid, userId,
- StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE);
- }
- }
- }
- }
-
private void assertPackageKnown(String volumeUuid, String packageName)
throws PackageManagerException {
synchronized (mPackages) {
diff --git a/services/core/java/com/android/server/pm/UserDataPreparer.java b/services/core/java/com/android/server/pm/UserDataPreparer.java
index 52599fd..fc00acc 100644
--- a/services/core/java/com/android/server/pm/UserDataPreparer.java
+++ b/services/core/java/com/android/server/pm/UserDataPreparer.java
@@ -17,13 +17,28 @@
package com.android.server.pm;
import android.content.Context;
+import android.content.pm.UserInfo;
import android.os.Environment;
import android.os.FileUtils;
import android.os.storage.StorageManager;
import android.os.storage.VolumeInfo;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.system.OsConstants;
import android.util.Log;
+import android.util.Slog;
+import android.util.SparseArray;
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
import java.util.Objects;
+import java.util.Set;
import static com.android.server.pm.PackageManagerService.logCriticalInfo;
@@ -31,6 +46,9 @@
* Helper class for preparing and destroying user storage
*/
class UserDataPreparer {
+ private static final String TAG = "UserDataPreparer";
+ private static final String XATTR_SERIAL = "user.serial";
+
private final Object mInstallLock;
private final Context mContext;
private final boolean mOnlyCore;
@@ -65,19 +83,15 @@
storage.prepareUserStorage(volumeUuid, userId, userSerial, flags);
if ((flags & StorageManager.FLAG_STORAGE_DE) != 0 && !mOnlyCore) {
- UserManagerService.enforceSerialNumber(
- Environment.getDataUserDeDirectory(volumeUuid, userId), userSerial);
+ enforceSerialNumber(getDataUserDeDirectory(volumeUuid, userId), userSerial);
if (Objects.equals(volumeUuid, StorageManager.UUID_PRIVATE_INTERNAL)) {
- UserManagerService.enforceSerialNumber(
- Environment.getDataSystemDeDirectory(userId), userSerial);
+ enforceSerialNumber(getDataSystemDeDirectory(userId), userSerial);
}
}
if ((flags & StorageManager.FLAG_STORAGE_CE) != 0 && !mOnlyCore) {
- UserManagerService.enforceSerialNumber(
- Environment.getDataUserCeDirectory(volumeUuid, userId), userSerial);
+ enforceSerialNumber(getDataUserCeDirectory(volumeUuid, userId), userSerial);
if (Objects.equals(volumeUuid, StorageManager.UUID_PRIVATE_INTERNAL)) {
- UserManagerService.enforceSerialNumber(
- Environment.getDataSystemCeDirectory(userId), userSerial);
+ enforceSerialNumber(getDataSystemCeDirectory(userId), userSerial);
}
}
@@ -117,13 +131,13 @@
// Clean up system data
if (Objects.equals(volumeUuid, StorageManager.UUID_PRIVATE_INTERNAL)) {
if ((flags & StorageManager.FLAG_STORAGE_DE) != 0) {
- FileUtils.deleteContentsAndDir(Environment.getUserSystemDirectory(userId));
- FileUtils.deleteContentsAndDir(Environment.getDataSystemDeDirectory(userId));
- FileUtils.deleteContentsAndDir(Environment.getDataMiscDeDirectory(userId));
+ FileUtils.deleteContentsAndDir(getUserSystemDirectory(userId));
+ FileUtils.deleteContentsAndDir(getDataSystemDeDirectory(userId));
+ FileUtils.deleteContentsAndDir(getDataMiscDeDirectory(userId));
}
if ((flags & StorageManager.FLAG_STORAGE_CE) != 0) {
- FileUtils.deleteContentsAndDir(Environment.getDataSystemCeDirectory(userId));
- FileUtils.deleteContentsAndDir(Environment.getDataMiscCeDirectory(userId));
+ FileUtils.deleteContentsAndDir(getDataSystemCeDirectory(userId));
+ FileUtils.deleteContentsAndDir(getDataMiscCeDirectory(userId));
}
}
@@ -136,4 +150,183 @@
}
}
+ /**
+ * Examine all users present on given mounted volume, and destroy data
+ * belonging to users that are no longer valid, or whose user ID has been
+ * recycled.
+ */
+ void reconcileUsers(String volumeUuid, List<UserInfo> validUsersList) {
+ final List<File> files = new ArrayList<>();
+ Collections.addAll(files, FileUtils
+ .listFilesOrEmpty(Environment.getDataUserDeDirectory(volumeUuid)));
+ Collections.addAll(files, FileUtils
+ .listFilesOrEmpty(Environment.getDataUserCeDirectory(volumeUuid)));
+ Collections.addAll(files, FileUtils
+ .listFilesOrEmpty(Environment.getDataSystemDeDirectory()));
+ Collections.addAll(files, FileUtils
+ .listFilesOrEmpty(Environment.getDataSystemCeDirectory()));
+ Collections.addAll(files, FileUtils
+ .listFilesOrEmpty(Environment.getDataMiscCeDirectory()));
+ reconcileUsers(volumeUuid, validUsersList, files);
+ }
+
+ @VisibleForTesting
+ void reconcileUsers(String volumeUuid, List<UserInfo> validUsersList, List<File> files) {
+ final int userCount = validUsersList.size();
+ SparseArray<UserInfo> users = new SparseArray<>(userCount);
+ for (int i = 0; i < userCount; i++) {
+ UserInfo user = validUsersList.get(i);
+ users.put(user.id, user);
+ }
+ for (File file : files) {
+ if (!file.isDirectory()) {
+ continue;
+ }
+
+ final int userId;
+ final UserInfo info;
+ try {
+ userId = Integer.parseInt(file.getName());
+ info = users.get(userId);
+ } catch (NumberFormatException e) {
+ Slog.w(TAG, "Invalid user directory " + file);
+ continue;
+ }
+
+ boolean destroyUser = false;
+ if (info == null) {
+ logCriticalInfo(Log.WARN, "Destroying user directory " + file
+ + " because no matching user was found");
+ destroyUser = true;
+ } else if (!mOnlyCore) {
+ try {
+ enforceSerialNumber(file, info.serialNumber);
+ } catch (IOException e) {
+ logCriticalInfo(Log.WARN, "Destroying user directory " + file
+ + " because we failed to enforce serial number: " + e);
+ destroyUser = true;
+ }
+ }
+
+ if (destroyUser) {
+ synchronized (mInstallLock) {
+ destroyUserDataLI(volumeUuid, userId,
+ StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE);
+ }
+ }
+ }
+ }
+
+ @VisibleForTesting
+ protected File getDataMiscCeDirectory(int userId) {
+ return Environment.getDataMiscCeDirectory(userId);
+ }
+
+ @VisibleForTesting
+ protected File getDataSystemCeDirectory(int userId) {
+ return Environment.getDataSystemCeDirectory(userId);
+ }
+
+ @VisibleForTesting
+ protected File getDataMiscDeDirectory(int userId) {
+ return Environment.getDataMiscDeDirectory(userId);
+ }
+
+ @VisibleForTesting
+ protected File getUserSystemDirectory(int userId) {
+ return Environment.getUserSystemDirectory(userId);
+ }
+
+ @VisibleForTesting
+ protected File getDataUserCeDirectory(String volumeUuid, int userId) {
+ return Environment.getDataUserCeDirectory(volumeUuid, userId);
+ }
+
+ @VisibleForTesting
+ protected File getDataSystemDeDirectory(int userId) {
+ return Environment.getDataSystemDeDirectory(userId);
+ }
+
+ @VisibleForTesting
+ protected File getDataUserDeDirectory(String volumeUuid, int userId) {
+ return Environment.getDataUserDeDirectory(volumeUuid, userId);
+ }
+
+ @VisibleForTesting
+ protected boolean isFileEncryptedEmulatedOnly() {
+ return StorageManager.isFileEncryptedEmulatedOnly();
+ }
+
+ /**
+ * Enforce that serial number stored in user directory inode matches the
+ * given expected value. Gracefully sets the serial number if currently
+ * undefined.
+ *
+ * @throws IOException when problem extracting serial number, or serial
+ * number is mismatched.
+ */
+ void enforceSerialNumber(File file, int serialNumber) throws IOException {
+ if (isFileEncryptedEmulatedOnly()) {
+ // When we're emulating FBE, the directory may have been chmod
+ // 000'ed, meaning we can't read the serial number to enforce it;
+ // instead of destroying the user, just log a warning.
+ Slog.w(TAG, "Device is emulating FBE; assuming current serial number is valid");
+ return;
+ }
+
+ final int foundSerial = getSerialNumber(file);
+ Slog.v(TAG, "Found " + file + " with serial number " + foundSerial);
+
+ if (foundSerial == -1) {
+ Slog.d(TAG, "Serial number missing on " + file + "; assuming current is valid");
+ try {
+ setSerialNumber(file, serialNumber);
+ } catch (IOException e) {
+ Slog.w(TAG, "Failed to set serial number on " + file, e);
+ }
+
+ } else if (foundSerial != serialNumber) {
+ throw new IOException("Found serial number " + foundSerial
+ + " doesn't match expected " + serialNumber);
+ }
+ }
+
+ /**
+ * Set serial number stored in user directory inode.
+ *
+ * @throws IOException if serial number was already set
+ */
+ private static void setSerialNumber(File file, int serialNumber) throws IOException {
+ try {
+ final byte[] buf = Integer.toString(serialNumber).getBytes(StandardCharsets.UTF_8);
+ Os.setxattr(file.getAbsolutePath(), XATTR_SERIAL, buf, OsConstants.XATTR_CREATE);
+ } catch (ErrnoException e) {
+ throw e.rethrowAsIOException();
+ }
+ }
+
+ /**
+ * Return serial number stored in user directory inode.
+ *
+ * @return parsed serial number, or -1 if not set
+ */
+ @VisibleForTesting
+ static int getSerialNumber(File file) throws IOException {
+ try {
+ final byte[] buf = Os.getxattr(file.getAbsolutePath(), XATTR_SERIAL);
+ final String serial = new String(buf);
+ try {
+ return Integer.parseInt(serial);
+ } catch (NumberFormatException e) {
+ throw new IOException("Bad serial number: " + serial);
+ }
+ } catch (ErrnoException e) {
+ if (e.errno == OsConstants.ENODATA) {
+ return -1;
+ } else {
+ throw e.rethrowAsIOException();
+ }
+ }
+ }
+
}
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 455d3e4..627fa54 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -218,8 +218,6 @@
static final int WRITE_USER_MSG = 1;
static final int WRITE_USER_DELAY = 2*1000; // 2 seconds
- private static final String XATTR_SERIAL = "user.serial";
-
// Tron counters
private static final String TRON_GUEST_CREATED = "users_guest_created";
private static final String TRON_USER_CREATED = "users_user_created";
@@ -3159,6 +3157,15 @@
}
/**
+ * Examine all users present on given mounted volume, and destroy data
+ * belonging to users that are no longer valid, or whose user ID has been
+ * recycled.
+ */
+ void reconcileUsers(String volumeUuid) {
+ mUserDataPreparer.reconcileUsers(volumeUuid, getUsers(true /* excludeDying */));
+ }
+
+ /**
* Make a note of the last started time of a user and do some cleanup.
* This is called with ActivityManagerService lock held.
* @param userId the user that was just foregrounded
@@ -3219,78 +3226,6 @@
return RESTRICTIONS_FILE_PREFIX + packageName + XML_SUFFIX;
}
- /**
- * Enforce that serial number stored in user directory inode matches the
- * given expected value. Gracefully sets the serial number if currently
- * undefined.
- *
- * @throws IOException when problem extracting serial number, or serial
- * number is mismatched.
- */
- public static void enforceSerialNumber(File file, int serialNumber) throws IOException {
- if (StorageManager.isFileEncryptedEmulatedOnly()) {
- // When we're emulating FBE, the directory may have been chmod
- // 000'ed, meaning we can't read the serial number to enforce it;
- // instead of destroying the user, just log a warning.
- Slog.w(LOG_TAG, "Device is emulating FBE; assuming current serial number is valid");
- return;
- }
-
- final int foundSerial = getSerialNumber(file);
- Slog.v(LOG_TAG, "Found " + file + " with serial number " + foundSerial);
-
- if (foundSerial == -1) {
- Slog.d(LOG_TAG, "Serial number missing on " + file + "; assuming current is valid");
- try {
- setSerialNumber(file, serialNumber);
- } catch (IOException e) {
- Slog.w(LOG_TAG, "Failed to set serial number on " + file, e);
- }
-
- } else if (foundSerial != serialNumber) {
- throw new IOException("Found serial number " + foundSerial
- + " doesn't match expected " + serialNumber);
- }
- }
-
- /**
- * Set serial number stored in user directory inode.
- *
- * @throws IOException if serial number was already set
- */
- private static void setSerialNumber(File file, int serialNumber)
- throws IOException {
- try {
- final byte[] buf = Integer.toString(serialNumber).getBytes(StandardCharsets.UTF_8);
- Os.setxattr(file.getAbsolutePath(), XATTR_SERIAL, buf, OsConstants.XATTR_CREATE);
- } catch (ErrnoException e) {
- throw e.rethrowAsIOException();
- }
- }
-
- /**
- * Return serial number stored in user directory inode.
- *
- * @return parsed serial number, or -1 if not set
- */
- private static int getSerialNumber(File file) throws IOException {
- try {
- final byte[] buf = Os.getxattr(file.getAbsolutePath(), XATTR_SERIAL);
- final String serial = new String(buf);
- try {
- return Integer.parseInt(serial);
- } catch (NumberFormatException e) {
- throw new IOException("Bad serial number: " + serial);
- }
- } catch (ErrnoException e) {
- if (e.errno == OsConstants.ENODATA) {
- return -1;
- } else {
- throw e.rethrowAsIOException();
- }
- }
- }
-
@Override
public void setSeedAccountData(int userId, String accountName, String accountType,
PersistableBundle accountOptions, boolean persist) {
diff --git a/services/core/java/com/android/server/policy/BarController.java b/services/core/java/com/android/server/policy/BarController.java
index 6edb4d2..7a28081 100644
--- a/services/core/java/com/android/server/policy/BarController.java
+++ b/services/core/java/com/android/server/policy/BarController.java
@@ -18,6 +18,7 @@
import android.app.StatusBarManager;
import android.os.Handler;
+import android.os.Message;
import android.os.SystemClock;
import android.util.Slog;
import android.view.View;
@@ -43,6 +44,8 @@
private static final int TRANSLUCENT_ANIMATION_DELAY_MS = 1000;
+ private static final int MSG_NAV_BAR_VISIBILITY_CHANGED = 1;
+
protected final String mTag;
private final int mTransientFlag;
private final int mUnhideFlag;
@@ -63,6 +66,8 @@
private boolean mSetUnHideFlagWhenNextTransparent;
private boolean mNoAnimationOnNextShow;
+ private OnBarVisibilityChangedListener mVisibilityChangeListener;
+
public BarController(String tag, int transientFlag, int unhideFlag, int translucentFlag,
int statusBarManagerId, int translucentWmFlag, int transparentFlag) {
mTag = "BarController." + tag;
@@ -72,7 +77,7 @@
mStatusBarManagerId = statusBarManagerId;
mTranslucentWmFlag = translucentWmFlag;
mTransparentFlag = transparentFlag;
- mHandler = new Handler();
+ mHandler = new BarHandler();
}
public void setWindow(WindowState win) {
@@ -153,9 +158,18 @@
mNoAnimationOnNextShow = false;
final int state = computeStateLw(wasVis, wasAnim, mWin, change);
final boolean stateChanged = updateStateLw(state);
+
+ if (change && (mVisibilityChangeListener != null)) {
+ mHandler.obtainMessage(MSG_NAV_BAR_VISIBILITY_CHANGED, show ? 1 : 0, 0).sendToTarget();
+ }
+
return change || stateChanged;
}
+ void setOnBarVisibilityChangedListener(OnBarVisibilityChangedListener listener) {
+ mVisibilityChangeListener = listener;
+ }
+
protected boolean skipAnimation() {
return false;
}
@@ -300,4 +314,22 @@
pw.println(transientBarStateToString(mTransientBarState));
}
}
+
+ private class BarHandler extends Handler {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_NAV_BAR_VISIBILITY_CHANGED:
+ final boolean visible = msg.arg1 != 0;
+ if (mVisibilityChangeListener != null) {
+ mVisibilityChangeListener.onBarVisibilityChanged(visible);
+ }
+ break;
+ }
+ }
+ }
+
+ interface OnBarVisibilityChangedListener {
+ void onBarVisibilityChanged(boolean visible);
+ }
}
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 180f6c9..c795676 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -990,6 +990,14 @@
WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION,
View.NAVIGATION_BAR_TRANSPARENT);
+ private final BarController.OnBarVisibilityChangedListener mNavBarVisibilityListener =
+ new BarController.OnBarVisibilityChangedListener() {
+ @Override
+ public void onBarVisibilityChanged(boolean visible) {
+ mAccessibilityManager.notifyAccessibilityButtonAvailabilityChanged(visible);
+ }
+ };
+
private ImmersiveModeConfirmation mImmersiveModeConfirmation;
private SystemGesturesPointerEventListener mSystemGestures;
@@ -2900,6 +2908,8 @@
}
mNavigationBar = win;
mNavigationBarController.setWindow(win);
+ mNavigationBarController.setOnBarVisibilityChangedListener(
+ mNavBarVisibilityListener);
if (DEBUG_LAYOUT) Slog.i(TAG, "NAVIGATION BAR: " + mNavigationBar);
break;
case TYPE_NAVIGATION_BAR_PANEL:
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 238866a..91a5f4f 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -517,9 +517,6 @@
private final ArrayList<PowerManagerInternal.LowPowerModeListener> mLowPowerModeListeners
= new ArrayList<PowerManagerInternal.LowPowerModeListener>();
- // True if brightness should be affected by twilight.
- private boolean mBrightnessUseTwilight;
-
// True if we are currently in VR Mode.
private boolean mIsVrModeEnabled;
@@ -735,9 +732,6 @@
resolver.registerContentObserver(Settings.Secure.getUriFor(
Settings.Secure.DOUBLE_TAP_TO_WAKE),
false, mSettingsObserver, UserHandle.USER_ALL);
- resolver.registerContentObserver(Settings.Secure.getUriFor(
- Secure.BRIGHTNESS_USE_TWILIGHT),
- false, mSettingsObserver, UserHandle.USER_ALL);
IVrManager vrManager =
(IVrManager) getBinderService(VrManagerService.VR_MANAGER_BINDER_SERVICE);
if (vrManager != null) {
@@ -878,9 +872,6 @@
Settings.System.SCREEN_BRIGHTNESS_MODE,
Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL, UserHandle.USER_CURRENT);
- mBrightnessUseTwilight = Settings.Secure.getIntForUser(resolver,
- Secure.BRIGHTNESS_USE_TWILIGHT, 0, UserHandle.USER_CURRENT) != 0;
-
final boolean lowPowerModeEnabled = Settings.Global.getInt(resolver,
Settings.Global.LOW_POWER_MODE, 0) != 0;
final boolean autoLowPowerModeConfigured = Settings.Global.getInt(resolver,
@@ -2254,7 +2245,6 @@
mDisplayPowerRequest.useProximitySensor = shouldUseProximitySensorLocked();
mDisplayPowerRequest.lowPowerMode = mLowPowerModeEnabled;
mDisplayPowerRequest.boostScreenBrightness = shouldBoostScreenBrightness();
- mDisplayPowerRequest.useTwilight = mBrightnessUseTwilight;
if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_DOZE) {
mDisplayPowerRequest.dozeScreenState = mDozeScreenStateOverrideFromDreamManager;
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
index fb0dd2a..b4467af 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
@@ -23,9 +23,6 @@
public interface StatusBarManagerInternal {
void setNotificationDelegate(NotificationDelegate delegate);
- void buzzBeepBlinked();
- void notificationLightPulse(int argb, int onMillis, int offMillis);
- void notificationLightOff();
void showScreenPinningRequest(int taskId);
void showAssistDisclosure();
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 7b7db0e..2dfe20a8 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -120,40 +120,6 @@
}
@Override
- public void buzzBeepBlinked() {
- if (mBar != null) {
- try {
- mBar.buzzBeepBlinked();
- } catch (RemoteException ex) {
- }
- }
- }
-
- @Override
- public void notificationLightPulse(int argb, int onMillis, int offMillis) {
- mNotificationLightOn = true;
- if (mBar != null) {
- try {
- mBar.notificationLightPulse(argb, onMillis, offMillis);
- } catch (RemoteException ex) {
- }
- }
- }
-
- @Override
- public void notificationLightOff() {
- if (mNotificationLightOn) {
- mNotificationLightOn = false;
- if (mBar != null) {
- try {
- mBar.notificationLightOff();
- } catch (RemoteException ex) {
- }
- }
- }
- }
-
- @Override
public void showScreenPinningRequest(int taskId) {
if (mBar != null) {
try {
diff --git a/services/core/jni/com_android_server_HardwarePropertiesManagerService.cpp b/services/core/jni/com_android_server_HardwarePropertiesManagerService.cpp
index 545b3d7..703518d 100644
--- a/services/core/jni/com_android_server_HardwarePropertiesManagerService.cpp
+++ b/services/core/jni/com_android_server_HardwarePropertiesManagerService.cpp
@@ -70,7 +70,7 @@
static void nativeInit(JNIEnv* env, jobject obj) {
// TODO(b/31632518)
if (gThermalModule == nullptr) {
- gThermalModule = IThermal::getService("thermal");
+ gThermalModule = IThermal::getService();
}
if (gThermalModule == nullptr) {
diff --git a/services/core/jni/com_android_server_SystemServer.cpp b/services/core/jni/com_android_server_SystemServer.cpp
index e46490b..3120af5 100644
--- a/services/core/jni/com_android_server_SystemServer.cpp
+++ b/services/core/jni/com_android_server_SystemServer.cpp
@@ -26,18 +26,11 @@
namespace android {
-static int start_sensor_service(void* /*unused*/) {
- SensorService::instantiate();
- return 0;
-}
-
static void android_server_SystemServer_startSensorService(JNIEnv* /* env */, jobject /* clazz */) {
char propBuf[PROPERTY_VALUE_MAX];
property_get("system_init.startsensorservice", propBuf, "1");
if (strcmp(propBuf, "1") == 0) {
- // Start the sensor service in a new thread
- createThreadEtc(start_sensor_service, nullptr,
- "StartSensorThread", PRIORITY_FOREGROUND);
+ SensorService::instantiate();
}
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 37f7966..003b6d0 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -60,6 +60,7 @@
import android.annotation.UserIdInt;
import android.app.Activity;
import android.app.ActivityManager;
+import android.app.ActivityManagerInternal;
import android.app.AlarmManager;
import android.app.AppGlobals;
import android.app.IActivityManager;
@@ -6151,8 +6152,12 @@
intent.setComponent(mOwners.getDeviceOwnerComponent());
intent.setDataAndType(bugreportUri, RemoteBugreportUtils.BUGREPORT_MIMETYPE);
intent.putExtra(DeviceAdminReceiver.EXTRA_BUGREPORT_HASH, bugreportHash);
- mContext.grantUriPermission(mOwners.getDeviceOwnerComponent().getPackageName(),
- bugreportUri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+
+ LocalServices.getService(ActivityManagerInternal.class)
+ .grantUriPermissionFromIntent(Process.SHELL_UID,
+ mOwners.getDeviceOwnerComponent().getPackageName(),
+ intent, mOwners.getDeviceOwnerUserId());
mContext.sendBroadcastAsUser(intent, UserHandle.of(mOwners.getDeviceOwnerUserId()));
}
} catch (FileNotFoundException e) {
@@ -6706,6 +6711,8 @@
policy.mDelegationMap.clear();
policy.mStatusBarDisabled = false;
policy.mUserProvisioningState = DevicePolicyManager.STATE_USER_UNMANAGED;
+ policy.mAffiliationIds.clear();
+ policy.mLockTaskPackages.clear();
saveSettingsLocked(userId);
try {
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index b911d2d..83e209d 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -125,8 +125,13 @@
public final class SystemServer {
private static final String TAG = "SystemServer";
+ // Tag for timing measurement of main thread.
+ private static final String SYSTEM_SERVER_TIMING_TAG = "SystemServerTiming";
+ // Tag for timing measurement of non-main asynchronous operations.
+ private static final String SYSTEM_SERVER_TIMING_ASYNC_TAG = SYSTEM_SERVER_TIMING_TAG + "Async";
+
private static final BootTimingsTraceLog BOOT_TIMINGS_TRACE_LOG
- = new BootTimingsTraceLog("SystemServerTiming", Trace.TRACE_TAG_SYSTEM_SERVER);
+ = new BootTimingsTraceLog(SYSTEM_SERVER_TIMING_TAG, Trace.TRACE_TAG_SYSTEM_SERVER);
private static final String ENCRYPTING_STATE = "trigger_restart_min_framework";
private static final String ENCRYPTED_STATE = "1";
@@ -149,6 +154,8 @@
"com.android.server.voiceinteraction.VoiceInteractionManagerService";
private static final String PRINT_MANAGER_SERVICE_CLASS =
"com.android.server.print.PrintManagerService";
+ private static final String COMPANION_DEVICE_MANAGER_SERVICE_CLASS =
+ "com.android.server.print.CompanionDeviceManagerService";
private static final String USB_SERVICE_CLASS =
"com.android.server.usb.UsbService$Lifecycle";
private static final String MIDI_SERVICE_CLASS =
@@ -227,8 +234,11 @@
private boolean mFirstBoot;
private final boolean mRuntimeRestart;
+ private static final String START_SENSOR_SERVICE = "StartSensorService";
+ private Future<?> mSensorServiceStart;
+
/**
- * Start the sensor service.
+ * Start the sensor service. This is a blocking call and can take time.
*/
private static native void startSensorService();
@@ -382,7 +392,7 @@
MetricsLogger.histogram(null, "boot_system_server_ready", uptimeMillis);
final int MAX_UPTIME_MILLIS = 60 * 1000;
if (uptimeMillis > MAX_UPTIME_MILLIS) {
- Slog.wtf("SystemServerTiming",
+ Slog.wtf(SYSTEM_SERVER_TIMING_TAG,
"SystemServer init took too long. uptimeMillis=" + uptimeMillis);
}
}
@@ -584,9 +594,15 @@
// The sensor service needs access to package manager service, app ops
// service, and permissions service, therefore we start it after them.
- traceBeginAndSlog("StartSensorService");
- startSensorService();
- traceEnd();
+ // Start sensor service in a separate thread. Completion should be checked
+ // before using it.
+ mSensorServiceStart = SystemServerInitThreadPool.get().submit(() -> {
+ BootTimingsTraceLog traceLog = new BootTimingsTraceLog(
+ SYSTEM_SERVER_TIMING_ASYNC_TAG, Trace.TRACE_TAG_SYSTEM_SERVER);
+ traceLog.traceBegin(START_SENSOR_SERVICE);
+ startSensorService();
+ traceLog.traceEnd();
+ }, START_SENSOR_SERVICE);
}
/**
@@ -742,6 +758,9 @@
traceEnd();
traceBeginAndSlog("StartWindowManagerService");
+ // WMS needs sensor service ready
+ ConcurrentUtils.waitForFutureNoInterrupt(mSensorServiceStart, START_SENSOR_SERVICE);
+ mSensorServiceStart = null;
wm = WindowManagerService.main(context, inputManager,
mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
!mFirstBoot, mOnlyCore, new PhoneWindowManager());
@@ -1333,6 +1352,10 @@
traceEnd();
}
+ traceBeginAndSlog("StartCompanionDeviceManager");
+ mSystemServiceManager.startService(COMPANION_DEVICE_MANAGER_SERVICE_CLASS);
+ traceEnd();
+
traceBeginAndSlog("StartRestrictionManager");
mSystemServiceManager.startService(RestrictionsManagerService.class);
traceEnd();
@@ -1590,7 +1613,7 @@
webviewPrep = SystemServerInitThreadPool.get().submit(() -> {
Slog.i(TAG, WEBVIEW_PREPARATION);
BootTimingsTraceLog traceLog = new BootTimingsTraceLog(
- "SystemServerTiming", Trace.TRACE_TAG_SYSTEM_SERVER);
+ SYSTEM_SERVER_TIMING_ASYNC_TAG, Trace.TRACE_TAG_SYSTEM_SERVER);
traceLog.traceBegin(WEBVIEW_PREPARATION);
mWebViewUpdateService.prepareWebViewInSystemServer();
traceLog.traceEnd();
@@ -1651,13 +1674,13 @@
Watchdog.getInstance().start();
traceEnd();
- if (webviewPrep != null) {
- ConcurrentUtils.waitForFutureNoInterrupt(webviewPrep, WEBVIEW_PREPARATION);
- }
-
// It is now okay to let the various system services start their
// third party code...
traceBeginAndSlog("PhaseThirdPartyAppsCanStart");
+ // confirm webview completion before starting 3rd party
+ if (webviewPrep != null) {
+ ConcurrentUtils.waitForFutureNoInterrupt(webviewPrep, WEBVIEW_PREPARATION);
+ }
mSystemServiceManager.startBootPhase(
SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);
traceEnd();
diff --git a/services/print/java/com/android/server/print/CompanionDeviceManagerService.java b/services/print/java/com/android/server/print/CompanionDeviceManagerService.java
new file mode 100644
index 0000000..9824c1d
--- /dev/null
+++ b/services/print/java/com/android/server/print/CompanionDeviceManagerService.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2017 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.print;
+
+import static com.android.internal.util.Preconditions.checkNotNull;
+
+import android.app.PendingIntent;
+import android.companion.AssociationRequest;
+import android.companion.ICompanionDeviceManager;
+import android.companion.ICompanionDeviceManagerService;
+import android.companion.IOnAssociateCallback;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
+
+import com.android.server.SystemService;
+
+//TODO move to own package!
+/** @hide */
+public class CompanionDeviceManagerService extends SystemService {
+
+ private static final ComponentName SERVICE_TO_BIND_TO = ComponentName.createRelative(
+ "com.android.companiondevicemanager", ".DeviceDiscoveryService");
+
+ private static final boolean DEBUG = false;
+ private static final String LOG_TAG = "CompanionDeviceManagerService";
+
+ private final CompanionDeviceManagerImpl mImpl;
+
+ public CompanionDeviceManagerService(Context context) {
+ super(context);
+ mImpl = new CompanionDeviceManagerImpl();
+ }
+
+ @Override
+ public void onStart() {
+ publishBinderService(Context.COMPANION_DEVICE_SERVICE, mImpl);
+ }
+
+ class CompanionDeviceManagerImpl extends ICompanionDeviceManager.Stub {
+
+ @Override
+ public void associate(
+ AssociationRequest request,
+ IOnAssociateCallback callback,
+ String callingPackage) throws RemoteException {
+ if (DEBUG) {
+ Log.i(LOG_TAG, "associate(request = " + request + ", callback = " + callback
+ + ", callingPackage = " + callingPackage + ")");
+ }
+ checkNotNull(request);
+ checkNotNull(callback);
+ final long callingIdentity = Binder.clearCallingIdentity();
+ try {
+ //TODO bindServiceAsUser
+ getContext().bindService(
+ new Intent().setComponent(SERVICE_TO_BIND_TO),
+ getServiceConnection(request, callback, callingPackage),
+ Context.BIND_AUTO_CREATE);
+ } finally {
+ Binder.restoreCallingIdentity(callingIdentity);
+ }
+ }
+ }
+
+ private ServiceConnection getServiceConnection(
+ final AssociationRequest<?> request,
+ final IOnAssociateCallback callback,
+ final String callingPackage) {
+ return new ServiceConnection() {
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ if (DEBUG) {
+ Log.i(LOG_TAG,
+ "onServiceConnected(name = " + name + ", service = "
+ + service + ")");
+ }
+ try {
+ ICompanionDeviceManagerService.Stub
+ .asInterface(service)
+ .startDiscovery(
+ request,
+ getCallback(callingPackage, callback),
+ callingPackage);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ if (DEBUG) Log.i(LOG_TAG, "onServiceDisconnected(name = " + name + ")");
+ }
+ };
+ }
+
+ private IOnAssociateCallback.Stub getCallback(
+ String callingPackage,
+ IOnAssociateCallback propagateTo) {
+ return new IOnAssociateCallback.Stub() {
+
+ @Override
+ public void onSuccess(PendingIntent launcher)
+ throws RemoteException {
+ if (DEBUG) Log.i(LOG_TAG, "onSuccess(launcher = " + launcher + ")");
+ recordSpecialPriviledgesForPackage(callingPackage);
+ propagateTo.onSuccess(launcher);
+ }
+
+ @Override
+ public void onFailure(CharSequence reason) throws RemoteException {
+ if (DEBUG) Log.i(LOG_TAG, "onFailure()");
+ propagateTo.onFailure(reason);
+ }
+ };
+ }
+
+ void recordSpecialPriviledgesForPackage(String priviledgedPackage) {
+ //TODO Show dialog before recording notification access
+// final SettingStringHelper setting =
+// new SettingStringHelper(
+// getContext().getContentResolver(),
+// Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
+// Binder.getCallingUid());
+// setting.write(ColonDelimitedSet.OfStrings.add(setting.read(), priviledgedPackage));
+ }
+}
diff --git a/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java b/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java
index f30c466..f943ee2c 100644
--- a/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java
+++ b/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java
@@ -541,6 +541,8 @@
}
private void stopDemoMode() {
+ mDeviceInDemoMode = false;
+ mIsCarrierDemoMode = false;
mPreloadAppsInstaller = null;
mCameraIdsWithFlash = null;
mInjector.destroyWakeLock();
diff --git a/services/tests/notification/src/com/android/server/notification/NotificationComparatorTest.java b/services/tests/notification/src/com/android/server/notification/NotificationComparatorTest.java
index aa08b41..064ab0a 100644
--- a/services/tests/notification/src/com/android/server/notification/NotificationComparatorTest.java
+++ b/services/tests/notification/src/com/android/server/notification/NotificationComparatorTest.java
@@ -112,6 +112,7 @@
Notification n2 = new Notification.Builder(mContext)
.setCategory(Notification.CATEGORY_CALL)
.setFlag(Notification.FLAG_FOREGROUND_SERVICE, true)
+ .setColorized(true /* colorized */)
.build();
mRecordHighCall = new NotificationRecord(mContext, new StatusBarNotification(callPkg,
callPkg, 1, "highcall", callUid, callUid, n2,
@@ -186,10 +187,10 @@
final List<NotificationRecord> expected = new ArrayList<>();
expected.add(mRecordHighCall);
expected.add(mRecordDefaultMedia);
- expected.add(mRecordStarredContact);
- expected.add(mRecordContact);
expected.add(mRecordInlineReply);
expected.add(mRecordSms);
+ expected.add(mRecordStarredContact);
+ expected.add(mRecordContact);
expected.add(mRecordEmail);
expected.add(mRecordUrgent);
expected.add(mRecordCheater);
@@ -207,14 +208,19 @@
@Test
public void testMessaging() throws Exception {
NotificationComparator comp = new NotificationComparator(mContext);
- assertTrue(comp.isImportantMessaging(mRecordStarredContact));
- assertTrue(comp.isImportantMessaging(mRecordContact));
assertTrue(comp.isImportantMessaging(mRecordInlineReply));
assertTrue(comp.isImportantMessaging(mRecordSms));
assertFalse(comp.isImportantMessaging(mRecordEmail));
assertFalse(comp.isImportantMessaging(mRecordCheater));
}
+ @Test
+ public void testPeople() throws Exception {
+ NotificationComparator comp = new NotificationComparator(mContext);
+ assertTrue(comp.isImportantPeople(mRecordStarredContact));
+ assertTrue(comp.isImportantPeople(mRecordContact));
+ }
+
private NotificationChannel getDefaultChannel() {
return new NotificationChannel(NotificationChannel.DEFAULT_CHANNEL_ID, "name",
NotificationManager.IMPORTANCE_LOW);
diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
index 9645916..3f34d4f 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
@@ -76,6 +76,7 @@
import android.net.INetworkPolicyListener;
import android.net.INetworkStatsService;
import android.net.LinkProperties;
+import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.net.NetworkInfo.DetailedState;
import android.net.NetworkPolicy;
@@ -975,7 +976,8 @@
info.setDetailedState(DetailedState.CONNECTED, null, null);
final LinkProperties prop = new LinkProperties();
prop.setInterfaceName(TEST_IFACE);
- return new NetworkState(info, prop, null, null, null, TEST_SSID);
+ final NetworkCapabilities networkCapabilities = new NetworkCapabilities();
+ return new NetworkState(info, prop, networkCapabilities, null, null, TEST_SSID);
}
private void expectCurrentTime() throws Exception {
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index 7df638c..6fb65d5 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -2089,9 +2089,19 @@
assertTrue(dpm.getAffiliationIds(admin2).isEmpty());
assertFalse(dpm.isAffiliatedUser());
+ // Set affiliation ids again, then clear PO to check that the user becomes unaffiliated
+ dpm.setAffiliationIds(admin2, userAffiliationIds);
+ assertTrue(dpm.isAffiliatedUser());
+ dpm.clearProfileOwner(admin2);
+ assertFalse(dpm.isAffiliatedUser());
+
// Check that the system user remains affiliated.
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
assertTrue(dpm.isAffiliatedUser());
+
+ // Clear the device owner - the user becomes unaffiliated.
+ clearDeviceOwner();
+ assertFalse(dpm.isAffiliatedUser());
}
public void testGetUserProvisioningState_defaultResult() {
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserDataPreparerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserDataPreparerTest.java
new file mode 100644
index 0000000..7a676e25
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/pm/UserDataPreparerTest.java
@@ -0,0 +1,273 @@
+/*
+ * Copyright (C) 2017 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.pm;
+
+import android.content.Context;
+import android.content.pm.UserInfo;
+import android.os.FileUtils;
+import android.os.storage.StorageManager;
+import android.os.storage.VolumeInfo;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.util.Arrays;
+import java.util.Collections;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Matchers.isNull;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+/**
+ * <p>Run with:<pre>
+ * m FrameworksServicesTests &&
+ * adb install \
+ * -r out/target/product/hammerhead/data/app/FrameworksServicesTests/FrameworksServicesTests.apk &&
+ * adb shell am instrument -e class com.android.server.pm.UserDataPreparerTest \
+ * -w com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
+ * </pre>
+ */
+@RunWith(AndroidJUnit4.class)
+@Presubmit
+@SmallTest
+public class UserDataPreparerTest {
+
+ private static final int TEST_USER_SERIAL = 1000;
+ private static final int TEST_USER_ID = 10;
+
+ private TestUserDataPreparer mUserDataPreparer;
+
+ @Mock
+ private StorageManager mStorageManagerMock;
+
+ @Mock
+ private Context mContextMock;
+
+ @Mock
+ private Installer mInstaller;
+
+ private Object mInstallLock;
+
+ @Before
+ public void setup() {
+ Context ctx = InstrumentationRegistry.getContext();
+ FileUtils.deleteContents(ctx.getCacheDir());
+ mInstallLock = new Object();
+ MockitoAnnotations.initMocks(this);
+ mUserDataPreparer = new TestUserDataPreparer(mInstaller, mInstallLock, mContextMock, false,
+ ctx.getCacheDir());
+ when(mContextMock.getSystemServiceName(StorageManager.class))
+ .thenReturn(Context.STORAGE_SERVICE);
+ when(mContextMock.getSystemService(eq(Context.STORAGE_SERVICE)))
+ .thenReturn(mStorageManagerMock);
+ VolumeInfo testVolume = new VolumeInfo("testuuid", VolumeInfo.TYPE_PRIVATE, null, null);
+ when(mStorageManagerMock.getWritablePrivateVolumes()).thenReturn(Arrays.asList(testVolume));
+ }
+
+ @Test
+ public void testPrepareUserData_De() throws Exception {
+ File userDeDir = mUserDataPreparer.getDataUserDeDirectory(null, TEST_USER_ID);
+ userDeDir.mkdirs();
+ File systemDeDir = mUserDataPreparer.getDataSystemDeDirectory(TEST_USER_ID);
+ systemDeDir.mkdirs();
+ mUserDataPreparer
+ .prepareUserData(TEST_USER_ID, TEST_USER_SERIAL, StorageManager.FLAG_STORAGE_DE);
+ verify(mStorageManagerMock).prepareUserStorage(isNull(String.class), eq(TEST_USER_ID),
+ eq(TEST_USER_SERIAL), eq(StorageManager.FLAG_STORAGE_DE));
+ verify(mInstaller).createUserData(isNull(String.class), eq(TEST_USER_ID),
+ eq(TEST_USER_SERIAL), eq(StorageManager.FLAG_STORAGE_DE));
+ int serialNumber = UserDataPreparer.getSerialNumber(userDeDir);
+ assertEquals(TEST_USER_SERIAL, serialNumber);
+ serialNumber = UserDataPreparer.getSerialNumber(systemDeDir);
+ assertEquals(TEST_USER_SERIAL, serialNumber);
+ }
+
+ @Test
+ public void testPrepareUserData_Ce() throws Exception {
+ File userCeDir = mUserDataPreparer.getDataUserCeDirectory(null, TEST_USER_ID);
+ userCeDir.mkdirs();
+ File systemCeDir = mUserDataPreparer.getDataSystemCeDirectory(TEST_USER_ID);
+ systemCeDir.mkdirs();
+ mUserDataPreparer
+ .prepareUserData(TEST_USER_ID, TEST_USER_SERIAL, StorageManager.FLAG_STORAGE_CE);
+ verify(mStorageManagerMock).prepareUserStorage(isNull(String.class), eq(TEST_USER_ID),
+ eq(TEST_USER_SERIAL), eq(StorageManager.FLAG_STORAGE_CE));
+ verify(mInstaller).createUserData(isNull(String.class), eq(TEST_USER_ID),
+ eq(TEST_USER_SERIAL), eq(StorageManager.FLAG_STORAGE_CE));
+ int serialNumber = UserDataPreparer.getSerialNumber(userCeDir);
+ assertEquals(TEST_USER_SERIAL, serialNumber);
+ serialNumber = UserDataPreparer.getSerialNumber(systemCeDir);
+ assertEquals(TEST_USER_SERIAL, serialNumber);
+ }
+
+ @Test
+ public void testDestroyUserData() throws Exception {
+ // Add file in CE
+ File systemCeDir = mUserDataPreparer.getDataSystemCeDirectory(TEST_USER_ID);
+ systemCeDir.mkdirs();
+ File ceFile = new File(systemCeDir, "file");
+ writeFile(ceFile, "-----" );
+ testDestroyUserData_De();
+ // CE directory should be preserved
+ assertEquals(Collections.singletonList(ceFile), Arrays.asList(FileUtils.listFilesOrEmpty(
+ systemCeDir)));
+
+ testDestroyUserData_Ce();
+
+ // Verify that testDir is empty
+ assertEquals(Collections.emptyList(), Arrays.asList(FileUtils.listFilesOrEmpty(
+ mUserDataPreparer.testDir)));
+ }
+
+ @Test
+ public void testDestroyUserData_De() throws Exception {
+ File systemDir = mUserDataPreparer.getUserSystemDirectory(TEST_USER_ID);
+ systemDir.mkdirs();
+ writeFile(new File(systemDir, "file"), "-----" );
+ File systemDeDir = mUserDataPreparer.getDataSystemDeDirectory(TEST_USER_ID);
+ systemDeDir.mkdirs();
+ writeFile(new File(systemDeDir, "file"), "-----" );
+ File miscDeDir = mUserDataPreparer.getDataMiscDeDirectory(TEST_USER_ID);
+ miscDeDir.mkdirs();
+ writeFile(new File(miscDeDir, "file"), "-----" );
+
+ mUserDataPreparer.destroyUserData(TEST_USER_ID, StorageManager.FLAG_STORAGE_DE);
+
+ verify(mInstaller).destroyUserData(isNull(String.class), eq(TEST_USER_ID),
+ eq(StorageManager.FLAG_STORAGE_DE));
+ verify(mStorageManagerMock).destroyUserStorage(isNull(String.class), eq(TEST_USER_ID),
+ eq(StorageManager.FLAG_STORAGE_DE));
+
+ assertEquals(Collections.emptyList(), Arrays.asList(FileUtils.listFilesOrEmpty(systemDir)));
+ assertEquals(Collections.emptyList(), Arrays.asList(FileUtils.listFilesOrEmpty(
+ systemDeDir)));
+ assertEquals(Collections.emptyList(), Arrays.asList(FileUtils.listFilesOrEmpty(
+ miscDeDir)));
+ }
+
+ @Test
+ public void testDestroyUserData_Ce() throws Exception {
+ File systemCeDir = mUserDataPreparer.getDataSystemCeDirectory(TEST_USER_ID);
+ systemCeDir.mkdirs();
+ writeFile(new File(systemCeDir, "file"), "-----" );
+ File miscCeDir = mUserDataPreparer.getDataMiscCeDirectory(TEST_USER_ID);
+ miscCeDir.mkdirs();
+ writeFile(new File(miscCeDir, "file"), "-----" );
+
+ mUserDataPreparer.destroyUserData(TEST_USER_ID, StorageManager.FLAG_STORAGE_CE);
+
+ verify(mInstaller).destroyUserData(isNull(String.class), eq(TEST_USER_ID),
+ eq(StorageManager.FLAG_STORAGE_CE));
+ verify(mStorageManagerMock).destroyUserStorage(isNull(String.class), eq(TEST_USER_ID),
+ eq(StorageManager.FLAG_STORAGE_CE));
+
+ assertEquals(Collections.emptyList(), Arrays.asList(FileUtils.listFilesOrEmpty(
+ systemCeDir)));
+ assertEquals(Collections.emptyList(), Arrays.asList(FileUtils.listFilesOrEmpty(
+ miscCeDir)));
+ }
+
+ @Test
+ public void testReconcileUsers() throws Exception {
+ UserInfo u1 = new UserInfo(1, "u1", 0);
+ UserInfo u2 = new UserInfo(2, "u2", 0);
+ File testDir = mUserDataPreparer.testDir;
+ File dir1 = new File(testDir, "1");
+ dir1.mkdirs();
+ File dir2 = new File(testDir, "2");
+ dir2.mkdirs();
+ File dir3 = new File(testDir, "3");
+ dir3.mkdirs();
+
+ mUserDataPreparer
+ .reconcileUsers(StorageManager.UUID_PRIVATE_INTERNAL, Arrays.asList(u1, u2),
+ Arrays.asList(dir1, dir2, dir3));
+ // Verify that user 3 data is removed
+ verify(mInstaller).destroyUserData(isNull(String.class), eq(3),
+ eq(StorageManager.FLAG_STORAGE_DE|StorageManager.FLAG_STORAGE_CE));
+ }
+
+ private static void writeFile(File file, String content) throws IOException {
+ try (FileOutputStream os = new FileOutputStream(file)) {
+ os.write(content.getBytes(Charset.defaultCharset()));
+ }
+ }
+
+ private static class TestUserDataPreparer extends UserDataPreparer {
+ File testDir;
+
+ TestUserDataPreparer(Installer installer, Object installLock, Context context,
+ boolean onlyCore, File testDir) {
+ super(installer, installLock, context, onlyCore);
+ this.testDir = testDir;
+ }
+
+ @Override
+ protected File getDataMiscCeDirectory(int userId) {
+ return new File(testDir, "misc_ce_" + userId);
+ }
+
+ @Override
+ protected File getDataSystemCeDirectory(int userId) {
+ return new File(testDir, "system_ce_" + userId);
+ }
+
+ @Override
+ protected File getDataMiscDeDirectory(int userId) {
+ return new File(testDir, "misc_de_" + userId);
+ }
+
+ @Override
+ protected File getUserSystemDirectory(int userId) {
+ return new File(testDir, "user_system_" + userId);
+ }
+
+ @Override
+ protected File getDataUserCeDirectory(String volumeUuid, int userId) {
+ return new File(testDir, "user_ce_" + userId);
+ }
+
+ @Override
+ protected File getDataSystemDeDirectory(int userId) {
+ return new File(testDir, "system_de_" + userId);
+ }
+
+ @Override
+ protected File getDataUserDeDirectory(String volumeUuid, int userId) {
+ return new File(testDir, "user_de_" + userId);
+ }
+
+ @Override
+ protected boolean isFileEncryptedEmulatedOnly() {
+ return false;
+ }
+ }
+
+}
diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java
index d0ccd55..6e10029 100644
--- a/telecomm/java/android/telecom/ConnectionService.java
+++ b/telecomm/java/android/telecom/ConnectionService.java
@@ -98,6 +98,7 @@
private static final String SESSION_ADD_CS_ADAPTER = "CS.aCSA";
private static final String SESSION_REMOVE_CS_ADAPTER = "CS.rCSA";
private static final String SESSION_CREATE_CONN = "CS.crCo";
+ private static final String SESSION_CREATE_CONN_FAILED = "CS.crCoF";
private static final String SESSION_ABORT = "CS.ab";
private static final String SESSION_ANSWER = "CS.an";
private static final String SESSION_ANSWER_VIDEO = "CS.anV";
@@ -142,6 +143,7 @@
private static final int MSG_PULL_EXTERNAL_CALL = 22;
private static final int MSG_SEND_CALL_EVENT = 23;
private static final int MSG_ON_EXTRAS_CHANGED = 24;
+ private static final int MSG_CREATE_CONNECTION_FAILED = 25;
private static Connection sNullConnection;
@@ -211,6 +213,25 @@
}
@Override
+ public void createConnectionFailed(
+ String callId,
+ ConnectionRequest request,
+ boolean isIncoming,
+ Session.Info sessionInfo) {
+ Log.startSession(sessionInfo, SESSION_CREATE_CONN_FAILED);
+ try {
+ SomeArgs args = SomeArgs.obtain();
+ args.arg1 = callId;
+ args.arg2 = request;
+ args.arg3 = Log.createSubsession();
+ args.argi1 = isIncoming ? 1 : 0;
+ mHandler.obtainMessage(MSG_CREATE_CONNECTION_FAILED, args).sendToTarget();
+ } finally {
+ Log.endSession();
+ }
+ }
+
+ @Override
public void abort(String callId, Session.Info sessionInfo) {
Log.startSession(sessionInfo, SESSION_ABORT);
try {
@@ -552,6 +573,35 @@
}
break;
}
+ case MSG_CREATE_CONNECTION_FAILED: {
+ SomeArgs args = (SomeArgs) msg.obj;
+ Log.continueSession((Session) args.arg3, SESSION_HANDLER +
+ SESSION_CREATE_CONN_FAILED);
+ try {
+ final String id = (String) args.arg1;
+ final ConnectionRequest request = (ConnectionRequest) args.arg2;
+ final boolean isIncoming = args.argi1 == 1;
+ if (!mAreAccountsInitialized) {
+ Log.d(this, "Enqueueing pre-init request %s", id);
+ mPreInitializationConnectionRequests.add(
+ new android.telecom.Logging.Runnable(
+ SESSION_HANDLER + SESSION_CREATE_CONN_FAILED + ".pICR",
+ null /*lock*/) {
+ @Override
+ public void loggedRun() {
+ createConnectionFailed(id, request, isIncoming);
+ }
+ }.prepare());
+ } else {
+ Log.i(this, "createConnectionFailed %s", id);
+ createConnectionFailed(id, request, isIncoming);
+ }
+ } finally {
+ args.recycle();
+ Log.endSession();
+ }
+ break;
+ }
case MSG_ABORT: {
SomeArgs args = (SomeArgs) msg.obj;
Log.continueSession((Session) args.arg2, SESSION_HANDLER + SESSION_ABORT);
@@ -1175,6 +1225,17 @@
}
}
+ private void createConnectionFailed(final String callId, final ConnectionRequest request,
+ boolean isIncoming) {
+
+ Log.i(this, "createConnectionFailed %s", callId);
+ if (isIncoming) {
+ onCreateIncomingConnectionFailed(request);
+ } else {
+ onCreateOutgoingConnectionFailed(request);
+ }
+ }
+
private void abort(String callId) {
Log.d(this, "abort %s", callId);
findConnectionForAction(callId, "abort").onAbort();
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index ba7b6a1..96070b8 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -1517,6 +1517,10 @@
* otherwise.
*/
public boolean isIncomingCallPermitted(PhoneAccountHandle phoneAccountHandle) {
+ if (phoneAccountHandle == null) {
+ return false;
+ }
+
ITelecomService service = getTelecomService();
if (service != null) {
try {
diff --git a/telecomm/java/com/android/internal/telecom/IConnectionService.aidl b/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
index 8a27675..20feba7 100644
--- a/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
+++ b/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
@@ -46,6 +46,9 @@
boolean isUnknown,
in Session.Info sessionInfo);
+ void createConnectionFailed(String callId, in ConnectionRequest request, boolean isIncoming,
+ in Session.Info sessionInfo);
+
void abort(String callId, in Session.Info sessionInfo);
void answerVideo(String callId, int videoState, in Session.Info sessionInfo);